linux-2.6.22.1-001-lzma-vmlinuz.00.patch 712 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856
  1. diff -rduNp linux-2.6.22.1.oorig/.miniconfig linux-2.6.22.1/.miniconfig
  2. --- linux-2.6.22.1.oorig/.miniconfig 1970-01-01 01:00:00.000000000 +0100
  3. +++ linux-2.6.22.1/.miniconfig 2007-07-24 14:17:46.000000000 +0200
  4. @@ -0,0 +1,89 @@
  5. +#make allnoconfig KCONFIG_ALLCONFIG=miniconfig
  6. +CONFIG_X86_32=y
  7. +CONFIG_CLOCKSOURCE_WATCHDOG=y
  8. +CONFIG_LOCKDEP_SUPPORT=y
  9. +CONFIG_SEMAPHORE_SLEEPERS=y
  10. +CONFIG_MMU=y
  11. +CONFIG_GENERIC_ISA_DMA=y
  12. +CONFIG_GENERIC_HWEIGHT=y
  13. +CONFIG_DMI=y
  14. +CONFIG_INIT_ENV_ARG_LIMIT=32
  15. +CONFIG_IKCONFIG=y
  16. +CONFIG_IKCONFIG_PROC=y
  17. +CONFIG_SYSFS_DEPRECATED=y
  18. +CONFIG_BLK_DEV_INITRD=y
  19. +CONFIG_SYSCTL=y
  20. +CONFIG_EMBEDDED=y
  21. +CONFIG_PRINTK=y
  22. +CONFIG_BASE_SMALL=1
  23. +CONFIG_BLOCK=y
  24. +CONFIG_IOSCHED_NOOP=y
  25. +CONFIG_DEFAULT_IOSCHED="noop"
  26. +CONFIG_X86_GENERIC=y
  27. +CONFIG_X86_L1_CACHE_SHIFT=7
  28. +CONFIG_GENERIC_CALIBRATE_DELAY=y
  29. +CONFIG_X86_WP_WORKS_OK=y
  30. +CONFIG_X86_BSWAP=y
  31. +CONFIG_X86_CMPXCHG64=y
  32. +CONFIG_X86_INTEL_USERCOPY=y
  33. +CONFIG_X86_TSC=y
  34. +CONFIG_PREEMPT_NONE=y
  35. +CONFIG_VM86=y
  36. +CONFIG_HIGHMEM=y
  37. +CONFIG_FLATMEM=y
  38. +CONFIG_MTRR=y
  39. +CONFIG_HZ_250=y
  40. +CONFIG_PHYSICAL_ALIGN=0x100000
  41. +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
  42. +CONFIG_PM=y
  43. +CONFIG_ACPI=y
  44. +CONFIG_ACPI_SLEEP=y
  45. +CONFIG_ACPI_BLACKLIST_YEAR=0
  46. +CONFIG_ACPI_EC=y
  47. +CONFIG_ACPI_SYSTEM=y
  48. +CONFIG_PCI=y
  49. +CONFIG_PCI_GOANY=y
  50. +CONFIG_PCI_DIRECT=y
  51. +CONFIG_BINFMT_ELF=y
  52. +CONFIG_STANDALONE=y
  53. +CONFIG_BLK_DEV_LOOP=y
  54. +CONFIG_IDE=y
  55. +CONFIG_IDE_MAX_HWIFS=2
  56. +CONFIG_BLK_DEV_IDE=y
  57. +CONFIG_BLK_DEV_IDEDISK=y
  58. +CONFIG_IDEDISK_MULTI_MODE=y
  59. +CONFIG_BLK_DEV_IDECD=y
  60. +CONFIG_IDE_GENERIC=y
  61. +CONFIG_INPUT_MOUSEDEV=y
  62. +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
  63. +CONFIG_INPUT_KEYBOARD=y
  64. +CONFIG_KEYBOARD_ATKBD=y
  65. +CONFIG_SERIO=y
  66. +CONFIG_VT=y
  67. +CONFIG_VT_CONSOLE=y
  68. +CONFIG_UNIX98_PTYS=y
  69. +CONFIG_VGA_CONSOLE=y
  70. +CONFIG_USB_ARCH_HAS_HCD=y
  71. +CONFIG_USB_ARCH_HAS_EHCI=y
  72. +CONFIG_EXT2_FS=y
  73. +CONFIG_DNOTIFY=y
  74. +CONFIG_ISO9660_FS=y
  75. +CONFIG_FAT_FS=y
  76. +CONFIG_VFAT_FS=y
  77. +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
  78. +CONFIG_PROC_FS=y
  79. +CONFIG_PROC_SYSCTL=y
  80. +CONFIG_SYSFS=y
  81. +CONFIG_RAMFS=y
  82. +CONFIG_SQUASHFS=y
  83. +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
  84. +CONFIG_MSDOS_PARTITION=y
  85. +CONFIG_NLS_DEFAULT="iso8859-1"
  86. +CONFIG_AUFS=y
  87. +CONFIG_AUFS_FAKE_DM=y
  88. +CONFIG_EARLY_PRINTK=y
  89. +CONFIG_DOUBLEFAULT=y
  90. +CONFIG_ZLIB_INFLATE=y
  91. +CONFIG_HAS_IOPORT=y
  92. +CONFIG_GENERIC_IRQ_PROBE=y
  93. +CONFIG_KTIME_SCALAR=y
  94. diff -rduNp linux-2.6.22.1.oorig/Makefile linux-2.6.22.1/Makefile
  95. --- linux-2.6.22.1.oorig/Makefile 2007-07-10 20:56:30.000000000 +0200
  96. +++ linux-2.6.22.1/Makefile 2007-07-24 14:17:46.000000000 +0200
  97. @@ -188,7 +188,7 @@ CROSS_COMPILE ?=
  98. # Architecture as present in compile.h
  99. UTS_MACHINE := $(ARCH)
  100. -KCONFIG_CONFIG ?= .config
  101. +KCONFIG_CONFIG ?= .miniconfig
  102. # SHELL used by kbuild
  103. CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
  104. diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.c linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.c
  105. --- linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
  106. +++ linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.c 2007-07-24 14:17:46.000000000 +0200
  107. @@ -0,0 +1,588 @@
  108. +/*
  109. + LzmaDecode.c
  110. + LZMA Decoder (optimized for Speed version)
  111. +
  112. + LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
  113. + http://www.7-zip.org/
  114. +
  115. + LZMA SDK is licensed under two licenses:
  116. + 1) GNU Lesser General Public License (GNU LGPL)
  117. + 2) Common Public License (CPL)
  118. + It means that you can select one of these two licenses and
  119. + follow rules of that license.
  120. +
  121. + SPECIAL EXCEPTION:
  122. + Igor Pavlov, as the author of this Code, expressly permits you to
  123. + statically or dynamically link your Code (or bind by name) to the
  124. + interfaces of this file without subjecting your linked Code to the
  125. + terms of the CPL or GNU LGPL. Any modifications or additions
  126. + to this file, however, are subject to the LGPL or CPL terms.
  127. +*/
  128. +
  129. +#include "LzmaDecode.h"
  130. +
  131. +#ifndef Byte
  132. +#define Byte unsigned char
  133. +#endif
  134. +
  135. +#define kNumTopBits 24
  136. +#define kTopValue ((UInt32)1 << kNumTopBits)
  137. +
  138. +#define kNumBitModelTotalBits 11
  139. +#define kBitModelTotal (1 << kNumBitModelTotalBits)
  140. +#define kNumMoveBits 5
  141. +
  142. +#define RC_READ_BYTE (*Buffer++)
  143. +
  144. +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
  145. + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
  146. +
  147. +#ifdef _LZMA_IN_CB
  148. +
  149. +#define RC_TEST { if (Buffer == BufferLim) \
  150. + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
  151. + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
  152. +
  153. +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
  154. +
  155. +#else
  156. +
  157. +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
  158. +
  159. +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
  160. +
  161. +#endif
  162. +
  163. +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
  164. +
  165. +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
  166. +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
  167. +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
  168. +
  169. +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
  170. + { UpdateBit0(p); mi <<= 1; A0; } else \
  171. + { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
  172. +
  173. +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
  174. +
  175. +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
  176. + { int i = numLevels; res = 1; \
  177. + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
  178. + res -= (1 << numLevels); }
  179. +
  180. +
  181. +#define kNumPosBitsMax 4
  182. +#define kNumPosStatesMax (1 << kNumPosBitsMax)
  183. +
  184. +#define kLenNumLowBits 3
  185. +#define kLenNumLowSymbols (1 << kLenNumLowBits)
  186. +#define kLenNumMidBits 3
  187. +#define kLenNumMidSymbols (1 << kLenNumMidBits)
  188. +#define kLenNumHighBits 8
  189. +#define kLenNumHighSymbols (1 << kLenNumHighBits)
  190. +
  191. +#define LenChoice 0
  192. +#define LenChoice2 (LenChoice + 1)
  193. +#define LenLow (LenChoice2 + 1)
  194. +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
  195. +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
  196. +#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
  197. +
  198. +
  199. +#define kNumStates 12
  200. +#define kNumLitStates 7
  201. +
  202. +#define kStartPosModelIndex 4
  203. +#define kEndPosModelIndex 14
  204. +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
  205. +
  206. +#define kNumPosSlotBits 6
  207. +#define kNumLenToPosStates 4
  208. +
  209. +#define kNumAlignBits 4
  210. +#define kAlignTableSize (1 << kNumAlignBits)
  211. +
  212. +#define kMatchMinLen 2
  213. +
  214. +#define IsMatch 0
  215. +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
  216. +#define IsRepG0 (IsRep + kNumStates)
  217. +#define IsRepG1 (IsRepG0 + kNumStates)
  218. +#define IsRepG2 (IsRepG1 + kNumStates)
  219. +#define IsRep0Long (IsRepG2 + kNumStates)
  220. +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
  221. +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
  222. +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
  223. +#define LenCoder (Align + kAlignTableSize)
  224. +#define RepLenCoder (LenCoder + kNumLenProbs)
  225. +#define Literal (RepLenCoder + kNumLenProbs)
  226. +
  227. +#if Literal != LZMA_BASE_SIZE
  228. +StopCompilingDueBUG
  229. +#endif
  230. +
  231. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
  232. +{
  233. + unsigned char prop0;
  234. + if (size < LZMA_PROPERTIES_SIZE)
  235. + return LZMA_RESULT_DATA_ERROR;
  236. + prop0 = propsData[0];
  237. + if (prop0 >= (9 * 5 * 5))
  238. + return LZMA_RESULT_DATA_ERROR;
  239. + {
  240. + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
  241. + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
  242. + propsRes->lc = prop0;
  243. + /*
  244. + unsigned char remainder = (unsigned char)(prop0 / 9);
  245. + propsRes->lc = prop0 % 9;
  246. + propsRes->pb = remainder / 5;
  247. + propsRes->lp = remainder % 5;
  248. + */
  249. + }
  250. +
  251. + #ifdef _LZMA_OUT_READ
  252. + {
  253. + int i;
  254. + propsRes->DictionarySize = 0;
  255. + for (i = 0; i < 4; i++)
  256. + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
  257. + if (propsRes->DictionarySize == 0)
  258. + propsRes->DictionarySize = 1;
  259. + }
  260. + #endif
  261. + return LZMA_RESULT_OK;
  262. +}
  263. +
  264. +#define kLzmaStreamWasFinishedId (-1)
  265. +
  266. +int LzmaDecode(CLzmaDecoderState *vs,
  267. + #ifdef _LZMA_IN_CB
  268. + ILzmaInCallback *InCallback,
  269. + #else
  270. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  271. + #endif
  272. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
  273. +{
  274. + CProb *p = vs->Probs;
  275. + SizeT nowPos = 0;
  276. + Byte previousByte = 0;
  277. + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
  278. + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
  279. + int lc = vs->Properties.lc;
  280. +
  281. + #ifdef _LZMA_OUT_READ
  282. +
  283. + UInt32 Range = vs->Range;
  284. + UInt32 Code = vs->Code;
  285. + #ifdef _LZMA_IN_CB
  286. + const Byte *Buffer = vs->Buffer;
  287. + const Byte *BufferLim = vs->BufferLim;
  288. + #else
  289. + const Byte *Buffer = inStream;
  290. + const Byte *BufferLim = inStream + inSize;
  291. + #endif
  292. + int state = vs->State;
  293. + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
  294. + int len = vs->RemainLen;
  295. + UInt32 globalPos = vs->GlobalPos;
  296. + UInt32 distanceLimit = vs->DistanceLimit;
  297. +
  298. + Byte *dictionary = vs->Dictionary;
  299. + UInt32 dictionarySize = vs->Properties.DictionarySize;
  300. + UInt32 dictionaryPos = vs->DictionaryPos;
  301. +
  302. + Byte tempDictionary[4];
  303. +
  304. + #ifndef _LZMA_IN_CB
  305. + *inSizeProcessed = 0;
  306. + #endif
  307. + *outSizeProcessed = 0;
  308. + if (len == kLzmaStreamWasFinishedId)
  309. + return LZMA_RESULT_OK;
  310. +
  311. + if (dictionarySize == 0)
  312. + {
  313. + dictionary = tempDictionary;
  314. + dictionarySize = 1;
  315. + tempDictionary[0] = vs->TempDictionary[0];
  316. + }
  317. +
  318. + if (len == kLzmaNeedInitId)
  319. + {
  320. + {
  321. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  322. + UInt32 i;
  323. + for (i = 0; i < numProbs; i++)
  324. + p[i] = kBitModelTotal >> 1;
  325. + rep0 = rep1 = rep2 = rep3 = 1;
  326. + state = 0;
  327. + globalPos = 0;
  328. + distanceLimit = 0;
  329. + dictionaryPos = 0;
  330. + dictionary[dictionarySize - 1] = 0;
  331. + #ifdef _LZMA_IN_CB
  332. + RC_INIT;
  333. + #else
  334. + RC_INIT(inStream, inSize);
  335. + #endif
  336. + }
  337. + len = 0;
  338. + }
  339. + while(len != 0 && nowPos < outSize)
  340. + {
  341. + UInt32 pos = dictionaryPos - rep0;
  342. + if (pos >= dictionarySize)
  343. + pos += dictionarySize;
  344. + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
  345. + if (++dictionaryPos == dictionarySize)
  346. + dictionaryPos = 0;
  347. + len--;
  348. + }
  349. + if (dictionaryPos == 0)
  350. + previousByte = dictionary[dictionarySize - 1];
  351. + else
  352. + previousByte = dictionary[dictionaryPos - 1];
  353. +
  354. + #else /* if !_LZMA_OUT_READ */
  355. +
  356. + int state = 0;
  357. + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
  358. + int len = 0;
  359. + const Byte *Buffer;
  360. + const Byte *BufferLim;
  361. + UInt32 Range;
  362. + UInt32 Code;
  363. +
  364. + #ifndef _LZMA_IN_CB
  365. + *inSizeProcessed = 0;
  366. + #endif
  367. + *outSizeProcessed = 0;
  368. +
  369. + {
  370. + UInt32 i;
  371. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  372. + for (i = 0; i < numProbs; i++)
  373. + p[i] = kBitModelTotal >> 1;
  374. + }
  375. +
  376. + #ifdef _LZMA_IN_CB
  377. + RC_INIT;
  378. + #else
  379. + RC_INIT(inStream, inSize);
  380. + #endif
  381. +
  382. + #endif /* _LZMA_OUT_READ */
  383. +
  384. + while(nowPos < outSize)
  385. + {
  386. + CProb *prob;
  387. + UInt32 bound;
  388. + int posState = (int)(
  389. + (nowPos
  390. + #ifdef _LZMA_OUT_READ
  391. + + globalPos
  392. + #endif
  393. + )
  394. + & posStateMask);
  395. +
  396. + prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
  397. + IfBit0(prob)
  398. + {
  399. + int symbol = 1;
  400. + UpdateBit0(prob)
  401. + prob = p + Literal + (LZMA_LIT_SIZE *
  402. + (((
  403. + (nowPos
  404. + #ifdef _LZMA_OUT_READ
  405. + + globalPos
  406. + #endif
  407. + )
  408. + & literalPosMask) << lc) + (previousByte >> (8 - lc))));
  409. +
  410. + if (state >= kNumLitStates)
  411. + {
  412. + int matchByte;
  413. + #ifdef _LZMA_OUT_READ
  414. + UInt32 pos = dictionaryPos - rep0;
  415. + if (pos >= dictionarySize)
  416. + pos += dictionarySize;
  417. + matchByte = dictionary[pos];
  418. + #else
  419. + matchByte = outStream[nowPos - rep0];
  420. + #endif
  421. + do
  422. + {
  423. + int bit;
  424. + CProb *probLit;
  425. + matchByte <<= 1;
  426. + bit = (matchByte & 0x100);
  427. + probLit = prob + 0x100 + bit + symbol;
  428. + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
  429. + }
  430. + while (symbol < 0x100);
  431. + }
  432. + while (symbol < 0x100)
  433. + {
  434. + CProb *probLit = prob + symbol;
  435. + RC_GET_BIT(probLit, symbol)
  436. + }
  437. + previousByte = (Byte)symbol;
  438. +
  439. + outStream[nowPos++] = previousByte;
  440. + #ifdef _LZMA_OUT_READ
  441. + if (distanceLimit < dictionarySize)
  442. + distanceLimit++;
  443. +
  444. + dictionary[dictionaryPos] = previousByte;
  445. + if (++dictionaryPos == dictionarySize)
  446. + dictionaryPos = 0;
  447. + #endif
  448. + if (state < 4) state = 0;
  449. + else if (state < 10) state -= 3;
  450. + else state -= 6;
  451. + }
  452. + else
  453. + {
  454. + UpdateBit1(prob);
  455. + prob = p + IsRep + state;
  456. + IfBit0(prob)
  457. + {
  458. + UpdateBit0(prob);
  459. + rep3 = rep2;
  460. + rep2 = rep1;
  461. + rep1 = rep0;
  462. + state = state < kNumLitStates ? 0 : 3;
  463. + prob = p + LenCoder;
  464. + }
  465. + else
  466. + {
  467. + UpdateBit1(prob);
  468. + prob = p + IsRepG0 + state;
  469. + IfBit0(prob)
  470. + {
  471. + UpdateBit0(prob);
  472. + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
  473. + IfBit0(prob)
  474. + {
  475. + #ifdef _LZMA_OUT_READ
  476. + UInt32 pos;
  477. + #endif
  478. + UpdateBit0(prob);
  479. +
  480. + #ifdef _LZMA_OUT_READ
  481. + if (distanceLimit == 0)
  482. + #else
  483. + if (nowPos == 0)
  484. + #endif
  485. + return LZMA_RESULT_DATA_ERROR;
  486. +
  487. + state = state < kNumLitStates ? 9 : 11;
  488. + #ifdef _LZMA_OUT_READ
  489. + pos = dictionaryPos - rep0;
  490. + if (pos >= dictionarySize)
  491. + pos += dictionarySize;
  492. + previousByte = dictionary[pos];
  493. + dictionary[dictionaryPos] = previousByte;
  494. + if (++dictionaryPos == dictionarySize)
  495. + dictionaryPos = 0;
  496. + #else
  497. + previousByte = outStream[nowPos - rep0];
  498. + #endif
  499. + outStream[nowPos++] = previousByte;
  500. + #ifdef _LZMA_OUT_READ
  501. + if (distanceLimit < dictionarySize)
  502. + distanceLimit++;
  503. + #endif
  504. +
  505. + continue;
  506. + }
  507. + else
  508. + {
  509. + UpdateBit1(prob);
  510. + }
  511. + }
  512. + else
  513. + {
  514. + UInt32 distance;
  515. + UpdateBit1(prob);
  516. + prob = p + IsRepG1 + state;
  517. + IfBit0(prob)
  518. + {
  519. + UpdateBit0(prob);
  520. + distance = rep1;
  521. + }
  522. + else
  523. + {
  524. + UpdateBit1(prob);
  525. + prob = p + IsRepG2 + state;
  526. + IfBit0(prob)
  527. + {
  528. + UpdateBit0(prob);
  529. + distance = rep2;
  530. + }
  531. + else
  532. + {
  533. + UpdateBit1(prob);
  534. + distance = rep3;
  535. + rep3 = rep2;
  536. + }
  537. + rep2 = rep1;
  538. + }
  539. + rep1 = rep0;
  540. + rep0 = distance;
  541. + }
  542. + state = state < kNumLitStates ? 8 : 11;
  543. + prob = p + RepLenCoder;
  544. + }
  545. + {
  546. + int numBits, offset;
  547. + CProb *probLen = prob + LenChoice;
  548. + IfBit0(probLen)
  549. + {
  550. + UpdateBit0(probLen);
  551. + probLen = prob + LenLow + (posState << kLenNumLowBits);
  552. + offset = 0;
  553. + numBits = kLenNumLowBits;
  554. + }
  555. + else
  556. + {
  557. + UpdateBit1(probLen);
  558. + probLen = prob + LenChoice2;
  559. + IfBit0(probLen)
  560. + {
  561. + UpdateBit0(probLen);
  562. + probLen = prob + LenMid + (posState << kLenNumMidBits);
  563. + offset = kLenNumLowSymbols;
  564. + numBits = kLenNumMidBits;
  565. + }
  566. + else
  567. + {
  568. + UpdateBit1(probLen);
  569. + probLen = prob + LenHigh;
  570. + offset = kLenNumLowSymbols + kLenNumMidSymbols;
  571. + numBits = kLenNumHighBits;
  572. + }
  573. + }
  574. + RangeDecoderBitTreeDecode(probLen, numBits, len);
  575. + len += offset;
  576. + }
  577. +
  578. + if (state < 4)
  579. + {
  580. + int posSlot;
  581. + state += kNumLitStates;
  582. + prob = p + PosSlot +
  583. + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
  584. + kNumPosSlotBits);
  585. + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
  586. + if (posSlot >= kStartPosModelIndex)
  587. + {
  588. + int numDirectBits = ((posSlot >> 1) - 1);
  589. + rep0 = (2 | ((UInt32)posSlot & 1));
  590. + if (posSlot < kEndPosModelIndex)
  591. + {
  592. + rep0 <<= numDirectBits;
  593. + prob = p + SpecPos + rep0 - posSlot - 1;
  594. + }
  595. + else
  596. + {
  597. + numDirectBits -= kNumAlignBits;
  598. + do
  599. + {
  600. + RC_NORMALIZE
  601. + Range >>= 1;
  602. + rep0 <<= 1;
  603. + if (Code >= Range)
  604. + {
  605. + Code -= Range;
  606. + rep0 |= 1;
  607. + }
  608. + }
  609. + while (--numDirectBits != 0);
  610. + prob = p + Align;
  611. + rep0 <<= kNumAlignBits;
  612. + numDirectBits = kNumAlignBits;
  613. + }
  614. + {
  615. + int i = 1;
  616. + int mi = 1;
  617. + do
  618. + {
  619. + CProb *prob3 = prob + mi;
  620. + RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
  621. + i <<= 1;
  622. + }
  623. + while(--numDirectBits != 0);
  624. + }
  625. + }
  626. + else
  627. + rep0 = posSlot;
  628. + if (++rep0 == (UInt32)(0))
  629. + {
  630. + /* it's for stream version */
  631. + len = kLzmaStreamWasFinishedId;
  632. + break;
  633. + }
  634. + }
  635. +
  636. + len += kMatchMinLen;
  637. + #ifdef _LZMA_OUT_READ
  638. + if (rep0 > distanceLimit)
  639. + #else
  640. + if (rep0 > nowPos)
  641. + #endif
  642. + return LZMA_RESULT_DATA_ERROR;
  643. +
  644. + #ifdef _LZMA_OUT_READ
  645. + if (dictionarySize - distanceLimit > (UInt32)len)
  646. + distanceLimit += len;
  647. + else
  648. + distanceLimit = dictionarySize;
  649. + #endif
  650. +
  651. + do
  652. + {
  653. + #ifdef _LZMA_OUT_READ
  654. + UInt32 pos = dictionaryPos - rep0;
  655. + if (pos >= dictionarySize)
  656. + pos += dictionarySize;
  657. + previousByte = dictionary[pos];
  658. + dictionary[dictionaryPos] = previousByte;
  659. + if (++dictionaryPos == dictionarySize)
  660. + dictionaryPos = 0;
  661. + #else
  662. + previousByte = outStream[nowPos - rep0];
  663. + #endif
  664. + len--;
  665. + outStream[nowPos++] = previousByte;
  666. + }
  667. + while(len != 0 && nowPos < outSize);
  668. + }
  669. + }
  670. + RC_NORMALIZE;
  671. +
  672. + #ifdef _LZMA_OUT_READ
  673. + vs->Range = Range;
  674. + vs->Code = Code;
  675. + vs->DictionaryPos = dictionaryPos;
  676. + vs->GlobalPos = globalPos + (UInt32)nowPos;
  677. + vs->DistanceLimit = distanceLimit;
  678. + vs->Reps[0] = rep0;
  679. + vs->Reps[1] = rep1;
  680. + vs->Reps[2] = rep2;
  681. + vs->Reps[3] = rep3;
  682. + vs->State = state;
  683. + vs->RemainLen = len;
  684. + vs->TempDictionary[0] = tempDictionary[0];
  685. + #endif
  686. +
  687. + #ifdef _LZMA_IN_CB
  688. + vs->Buffer = Buffer;
  689. + vs->BufferLim = BufferLim;
  690. + #else
  691. + *inSizeProcessed = (SizeT)(Buffer - inStream);
  692. + #endif
  693. + *outSizeProcessed = nowPos;
  694. + return LZMA_RESULT_OK;
  695. +}
  696. diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.h linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.h
  697. --- linux-2.6.22.1.oorig/arch/i386/boot/compressed/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
  698. +++ linux-2.6.22.1/arch/i386/boot/compressed/LzmaDecode.h 2007-07-24 14:17:46.000000000 +0200
  699. @@ -0,0 +1,131 @@
  700. +/*
  701. + LzmaDecode.h
  702. + LZMA Decoder interface
  703. +
  704. + LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
  705. + http://www.7-zip.org/
  706. +
  707. + LZMA SDK is licensed under two licenses:
  708. + 1) GNU Lesser General Public License (GNU LGPL)
  709. + 2) Common Public License (CPL)
  710. + It means that you can select one of these two licenses and
  711. + follow rules of that license.
  712. +
  713. + SPECIAL EXCEPTION:
  714. + Igor Pavlov, as the author of this code, expressly permits you to
  715. + statically or dynamically link your code (or bind by name) to the
  716. + interfaces of this file without subjecting your linked code to the
  717. + terms of the CPL or GNU LGPL. Any modifications or additions
  718. + to this file, however, are subject to the LGPL or CPL terms.
  719. +*/
  720. +
  721. +#ifndef __LZMADECODE_H
  722. +#define __LZMADECODE_H
  723. +
  724. +/* #define _LZMA_IN_CB */
  725. +/* Use callback for input data */
  726. +
  727. +/* #define _LZMA_OUT_READ */
  728. +/* Use read function for output data */
  729. +
  730. +/* #define _LZMA_PROB32 */
  731. +/* It can increase speed on some 32-bit CPUs,
  732. + but memory usage will be doubled in that case */
  733. +
  734. +/* #define _LZMA_LOC_OPT */
  735. +/* Enable local speed optimizations inside code */
  736. +
  737. +/* #define _LZMA_SYSTEM_SIZE_T */
  738. +/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
  739. +
  740. +#ifndef UInt32
  741. +#ifdef _LZMA_UINT32_IS_ULONG
  742. +#define UInt32 unsigned long
  743. +#else
  744. +#define UInt32 unsigned int
  745. +#endif
  746. +#endif
  747. +
  748. +#ifndef SizeT
  749. +#ifdef _LZMA_SYSTEM_SIZE_T
  750. +#include <stddef.h>
  751. +#define SizeT size_t
  752. +#else
  753. +#define SizeT UInt32
  754. +#endif
  755. +#endif
  756. +
  757. +#ifdef _LZMA_PROB32
  758. +#define CProb UInt32
  759. +#else
  760. +#define CProb unsigned short
  761. +#endif
  762. +
  763. +#define LZMA_RESULT_OK 0
  764. +#define LZMA_RESULT_DATA_ERROR 1
  765. +
  766. +#ifdef _LZMA_IN_CB
  767. +typedef struct _ILzmaInCallback
  768. +{
  769. + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
  770. +} ILzmaInCallback;
  771. +#endif
  772. +
  773. +#define LZMA_BASE_SIZE 1846
  774. +#define LZMA_LIT_SIZE 768
  775. +
  776. +#define LZMA_PROPERTIES_SIZE 5
  777. +
  778. +typedef struct _CLzmaProperties
  779. +{
  780. + int lc;
  781. + int lp;
  782. + int pb;
  783. + #ifdef _LZMA_OUT_READ
  784. + UInt32 DictionarySize;
  785. + #endif
  786. +}CLzmaProperties;
  787. +
  788. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
  789. +
  790. +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
  791. +
  792. +#define kLzmaNeedInitId (-2)
  793. +
  794. +typedef struct _CLzmaDecoderState
  795. +{
  796. + CLzmaProperties Properties;
  797. + CProb *Probs;
  798. +
  799. + #ifdef _LZMA_IN_CB
  800. + const unsigned char *Buffer;
  801. + const unsigned char *BufferLim;
  802. + #endif
  803. +
  804. + #ifdef _LZMA_OUT_READ
  805. + unsigned char *Dictionary;
  806. + UInt32 Range;
  807. + UInt32 Code;
  808. + UInt32 DictionaryPos;
  809. + UInt32 GlobalPos;
  810. + UInt32 DistanceLimit;
  811. + UInt32 Reps[4];
  812. + int State;
  813. + int RemainLen;
  814. + unsigned char TempDictionary[4];
  815. + #endif
  816. +} CLzmaDecoderState;
  817. +
  818. +#ifdef _LZMA_OUT_READ
  819. +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
  820. +#endif
  821. +
  822. +int LzmaDecode(CLzmaDecoderState *vs,
  823. + #ifdef _LZMA_IN_CB
  824. + ILzmaInCallback *inCallback,
  825. + #else
  826. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  827. + #endif
  828. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
  829. +
  830. +#endif
  831. diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/Makefile linux-2.6.22.1/arch/i386/boot/compressed/Makefile
  832. --- linux-2.6.22.1.oorig/arch/i386/boot/compressed/Makefile 2007-07-10 20:56:30.000000000 +0200
  833. +++ linux-2.6.22.1/arch/i386/boot/compressed/Makefile 2007-07-24 14:17:46.000000000 +0200
  834. @@ -4,15 +4,16 @@
  835. # create a compressed vmlinux image from the original vmlinux
  836. #
  837. -targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
  838. - vmlinux.bin.all vmlinux.relocs
  839. +tragets := head.o lzma_misc.o piggy.o \
  840. + vmlinux.bin.all vmlinux.relocs \
  841. + vmlinux vmlinux.bin vmlinux.bin.gz
  842. EXTRA_AFLAGS := -traditional
  843. LDFLAGS_vmlinux := -T
  844. -CFLAGS_misc.o += -fPIC
  845. +CFLAGS_lzma_misc.o += -fPIC
  846. hostprogs-y := relocs
  847. -$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
  848. +$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/lzma_misc.o $(obj)/piggy.o FORCE
  849. $(call if_changed,ld)
  850. @:
  851. @@ -33,10 +34,10 @@ $(obj)/vmlinux.bin.all: $(vmlinux.bin.al
  852. ifdef CONFIG_RELOCATABLE
  853. $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
  854. - $(call if_changed,gzip)
  855. + $(call if_changed,lzma)
  856. else
  857. $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
  858. - $(call if_changed,gzip)
  859. + $(call if_changed,lzma)
  860. endif
  861. LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
  862. diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/lzma_misc.c linux-2.6.22.1/arch/i386/boot/compressed/lzma_misc.c
  863. --- linux-2.6.22.1.oorig/arch/i386/boot/compressed/lzma_misc.c 1970-01-01 01:00:00.000000000 +0100
  864. +++ linux-2.6.22.1/arch/i386/boot/compressed/lzma_misc.c 2007-07-24 14:17:46.000000000 +0200
  865. @@ -0,0 +1,290 @@
  866. +/*
  867. + * lzma_misc.c
  868. + *
  869. + * Decompress LZMA compressed vmlinuz
  870. + * Version 0.9 Copyright (c) Ming-Ching Tiew mctiew@yahoo.com
  871. + * Program adapted from misc.c for 2.6.20.1 kernel
  872. + * Please refer to misc.c for authorship and copyright.
  873. + * Date: 25 March 2007
  874. + * Source released under GPL
  875. + */
  876. +
  877. +#undef CONFIG_PARAVIRT
  878. +#include <linux/linkage.h>
  879. +#include <linux/vmalloc.h>
  880. +#include <linux/screen_info.h>
  881. +#include <asm/io.h>
  882. +#include <asm/page.h>
  883. +#include <asm/boot.h>
  884. +
  885. +/* WARNING!!
  886. + * This code is compiled with -fPIC and it is relocated dynamically
  887. + * at run time, but no relocation processing is performed.
  888. + * This means that it is not safe to place pointers in static structures.
  889. + */
  890. +
  891. +#define OF(args) args
  892. +#define STATIC static
  893. +
  894. +#undef memset
  895. +#undef memcpy
  896. +
  897. +typedef unsigned char uch;
  898. +typedef unsigned short ush;
  899. +typedef unsigned long ulg;
  900. +
  901. +#define WSIZE 0x80000000 /* Window size must be at least 32k,
  902. + * and a power of two
  903. + * We don't actually have a window just
  904. + * a huge output buffer so I report
  905. + * a 2G windows size, as that should
  906. + * always be larger than our output buffer.
  907. + */
  908. +
  909. +static uch *inbuf; /* input buffer */
  910. +static uch *window; /* Sliding window buffer, (and final output buffer) */
  911. +
  912. +static unsigned insize; /* valid bytes in inbuf */
  913. +static unsigned inptr; /* index of next byte to be processed in inbuf */
  914. +
  915. +/* gzip flag byte */
  916. +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
  917. +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  918. +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
  919. +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
  920. +#define COMMENT 0x10 /* bit 4 set: file comment present */
  921. +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
  922. +#define RESERVED 0xC0 /* bit 6,7: reserved */
  923. +
  924. +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
  925. +
  926. +/* Diagnostic functions */
  927. +#ifdef DEBUG
  928. +# define Assert(cond,msg) {if(!(cond)) error(msg);}
  929. +# define Trace(x) fprintf x
  930. +# define Tracev(x) {if (verbose) fprintf x ;}
  931. +# define Tracevv(x) {if (verbose>1) fprintf x ;}
  932. +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
  933. +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
  934. +#else
  935. +# define Assert(cond,msg)
  936. +# define Trace(x)
  937. +# define Tracev(x)
  938. +# define Tracevv(x)
  939. +# define Tracec(c,x)
  940. +# define Tracecv(c,x)
  941. +#endif
  942. +
  943. +static int fill_inbuf(void);
  944. +static void error(char *m);
  945. +
  946. +/*
  947. + * This is set up by the setup-routine at boot-time
  948. + */
  949. +static unsigned char *real_mode; /* Pointer to real-mode data */
  950. +
  951. +#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
  952. +#ifndef STANDARD_MEMORY_BIOS_CALL
  953. +#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
  954. +#endif
  955. +#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
  956. +
  957. +extern unsigned char input_data[];
  958. +extern int input_len;
  959. +
  960. +static long bytes_out = 0;
  961. +
  962. +static void *memcpy(void *dest, const void *src, unsigned n);
  963. +
  964. +static void putstr(const char *);
  965. +
  966. +static unsigned long free_mem_ptr;
  967. +static unsigned long free_mem_end_ptr;
  968. +
  969. +#define HEAP_SIZE 0x3000
  970. +
  971. +static char *vidmem = (char *)0xb8000;
  972. +static int vidport;
  973. +static int lines, cols;
  974. +
  975. +#ifdef CONFIG_X86_NUMAQ
  976. +void *xquad_portio;
  977. +#endif
  978. +
  979. +static void scroll(void)
  980. +{
  981. + int i;
  982. +
  983. + memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
  984. + for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
  985. + vidmem[i] = ' ';
  986. +}
  987. +
  988. +static void putstr(const char *s)
  989. +{
  990. + int x,y,pos;
  991. + char c;
  992. +
  993. + x = RM_SCREEN_INFO.orig_x;
  994. + y = RM_SCREEN_INFO.orig_y;
  995. +
  996. + while ( ( c = *s++ ) != '\0' ) {
  997. + if ( c == '\n' ) {
  998. + x = 0;
  999. + if ( ++y >= lines ) {
  1000. + scroll();
  1001. + y--;
  1002. + }
  1003. + } else {
  1004. + vidmem [ ( x + cols * y ) * 2 ] = c;
  1005. + if ( ++x >= cols ) {
  1006. + x = 0;
  1007. + if ( ++y >= lines ) {
  1008. + scroll();
  1009. + y--;
  1010. + }
  1011. + }
  1012. + }
  1013. + }
  1014. +
  1015. + RM_SCREEN_INFO.orig_x = x;
  1016. + RM_SCREEN_INFO.orig_y = y;
  1017. +
  1018. + pos = (x + cols * y) * 2; /* Update cursor position */
  1019. + outb_p(14, vidport);
  1020. + outb_p(0xff & (pos >> 9), vidport+1);
  1021. + outb_p(15, vidport);
  1022. + outb_p(0xff & (pos >> 1), vidport+1);
  1023. +}
  1024. +
  1025. +static void* memcpy(void* dest, const void* src, unsigned n)
  1026. +{
  1027. + int i;
  1028. + char *d = (char *)dest, *s = (char *)src;
  1029. +
  1030. + for (i=0;i<n;i++) d[i] = s[i];
  1031. + return dest;
  1032. +}
  1033. +
  1034. +/* ===========================================================================
  1035. + * Fill the input buffer. This is called only when the buffer is empty
  1036. + * and at least one byte is really needed.
  1037. + */
  1038. +static int fill_inbuf(void)
  1039. +{
  1040. + error("ran out of input data");
  1041. + return 0;
  1042. +}
  1043. +
  1044. +/* ===========================================================================
  1045. + */
  1046. +static void error(char *x)
  1047. +{
  1048. + putstr("\n\n");
  1049. + putstr(x);
  1050. + putstr("\n\n -- System halted");
  1051. +
  1052. + while(1); /* Halt */
  1053. +}
  1054. +
  1055. +#define _LZMA_IN_CB
  1056. +#include "LzmaDecode.h"
  1057. +#include "LzmaDecode.c"
  1058. +
  1059. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
  1060. +
  1061. +/*
  1062. + * Do the lzma decompression
  1063. + */
  1064. +static int lzma_unzip(uch* output)
  1065. +{
  1066. +
  1067. + unsigned int i;
  1068. + CLzmaDecoderState state;
  1069. + unsigned int uncompressedSize = 0;
  1070. + unsigned char* p;
  1071. +
  1072. + ILzmaInCallback callback;
  1073. + callback.Read = read_byte;
  1074. +
  1075. + // lzma args
  1076. + i = get_byte();
  1077. + state.Properties.lc = i % 9, i = i / 9;
  1078. + state.Properties.lp = i % 5, state.Properties.pb = i / 5;
  1079. +
  1080. + // skip dictionary size
  1081. + for (i = 0; i < 4; i++)
  1082. + get_byte();
  1083. + // get uncompressed size
  1084. + p= (char*)&uncompressedSize;
  1085. + for (i = 0; i < 4; i++)
  1086. + *p++ = get_byte();
  1087. +
  1088. + // skip high order bytes
  1089. + for (i = 0; i < 4; i++)
  1090. + get_byte();
  1091. +
  1092. + // Just point it beyond
  1093. + state.Probs = (CProb*) ( free_mem_ptr );
  1094. + // decompress kernel
  1095. + if (LzmaDecode( &state, &callback,
  1096. + (unsigned char*)output, uncompressedSize, &i) == LZMA_RESULT_OK)
  1097. + {
  1098. + if ( i != uncompressedSize )
  1099. + error( "kernel corrupted!\n");
  1100. + bytes_out = i;
  1101. + return 0;
  1102. + }
  1103. + return 1;
  1104. +}
  1105. +
  1106. +
  1107. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
  1108. +{
  1109. + static unsigned int i = 0;
  1110. + static unsigned char val;
  1111. + *bufferSize = 1;
  1112. + val = get_byte();
  1113. + *buffer = &val;
  1114. + return LZMA_RESULT_OK;
  1115. +}
  1116. +
  1117. +asmlinkage void decompress_kernel(void *rmode, unsigned long end,
  1118. + uch *input_data, unsigned long input_len, uch *output)
  1119. +{
  1120. + real_mode = rmode;
  1121. +
  1122. + if (RM_SCREEN_INFO.orig_video_mode == 7) {
  1123. + vidmem = (char *) 0xb0000;
  1124. + vidport = 0x3b4;
  1125. + } else {
  1126. + vidmem = (char *) 0xb8000;
  1127. + vidport = 0x3d4;
  1128. + }
  1129. +
  1130. + lines = RM_SCREEN_INFO.orig_video_lines;
  1131. + cols = RM_SCREEN_INFO.orig_video_cols;
  1132. +
  1133. + window = output; /* Output buffer (Normally at 1M) */
  1134. + free_mem_ptr = end; /* Heap */
  1135. + free_mem_end_ptr = end + HEAP_SIZE;
  1136. + inbuf = input_data; /* Input buffer */
  1137. + insize = input_len;
  1138. + inptr = 0;
  1139. +
  1140. + if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
  1141. + error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
  1142. + if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
  1143. + error("Destination address too large");
  1144. +#ifndef CONFIG_RELOCATABLE
  1145. + if ((u32)output != LOAD_PHYSICAL_ADDR)
  1146. + error("Wrong destination address");
  1147. +#endif
  1148. + if( lzma_unzip(output) != 0 )
  1149. + {
  1150. + error("inflate error\n");
  1151. + }
  1152. + putstr("Ok, booting the kernel.\n");
  1153. +
  1154. + return;
  1155. +}
  1156. diff -rduNp linux-2.6.22.1.oorig/arch/i386/boot/compressed/vmlinux.scr linux-2.6.22.1/arch/i386/boot/compressed/vmlinux.scr
  1157. --- linux-2.6.22.1.oorig/arch/i386/boot/compressed/vmlinux.scr 2007-07-10 20:56:30.000000000 +0200
  1158. +++ linux-2.6.22.1/arch/i386/boot/compressed/vmlinux.scr 2007-07-24 14:17:46.000000000 +0200
  1159. @@ -3,8 +3,8 @@ SECTIONS
  1160. .data.compressed : {
  1161. input_len = .;
  1162. LONG(input_data_end - input_data) input_data = .;
  1163. + output_len = . + 5;
  1164. *(.data)
  1165. - output_len = . - 4;
  1166. input_data_end = .;
  1167. }
  1168. }
  1169. diff -rduNp linux-2.6.22.1.oorig/drivers/block/Kconfig linux-2.6.22.1/drivers/block/Kconfig
  1170. --- linux-2.6.22.1.oorig/drivers/block/Kconfig 2007-07-10 20:56:30.000000000 +0200
  1171. +++ linux-2.6.22.1/drivers/block/Kconfig 2007-07-24 14:17:46.000000000 +0200
  1172. @@ -406,6 +406,47 @@ config BLK_DEV_RAM_BLOCKSIZE
  1173. setups function - apparently needed by the rd_load_image routine
  1174. that supposes the filesystem in the image uses a 1024 blocksize.
  1175. +config LZMA_INITRD
  1176. + boolean "Allow LZMA compression on initrd"
  1177. + depends on BLK_DEV_INITRD=y
  1178. + default "y"
  1179. + help
  1180. + Use lzma compression on initrd, example 'lzma e initrd initrd.7z -d16'.
  1181. + If you have sufficient memory, you could compress using bigger dictionary size,
  1182. + 'lzma e initrd initrd.7z'.
  1183. +
  1184. +config LZMA_INITRD_KMALLOC_ONLY
  1185. + boolean "Use only kmalloc, do not use vmalloc on lzma initrd"
  1186. + depends on LZMA_INITRD=y
  1187. + default "n"
  1188. + help
  1189. + Set to y if you do not want to use vmalloc, ie use only kmalloc.
  1190. +
  1191. +config LZMA_INITRAM_FS
  1192. + boolean "Allow LZMA compression on initramfs"
  1193. + depends on BLK_DEV_RAM=y
  1194. + default "y"
  1195. + help
  1196. + Use lzma compression on initramfs, example 'lzma e initramfs.cpio initramfs.cpio.lzma'.
  1197. +
  1198. +config LZMA_INITRAM_FS_SMALLMEM
  1199. + boolean "Use lzma compression with small dictonary size."
  1200. + depends on LZMA_INITRAM_FS=y
  1201. + default "y"
  1202. + help
  1203. + Use lzma compression on initramfs with small dictionary size, example
  1204. + 'lzma e initramfs.cpio initramfs.cpio.lzma -d16'.
  1205. + Affects only the initramfs.cpio in the ~usr directory, which is compiled into
  1206. + the kernel. If you prepared initramfs.cpio for use with bootloader, you would
  1207. + need to specify the commandline options (-d16) yourself.
  1208. +
  1209. +config LZMA_INITRAM_FS_KMALLOC_ONLY
  1210. + boolean "Use only kmalloc, do not use vmalloc on lzma initramfs"
  1211. + depends on LZMA_INITRAM_FS=y
  1212. + default "n"
  1213. + help
  1214. + Set to y if you do not want to use vmalloc, ie use only kmalloc.
  1215. +
  1216. config CDROM_PKTCDVD
  1217. tristate "Packet writing on CD/DVD media"
  1218. depends on !UML
  1219. diff -rduNp linux-2.6.22.1.oorig/fs/Kconfig linux-2.6.22.1/fs/Kconfig
  1220. --- linux-2.6.22.1.oorig/fs/Kconfig 2007-07-10 20:56:30.000000000 +0200
  1221. +++ linux-2.6.22.1/fs/Kconfig 2007-07-24 14:17:46.000000000 +0200
  1222. @@ -1367,6 +1367,71 @@ config CRAMFS
  1223. If unsure, say N.
  1224. +config SQUASHFS
  1225. + tristate "SquashFS 3.2 - Squashed file system support"
  1226. + select ZLIB_INFLATE
  1227. + help
  1228. + Saying Y here includes support for SquashFS 3.2 (a Compressed Read-Only File
  1229. + System). Squashfs is a highly compressed read-only filesystem for Linux.
  1230. + It uses zlib compression to compress both files, inodes and directories.
  1231. + Inodes in the system are very small and all blocks are packed to minimise
  1232. + data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
  1233. + SquashFS 3.1 supports 64 bit filesystems and files (larger than 4GB), full
  1234. + uid/gid information, hard links and timestamps.
  1235. +
  1236. + Squashfs is intended for general read-only filesystem use, for archival
  1237. + use (i.e. in cases where a .tar.gz file may be used), and in embedded
  1238. + systems where low overhead is needed. Further information and filesystem tools
  1239. + are available from http://squashfs.sourceforge.net.
  1240. +
  1241. + If you want to compile this as a module ( = code which can be
  1242. + inserted in and removed from the running kernel whenever you want),
  1243. + say M here and read <file:Documentation/modules.txt>. The module
  1244. + will be called squashfs. Note that the root file system (the one
  1245. + containing the directory /) cannot be compiled as a module.
  1246. +
  1247. + If unsure, say N.
  1248. +
  1249. +config SQUASHFS_EMBEDDED
  1250. +
  1251. + bool "Additional options for memory-constrained systems"
  1252. + depends on SQUASHFS
  1253. + default n
  1254. + help
  1255. + Saying Y here allows you to specify cache sizes and how Squashfs
  1256. + allocates memory. This is only intended for memory constrained
  1257. + systems.
  1258. +
  1259. + If unsure, say N.
  1260. +
  1261. +config SQUASHFS_FRAGMENT_CACHE_SIZE
  1262. + int "Number of fragments cached" if SQUASHFS_EMBEDDED
  1263. + depends on SQUASHFS
  1264. + default "3"
  1265. + help
  1266. + By default SquashFS caches the last 3 fragments read from
  1267. + the filesystem. Increasing this amount may mean SquashFS
  1268. + has to re-read fragments less often from disk, at the expense
  1269. + of extra system memory. Decreasing this amount will mean
  1270. + SquashFS uses less memory at the expense of extra reads from disk.
  1271. +
  1272. + Note there must be at least one cached fragment. Anything
  1273. + much more than three will probably not make much difference.
  1274. +
  1275. +config SQUASHFS_VMALLOC
  1276. + bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
  1277. + depends on SQUASHFS
  1278. + default n
  1279. + help
  1280. + By default SquashFS uses kmalloc to obtain fragment cache memory.
  1281. + Kmalloc memory is the standard kernel allocator, but it can fail
  1282. + on memory constrained systems. Because of the way Vmalloc works,
  1283. + Vmalloc can succeed when kmalloc fails. Specifying this option
  1284. + will make SquashFS always use Vmalloc to allocate the
  1285. + fragment cache memory.
  1286. +
  1287. + If unsure, say N.
  1288. +
  1289. config VXFS_FS
  1290. tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
  1291. depends on BLOCK
  1292. @@ -2072,3 +2137,4 @@ source "fs/dlm/Kconfig"
  1293. endmenu
  1294. +source "fs/aufs/Kconfig"
  1295. diff -rduNp linux-2.6.22.1.oorig/fs/Makefile linux-2.6.22.1/fs/Makefile
  1296. --- linux-2.6.22.1.oorig/fs/Makefile 2007-07-10 20:56:30.000000000 +0200
  1297. +++ linux-2.6.22.1/fs/Makefile 2007-07-24 14:17:46.000000000 +0200
  1298. @@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/
  1299. obj-$(CONFIG_JBD2) += jbd2/
  1300. obj-$(CONFIG_EXT2_FS) += ext2/
  1301. obj-$(CONFIG_CRAMFS) += cramfs/
  1302. +obj-$(CONFIG_SQUASHFS) += squashfs/
  1303. obj-$(CONFIG_RAMFS) += ramfs/
  1304. obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
  1305. obj-$(CONFIG_CODA_FS) += coda/
  1306. @@ -118,3 +119,4 @@ obj-$(CONFIG_HPPFS) += hppfs/
  1307. obj-$(CONFIG_DEBUG_FS) += debugfs/
  1308. obj-$(CONFIG_OCFS2_FS) += ocfs2/
  1309. obj-$(CONFIG_GFS2_FS) += gfs2/
  1310. +obj-$(CONFIG_AUFS) += aufs/
  1311. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/Kconfig linux-2.6.22.1/fs/aufs/Kconfig
  1312. --- linux-2.6.22.1.oorig/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
  1313. +++ linux-2.6.22.1/fs/aufs/Kconfig 2007-07-24 14:17:46.000000000 +0200
  1314. @@ -0,0 +1,73 @@
  1315. +config AUFS
  1316. + tristate "Another unionfs"
  1317. + help
  1318. + Aufs is a stackable unification filesystem such as Unionfs,
  1319. + which unifies several directories and provides a merged single
  1320. + directory.
  1321. + In the early days, aufs was entirely re-designed and
  1322. + re-implemented Unionfs Version 1.x series. After many original
  1323. + ideas, approaches and improvements, it becomes totally
  1324. + different from Unionfs while keeping the basic features.
  1325. + See Unionfs for the basic features.
  1326. +
  1327. +if AUFS
  1328. +comment "These options are generated automatically for "#UTS_RELEASE
  1329. +
  1330. +config AUFS_FAKE_DM
  1331. + bool "Use simplified (fake) nameidata"
  1332. + depends on AUFS
  1333. + default y
  1334. + help
  1335. + Faking nameidata (VFS internal data), you can get better performance
  1336. + in some cases.
  1337. +
  1338. +choice
  1339. + prompt "Maximum number of branches"
  1340. + depends on AUFS
  1341. + default AUFS_BRANCH_MAX_127
  1342. + help
  1343. + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
  1344. +config AUFS_BRANCH_MAX_127
  1345. + bool "127"
  1346. + help
  1347. + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
  1348. +config AUFS_BRANCH_MAX_511
  1349. + bool "511"
  1350. + help
  1351. + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
  1352. +config AUFS_BRANCH_MAX_1023
  1353. + bool "1023"
  1354. + help
  1355. + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
  1356. +
  1357. +config AUFS_BRANCH_MAX_32767
  1358. + bool "32767"
  1359. + help
  1360. + Specifies the maximum number of branches (or member directories) in a single aufs. The larger value consumes more system resources and has an impact to performance.
  1361. +endchoice
  1362. +config AUFS_DEBUG
  1363. + bool "Debug aufs"
  1364. + depends on AUFS
  1365. + default y
  1366. + help
  1367. + Enable this to compile aufs internal debug code.
  1368. + The performance will be damaged.
  1369. +
  1370. +config AUFS_COMPAT
  1371. + bool "Compatibility with Unionfs (obsolete)"
  1372. + depends on AUFS
  1373. + default n
  1374. + help
  1375. + This makes aufs compatible with unionfs-style mount options and some
  1376. + behaviours.
  1377. + The dirs= mount option and =nfsro branch permission flag are always
  1378. + interpreted as br: mount option and =ro flag respectively. The
  1379. + 'debug', 'delete' and 'imap' mount options are ignored.
  1380. + If you disable this option, you will get,
  1381. + - aufs issues a warning about the ignored mount options
  1382. + - the default branch permission flag is set. RW for the first branch,
  1383. + and RO for the rests.
  1384. + - the name of a internal file which represents the directory is
  1385. + 'opaque', becomes '.wh..wh..opq'
  1386. + - the 'diropq=w' mount option is set by default
  1387. +endif
  1388. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/Makefile linux-2.6.22.1/fs/aufs/Makefile
  1389. --- linux-2.6.22.1.oorig/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
  1390. +++ linux-2.6.22.1/fs/aufs/Makefile 2007-07-24 14:17:46.000000000 +0200
  1391. @@ -0,0 +1,18 @@
  1392. +# AUFS Makefile for the Linux 2.6.16 and later
  1393. +# $Id: Makefile,v 1.29 2007/04/23 00:59:50 sfjro Exp $
  1394. +
  1395. +obj-$(CONFIG_AUFS) += aufs.o
  1396. +aufs-y := module.o super.o sbinfo.o xino.o \
  1397. + branch.o cpup.o whout.o plink.o wkq.o dcsub.o vfsub.o \
  1398. + opts.o \
  1399. + dentry.o dinfo.o \
  1400. + file.o f_op.o finfo.o \
  1401. + dir.o vdir.o \
  1402. + inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \
  1403. + misc.o
  1404. +#xattr.o
  1405. +aufs-$(CONFIG_AUFS_SYSAUFS) += sysaufs.o
  1406. +aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
  1407. +aufs-$(CONFIG_AUFS_EXPORT) += export.o
  1408. +#aufs-$(CONFIG_DEBUGFS) += dbgfs.o
  1409. +aufs-$(CONFIG_AUFS_DEBUG) += debug.o
  1410. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/aufs.h linux-2.6.22.1/fs/aufs/aufs.h
  1411. --- linux-2.6.22.1.oorig/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
  1412. +++ linux-2.6.22.1/fs/aufs/aufs.h 2007-07-24 14:17:46.000000000 +0200
  1413. @@ -0,0 +1,64 @@
  1414. +/*
  1415. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  1416. + *
  1417. + * This program, aufs is free software; you can redistribute it and/or modify
  1418. + * it under the terms of the GNU General Public License as published by
  1419. + * the Free Software Foundation; either version 2 of the License, or
  1420. + * (at your option) any later version.
  1421. + *
  1422. + * This program is distributed in the hope that it will be useful,
  1423. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1424. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1425. + * GNU General Public License for more details.
  1426. + *
  1427. + * You should have received a copy of the GNU General Public License
  1428. + * along with this program; if not, write to the Free Software
  1429. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  1430. + */
  1431. +
  1432. +/* $Id: aufs.h,v 1.24 2007/05/14 03:41:51 sfjro Exp $ */
  1433. +
  1434. +#ifndef __AUFS_H__
  1435. +#define __AUFS_H__
  1436. +
  1437. +#ifdef __KERNEL__
  1438. +
  1439. +#include <linux/version.h>
  1440. +
  1441. +/* limited support before 2.6.16, curretly 2.6.15 only. */
  1442. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
  1443. +#define atomic_long_t atomic_t
  1444. +#define atomic_long_set atomic_set
  1445. +#define timespec_to_ns(ts) ({(long long)(ts)->tv_sec;})
  1446. +#define D_CHILD d_child
  1447. +#else
  1448. +#define D_CHILD d_u.d_child
  1449. +#endif
  1450. +
  1451. +/* ---------------------------------------------------------------------- */
  1452. +
  1453. +#include "debug.h"
  1454. +
  1455. +#include "branch.h"
  1456. +#include "cpup.h"
  1457. +#include "dcsub.h"
  1458. +#include "dentry.h"
  1459. +#include "dir.h"
  1460. +#include "file.h"
  1461. +#include "inode.h"
  1462. +#include "misc.h"
  1463. +#include "module.h"
  1464. +#include "opts.h"
  1465. +#include "super.h"
  1466. +#include "sysaufs.h"
  1467. +#include "vfsub.h"
  1468. +#include "whout.h"
  1469. +#include "wkq.h"
  1470. +//#include "xattr.h"
  1471. +
  1472. +#if defined(CONFIG_AUFS_MODULE) && !defined(CONFIG_AUFS_KSIZE_PATCH)
  1473. +#define ksize(p) (-1U)
  1474. +#endif
  1475. +
  1476. +#endif /* __KERNEL__ */
  1477. +#endif /* __AUFS_H__ */
  1478. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/branch.c linux-2.6.22.1/fs/aufs/branch.c
  1479. --- linux-2.6.22.1.oorig/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
  1480. +++ linux-2.6.22.1/fs/aufs/branch.c 2007-07-24 14:17:46.000000000 +0200
  1481. @@ -0,0 +1,818 @@
  1482. +/*
  1483. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  1484. + *
  1485. + * This program, aufs is free software; you can redistribute it and/or modify
  1486. + * it under the terms of the GNU General Public License as published by
  1487. + * the Free Software Foundation; either version 2 of the License, or
  1488. + * (at your option) any later version.
  1489. + *
  1490. + * This program is distributed in the hope that it will be useful,
  1491. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1492. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1493. + * GNU General Public License for more details.
  1494. + *
  1495. + * You should have received a copy of the GNU General Public License
  1496. + * along with this program; if not, write to the Free Software
  1497. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  1498. + */
  1499. +
  1500. +/* $Id: branch.c,v 1.49 2007/05/14 03:38:23 sfjro Exp $ */
  1501. +
  1502. +//#include <linux/fs.h>
  1503. +//#include <linux/namei.h>
  1504. +#include "aufs.h"
  1505. +
  1506. +static void free_branch(struct aufs_branch *br)
  1507. +{
  1508. + TraceEnter();
  1509. +
  1510. + if (br->br_xino)
  1511. + fput(br->br_xino);
  1512. + dput(br->br_wh);
  1513. + dput(br->br_plink);
  1514. + mntput(br->br_mnt);
  1515. + DEBUG_ON(br_count(br) || atomic_read(&br->br_wh_running));
  1516. + kfree(br);
  1517. +}
  1518. +
  1519. +/*
  1520. + * frees all branches
  1521. + */
  1522. +void free_branches(struct aufs_sbinfo *sbinfo)
  1523. +{
  1524. + aufs_bindex_t bmax;
  1525. + struct aufs_branch **br;
  1526. +
  1527. + TraceEnter();
  1528. + bmax = sbinfo->si_bend + 1;
  1529. + br = sbinfo->si_branch;
  1530. + while (bmax--)
  1531. + free_branch(*br++);
  1532. +}
  1533. +
  1534. +/*
  1535. + * find the index of a branch which is specified by @br_id.
  1536. + */
  1537. +int find_brindex(struct super_block *sb, aufs_bindex_t br_id)
  1538. +{
  1539. + aufs_bindex_t bindex, bend;
  1540. +
  1541. + TraceEnter();
  1542. +
  1543. + bend = sbend(sb);
  1544. + for (bindex = 0; bindex <= bend; bindex++)
  1545. + if (sbr_id(sb, bindex) == br_id)
  1546. + return bindex;
  1547. + return -1;
  1548. +}
  1549. +
  1550. +/*
  1551. + * test if the @br is readonly or not.
  1552. + */
  1553. +int br_rdonly(struct aufs_branch *br)
  1554. +{
  1555. + return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
  1556. + || !br_writable(br->br_perm))
  1557. + ? -EROFS : 0;
  1558. +}
  1559. +
  1560. +/*
  1561. + * returns writable branch index, otherwise an error.
  1562. + * todo: customizable writable-branch-policy
  1563. + */
  1564. +static int find_rw_parent(struct dentry *dentry, aufs_bindex_t bend)
  1565. +{
  1566. + int err;
  1567. + aufs_bindex_t bindex, candidate;
  1568. + struct super_block *sb;
  1569. + struct dentry *parent, *hidden_parent;
  1570. +
  1571. + err = bend;
  1572. + sb = dentry->d_sb;
  1573. + parent = dget_parent(dentry);
  1574. +#if 1 // branch policy
  1575. + hidden_parent = au_h_dptr_i(parent, bend);
  1576. + if (hidden_parent && !br_rdonly(stobr(sb, bend)))
  1577. + goto out; /* success */
  1578. +#endif
  1579. +
  1580. + candidate = -1;
  1581. + for (bindex = dbstart(parent); bindex <= bend; bindex++) {
  1582. + hidden_parent = au_h_dptr_i(parent, bindex);
  1583. + if (hidden_parent && !br_rdonly(stobr(sb, bindex))) {
  1584. +#if 0 // branch policy
  1585. + if (candidate == -1)
  1586. + candidate = bindex;
  1587. + if (!au_test_perm(hidden_parent->d_inode, MAY_WRITE))
  1588. + return bindex;
  1589. +#endif
  1590. + err = bindex;
  1591. + goto out; /* success */
  1592. + }
  1593. + }
  1594. +#if 0 // branch policy
  1595. + err = candidate;
  1596. + if (candidate != -1)
  1597. + goto out; /* success */
  1598. +#endif
  1599. + err = -EROFS;
  1600. +
  1601. + out:
  1602. + dput(parent);
  1603. + return err;
  1604. +}
  1605. +
  1606. +int find_rw_br(struct super_block *sb, aufs_bindex_t bend)
  1607. +{
  1608. + aufs_bindex_t bindex;
  1609. +
  1610. + for (bindex = bend; bindex >= 0; bindex--)
  1611. + if (!br_rdonly(stobr(sb, bindex)))
  1612. + return bindex;
  1613. + return -EROFS;
  1614. +}
  1615. +
  1616. +int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend)
  1617. +{
  1618. + int err;
  1619. +
  1620. + err = find_rw_parent(dentry, bend);
  1621. + if (err >= 0)
  1622. + return err;
  1623. + return find_rw_br(dentry->d_sb, bend);
  1624. +}
  1625. +
  1626. +/* ---------------------------------------------------------------------- */
  1627. +
  1628. +/*
  1629. + * test if two hidden_dentries have overlapping branches.
  1630. + */
  1631. +//todo: try is_subdir()
  1632. +static int do_is_overlap(struct super_block *sb, struct dentry *hidden_d1,
  1633. + struct dentry *hidden_d2)
  1634. +{
  1635. + struct dentry *d;
  1636. +
  1637. + d = hidden_d1;
  1638. + do {
  1639. + if (unlikely(d == hidden_d2))
  1640. + return 1;
  1641. + d = d->d_parent; // dget_parent()
  1642. + } while (!IS_ROOT(d));
  1643. +
  1644. + return (d == hidden_d2);
  1645. +}
  1646. +
  1647. +#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
  1648. +#include <linux/loop.h>
  1649. +static int is_overlap_loopback(struct super_block *sb, struct dentry *hidden_d1,
  1650. + struct dentry *hidden_d2)
  1651. +{
  1652. + struct inode *hidden_inode;
  1653. + struct loop_device *l;
  1654. +
  1655. + hidden_inode = hidden_d1->d_inode;
  1656. + if (MAJOR(hidden_inode->i_sb->s_dev) != LOOP_MAJOR)
  1657. + return 0;
  1658. +
  1659. + l = hidden_inode->i_sb->s_bdev->bd_disk->private_data;
  1660. + hidden_d1 = l->lo_backing_file->f_dentry;
  1661. + if (unlikely(hidden_d1->d_sb == sb))
  1662. + return 1;
  1663. + return do_is_overlap(sb, hidden_d1, hidden_d2);
  1664. +}
  1665. +#else
  1666. +#define is_overlap_loopback(sb, hidden_d1, hidden_d2) 0
  1667. +#endif
  1668. +
  1669. +static int is_overlap(struct super_block *sb, struct dentry *hidden_d1,
  1670. + struct dentry *hidden_d2)
  1671. +{
  1672. + LKTRTrace("d1 %.*s, d2 %.*s\n", DLNPair(hidden_d1), DLNPair(hidden_d2));
  1673. + if (unlikely(hidden_d1 == hidden_d2))
  1674. + return 1;
  1675. + return do_is_overlap(sb, hidden_d1, hidden_d2)
  1676. + || do_is_overlap(sb, hidden_d2, hidden_d1)
  1677. + || is_overlap_loopback(sb, hidden_d1, hidden_d2)
  1678. + || is_overlap_loopback(sb, hidden_d2, hidden_d1);
  1679. +}
  1680. +
  1681. +/* ---------------------------------------------------------------------- */
  1682. +
  1683. +static int init_br_wh(struct super_block *sb, aufs_bindex_t bindex,
  1684. + struct aufs_branch *br, int new_perm,
  1685. + struct dentry *h_root, struct vfsmount *h_mnt)
  1686. +{
  1687. + int err, old_perm;
  1688. + struct inode *dir = sb->s_root->d_inode,
  1689. + *h_dir = h_root->d_inode;
  1690. + const int new = (bindex < 0);
  1691. +
  1692. + LKTRTrace("b%d, new_perm %d\n", bindex, new_perm);
  1693. +
  1694. + if (new)
  1695. + hi_lock_parent(h_dir);
  1696. + else
  1697. + hdir_lock(h_dir, dir, bindex);
  1698. +
  1699. + br_wh_write_lock(br);
  1700. + old_perm = br->br_perm;
  1701. + br->br_perm = new_perm;
  1702. + err = init_wh(h_root, br, au_do_nfsmnt(h_mnt), sb);
  1703. + br->br_perm = old_perm;
  1704. + br_wh_write_unlock(br);
  1705. +
  1706. + if (new)
  1707. + i_unlock(h_dir);
  1708. + else
  1709. + hdir_unlock(h_dir, dir, bindex);
  1710. +
  1711. + TraceErr(err);
  1712. + return err;
  1713. +}
  1714. +
  1715. +/* ---------------------------------------------------------------------- */
  1716. +
  1717. +/*
  1718. + * returns a newly allocated branch. @new_nbranch is a number of branches
  1719. + * after adding a branch.
  1720. + */
  1721. +static struct aufs_branch *alloc_addbr(struct super_block *sb, int new_nbranch)
  1722. +{
  1723. + struct aufs_branch **branchp, *add_branch;
  1724. + int sz;
  1725. + void *p;
  1726. + struct dentry *root;
  1727. + struct inode *inode;
  1728. + struct aufs_hinode *hinodep;
  1729. + struct aufs_hdentry *hdentryp;
  1730. +
  1731. + LKTRTrace("new_nbranch %d\n", new_nbranch);
  1732. + SiMustWriteLock(sb);
  1733. + root = sb->s_root;
  1734. + DiMustWriteLock(root);
  1735. + inode = root->d_inode;
  1736. + IiMustWriteLock(inode);
  1737. +
  1738. + add_branch = kmalloc(sizeof(*add_branch), GFP_KERNEL);
  1739. + //if (LktrCond) {kfree(add_branch); add_branch = NULL;}
  1740. + if (unlikely(!add_branch))
  1741. + goto out;
  1742. +
  1743. + sz = sizeof(*branchp) * (new_nbranch - 1);
  1744. + if (unlikely(!sz))
  1745. + sz = sizeof(*branchp);
  1746. + p = stosi(sb)->si_branch;
  1747. + branchp = au_kzrealloc(p, sz, sizeof(*branchp) * new_nbranch,
  1748. + GFP_KERNEL);
  1749. + //if (LktrCond) branchp = NULL;
  1750. + if (unlikely(!branchp))
  1751. + goto out;
  1752. + stosi(sb)->si_branch = branchp;
  1753. +
  1754. + sz = sizeof(*hdentryp) * (new_nbranch - 1);
  1755. + if (unlikely(!sz))
  1756. + sz = sizeof(*hdentryp);
  1757. + p = dtodi(root)->di_hdentry;
  1758. + hdentryp = au_kzrealloc(p, sz, sizeof(*hdentryp) * new_nbranch,
  1759. + GFP_KERNEL);
  1760. + //if (LktrCond) hdentryp = NULL;
  1761. + if (unlikely(!hdentryp))
  1762. + goto out;
  1763. + dtodi(root)->di_hdentry = hdentryp;
  1764. +
  1765. + sz = sizeof(*hinodep) * (new_nbranch - 1);
  1766. + if (unlikely(!sz))
  1767. + sz = sizeof(*hinodep);
  1768. + p = itoii(inode)->ii_hinode;
  1769. + hinodep = au_kzrealloc(p, sz, sizeof(*hinodep) * new_nbranch,
  1770. + GFP_KERNEL);
  1771. + //if (LktrCond) hinodep = NULL; // unavailable test
  1772. + if (unlikely(!hinodep))
  1773. + goto out;
  1774. + itoii(inode)->ii_hinode = hinodep;
  1775. + return add_branch; /* success */
  1776. +
  1777. + out:
  1778. + kfree(add_branch);
  1779. + TraceErr(-ENOMEM);
  1780. + return ERR_PTR(-ENOMEM);
  1781. +}
  1782. +
  1783. +/*
  1784. + * test if the branch permission is legal or not.
  1785. + */
  1786. +static int test_br(struct super_block *sb, struct inode *inode, int brperm,
  1787. + char *path)
  1788. +{
  1789. + int err;
  1790. +
  1791. + err = 0;
  1792. + if (unlikely(br_writable(brperm) && IS_RDONLY(inode))) {
  1793. + Err("write permission for readonly fs or inode, %s\n", path);
  1794. + err = -EINVAL;
  1795. + }
  1796. +
  1797. + TraceErr(err);
  1798. + return err;
  1799. +}
  1800. +
  1801. +/*
  1802. + * retunrs,,,
  1803. + * 0: success, the caller will add it
  1804. + * plus: success, it is already unified, the caller should ignore it
  1805. + * minus: error
  1806. + */
  1807. +static int test_add(struct super_block *sb, struct opt_add *add, int remount)
  1808. +{
  1809. + int err;
  1810. + struct dentry *root;
  1811. + struct inode *inode, *hidden_inode;
  1812. + aufs_bindex_t bend, bindex;
  1813. +
  1814. + LKTRTrace("%s, remo%d\n", add->path, remount);
  1815. +
  1816. + root = sb->s_root;
  1817. + if (unlikely(au_find_dbindex(root, add->nd.dentry) != -1)) {
  1818. + err = 1;
  1819. + if (!remount) {
  1820. + err = -EINVAL;
  1821. + Err("%s duplicated\n", add->path);
  1822. + }
  1823. + goto out;
  1824. + }
  1825. +
  1826. + err = -ENOSPC; //-E2BIG;
  1827. + bend = sbend(sb);
  1828. + //if (LktrCond) bend = AUFS_BRANCH_MAX;
  1829. + if (unlikely(AUFS_BRANCH_MAX <= add->bindex
  1830. + || AUFS_BRANCH_MAX - 1 <= bend)) {
  1831. + Err("number of branches exceeded %s\n", add->path);
  1832. + goto out;
  1833. + }
  1834. +
  1835. + err = -EDOM;
  1836. + if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
  1837. + Err("bad index %d\n", add->bindex);
  1838. + goto out;
  1839. + }
  1840. +
  1841. + inode = add->nd.dentry->d_inode;
  1842. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  1843. + err = -ENOENT;
  1844. + if (unlikely(!inode->i_nlink)) {
  1845. + Err("no existence %s\n", add->path);
  1846. + goto out;
  1847. + }
  1848. +
  1849. + err = -EINVAL;
  1850. + if (unlikely(inode->i_sb == sb)) {
  1851. + Err("%s must be outside\n", add->path);
  1852. + goto out;
  1853. + }
  1854. +
  1855. +#if 1 //ndef CONFIG_AUFS_ROBR
  1856. + if (unlikely(au_is_aufs(inode->i_sb)
  1857. + || !strcmp(au_sbtype(inode->i_sb), "unionfs"))) {
  1858. + Err("nested " AUFS_NAME " %s\n", add->path);
  1859. + goto out;
  1860. + }
  1861. +#endif
  1862. +
  1863. +#ifdef AuNoNfsBranch
  1864. + if (unlikely(au_is_nfs(inode->i_sb))) {
  1865. + Err(AuNoNfsBranchMsg ". %s\n", add->path);
  1866. + goto out;
  1867. + }
  1868. +#endif
  1869. +
  1870. + err = test_br(sb, add->nd.dentry->d_inode, add->perm, add->path);
  1871. + if (unlikely(err))
  1872. + goto out;
  1873. +
  1874. + if (unlikely(bend == -1))
  1875. + return 0; /* success */
  1876. +
  1877. + hidden_inode = au_h_dptr(root)->d_inode;
  1878. + if (unlikely(au_flag_test(sb, AuFlag_WARN_PERM)
  1879. + && ((hidden_inode->i_mode & S_IALLUGO)
  1880. + != (inode->i_mode & S_IALLUGO)
  1881. + || hidden_inode->i_uid != inode->i_uid
  1882. + || hidden_inode->i_gid != inode->i_gid)))
  1883. + Warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
  1884. + add->path,
  1885. + inode->i_uid, inode->i_gid, (inode->i_mode & S_IALLUGO),
  1886. + hidden_inode->i_uid, hidden_inode->i_gid,
  1887. + (hidden_inode->i_mode & S_IALLUGO));
  1888. +
  1889. + err = -EINVAL;
  1890. + for (bindex = 0; bindex <= bend; bindex++)
  1891. + if (unlikely(is_overlap(sb, add->nd.dentry,
  1892. + au_h_dptr_i(root, bindex)))) {
  1893. + Err("%s is overlapped\n", add->path);
  1894. + goto out;
  1895. + }
  1896. + err = 0;
  1897. +
  1898. + out:
  1899. + TraceErr(err);
  1900. + return err;
  1901. +}
  1902. +
  1903. +int br_add(struct super_block *sb, struct opt_add *add, int remount)
  1904. +{
  1905. + int err, sz;
  1906. + aufs_bindex_t bend, add_bindex;
  1907. + struct dentry *root;
  1908. + struct aufs_iinfo *iinfo;
  1909. + struct aufs_sbinfo *sbinfo;
  1910. + struct aufs_dinfo *dinfo;
  1911. + struct inode *root_inode;
  1912. + unsigned long long maxb;
  1913. + struct aufs_branch **branchp, *add_branch;
  1914. + struct aufs_hdentry *hdentryp;
  1915. + struct aufs_hinode *hinodep;
  1916. +
  1917. + LKTRTrace("b%d, %s, 0x%x, %.*s\n", add->bindex, add->path,
  1918. + add->perm, DLNPair(add->nd.dentry));
  1919. + SiMustWriteLock(sb);
  1920. + root = sb->s_root;
  1921. + DiMustWriteLock(root);
  1922. + root_inode = root->d_inode;
  1923. + IMustLock(root_inode);
  1924. + IiMustWriteLock(root_inode);
  1925. +
  1926. + err = test_add(sb, add, remount);
  1927. + if (unlikely(err < 0))
  1928. + goto out;
  1929. + if (unlikely(err))
  1930. + return 0; /* success */
  1931. +
  1932. + bend = sbend(sb);
  1933. + add_branch = alloc_addbr(sb, bend + 2);
  1934. + err = PTR_ERR(add_branch);
  1935. + if (IS_ERR(add_branch))
  1936. + goto out;
  1937. +
  1938. + err = 0;
  1939. + rw_init_nolock(&add_branch->br_wh_rwsem);
  1940. + add_branch->br_wh = add_branch->br_plink = NULL;
  1941. + if (unlikely(br_writable(add->perm))) {
  1942. + err = init_br_wh(sb, /*bindex*/-1, add_branch, add->perm,
  1943. + add->nd.dentry, add->nd.mnt);
  1944. + if (unlikely(err)) {
  1945. + kfree(add_branch);
  1946. + goto out;
  1947. + }
  1948. + }
  1949. + add_branch->br_xino = NULL;
  1950. + add_branch->br_mnt = mntget(add->nd.mnt);
  1951. + atomic_set(&add_branch->br_wh_running, 0);
  1952. + add_branch->br_id = new_br_id(sb);
  1953. + add_branch->br_perm = add->perm;
  1954. + atomic_set(&add_branch->br_count, 0);
  1955. +
  1956. + sbinfo = stosi(sb);
  1957. + dinfo = dtodi(root);
  1958. + iinfo = itoii(root_inode);
  1959. +
  1960. + add_bindex = add->bindex;
  1961. + sz = sizeof(*(sbinfo->si_branch)) * (bend + 1 - add_bindex);
  1962. + branchp = sbinfo->si_branch + add_bindex;
  1963. + memmove(branchp + 1, branchp, sz);
  1964. + *branchp = add_branch;
  1965. + sz = sizeof(*hdentryp) * (bend + 1 - add_bindex);
  1966. + hdentryp = dinfo->di_hdentry + add_bindex;
  1967. + memmove(hdentryp + 1, hdentryp, sz);
  1968. + hdentryp->hd_dentry = NULL;
  1969. + sz = sizeof(*hinodep) * (bend + 1 - add_bindex);
  1970. + hinodep = iinfo->ii_hinode + add_bindex;
  1971. + memmove(hinodep + 1, hinodep, sz);
  1972. + hinodep->hi_inode = NULL;
  1973. + hinodep->hi_notify = NULL;
  1974. +
  1975. + sbinfo->si_bend++;
  1976. + dinfo->di_bend++;
  1977. + iinfo->ii_bend++;
  1978. + if (unlikely(bend == -1)) {
  1979. + dinfo->di_bstart = 0;
  1980. + iinfo->ii_bstart = 0;
  1981. + }
  1982. + set_h_dptr(root, add_bindex, dget(add->nd.dentry));
  1983. + set_h_iptr(root_inode, add_bindex, igrab(add->nd.dentry->d_inode), 0);
  1984. + if (!add_bindex)
  1985. + au_cpup_attr_all(root_inode);
  1986. + else
  1987. + au_add_nlink(root_inode, add->nd.dentry->d_inode);
  1988. + maxb = add->nd.dentry->d_sb->s_maxbytes;
  1989. + if (sb->s_maxbytes < maxb)
  1990. + sb->s_maxbytes = maxb;
  1991. +
  1992. + if (au_flag_test(sb, AuFlag_XINO)) {
  1993. + struct file *base_file = stobr(sb, 0)->br_xino;
  1994. + if (!add_bindex)
  1995. + base_file = stobr(sb, 1)->br_xino;
  1996. + err = xino_init(sb, add_bindex, base_file, /*do_test*/1);
  1997. + if (unlikely(err)) {
  1998. + DEBUG_ON(add_branch->br_xino);
  1999. + Err("ignored xino err %d, force noxino\n", err);
  2000. + err = 0;
  2001. + au_flag_clr(sb, AuFlag_XINO);
  2002. + }
  2003. + }
  2004. +
  2005. + out:
  2006. + TraceErr(err);
  2007. + return err;
  2008. +}
  2009. +
  2010. +/* ---------------------------------------------------------------------- */
  2011. +
  2012. +/*
  2013. + * test if the branch is deletable or not.
  2014. + */
  2015. +static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
  2016. +{
  2017. + int err, i, j, sigen;
  2018. + struct au_dcsub_pages dpages;
  2019. +
  2020. + LKTRTrace("b%d\n", bindex);
  2021. + SiMustWriteLock(root->d_sb);
  2022. + DiMustWriteLock(root);
  2023. +
  2024. + err = au_dpages_init(&dpages, GFP_KERNEL);
  2025. + if (unlikely(err))
  2026. + goto out;
  2027. + err = au_dcsub_pages(&dpages, root, NULL, NULL);
  2028. + if (unlikely(err))
  2029. + goto out_dpages;
  2030. +
  2031. + sigen = au_sigen(root->d_sb);
  2032. + DiMustNoWaiters(root);
  2033. + IiMustNoWaiters(root->d_inode);
  2034. + di_write_unlock(root);
  2035. + for (i = 0; !err && i < dpages.ndpage; i++) {
  2036. + struct au_dpage *dpage;
  2037. + dpage = dpages.dpages + i;
  2038. + for (j = 0; !err && j < dpage->ndentry; j++) {
  2039. + struct dentry *d;
  2040. +
  2041. + d = dpage->dentries[j];
  2042. + if (au_digen(d) == sigen)
  2043. + di_read_lock_child(d, AUFS_I_RLOCK);
  2044. + else {
  2045. + di_write_lock_child(d);
  2046. + err = au_reval_dpath(d, sigen);
  2047. + if (!err)
  2048. + di_downgrade_lock(d, AUFS_I_RLOCK);
  2049. + else {
  2050. + di_write_unlock(d);
  2051. + break;
  2052. + }
  2053. + }
  2054. +
  2055. + if (au_h_dptr_i(d, bindex)
  2056. + && (!S_ISDIR(d->d_inode->i_mode)
  2057. + || dbstart(d) == dbend(d)))
  2058. + err = -EBUSY;
  2059. + di_read_unlock(d, AUFS_I_RLOCK);
  2060. + if (err)
  2061. + LKTRTrace("%.*s\n", DLNPair(d));
  2062. + }
  2063. + }
  2064. + di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
  2065. +
  2066. + out_dpages:
  2067. + au_dpages_free(&dpages);
  2068. + out:
  2069. + TraceErr(err);
  2070. + return err;
  2071. +}
  2072. +
  2073. +int br_del(struct super_block *sb, struct opt_del *del, int remount)
  2074. +{
  2075. + int err, do_wh, rerr;
  2076. + struct dentry *root;
  2077. + struct inode *inode, *hidden_dir;
  2078. + aufs_bindex_t bindex, bend, br_id;
  2079. + struct aufs_sbinfo *sbinfo;
  2080. + struct aufs_dinfo *dinfo;
  2081. + struct aufs_iinfo *iinfo;
  2082. + struct aufs_branch *br;
  2083. +
  2084. + LKTRTrace("%s, %.*s\n", del->path, DLNPair(del->h_root));
  2085. + SiMustWriteLock(sb);
  2086. + root = sb->s_root;
  2087. + DiMustWriteLock(root);
  2088. + inode = root->d_inode;
  2089. + IiMustWriteLock(inode);
  2090. +
  2091. + bindex = au_find_dbindex(root, del->h_root);
  2092. + if (unlikely(bindex < 0)) {
  2093. + if (remount)
  2094. + return 0; /* success */
  2095. + err = -ENOENT;
  2096. + Err("%s no such branch\n", del->path);
  2097. + goto out;
  2098. + }
  2099. + LKTRTrace("bindex b%d\n", bindex);
  2100. +
  2101. + err = -EBUSY;
  2102. + bend = sbend(sb);
  2103. + br = stobr(sb, bindex);
  2104. + if (unlikely(!bend || br_count(br))) {
  2105. + LKTRTrace("bend %d, br_count %d\n", bend, br_count(br));
  2106. + goto out;
  2107. + }
  2108. +
  2109. + do_wh = 0;
  2110. + hidden_dir = del->h_root->d_inode;
  2111. + if (unlikely(br->br_wh || br->br_plink)) {
  2112. +#if 0
  2113. + /* remove whiteout base */
  2114. + err = init_br_wh(sb, bindex, br, AuBr_RO, del->h_root,
  2115. + br->br_mnt);
  2116. + if (unlikely(err))
  2117. + goto out;
  2118. +#else
  2119. + dput(br->br_wh);
  2120. + dput(br->br_plink);
  2121. + br->br_wh = br->br_plink = NULL;
  2122. +#endif
  2123. + do_wh = 1;
  2124. + }
  2125. +
  2126. + err = test_children_busy(root, bindex);
  2127. + if (unlikely(err)) {
  2128. + if (unlikely(do_wh))
  2129. + goto out_wh;
  2130. + goto out;
  2131. + }
  2132. +
  2133. + err = 0;
  2134. + sbinfo = stosi(sb);
  2135. + dinfo = dtodi(root);
  2136. + iinfo = itoii(inode);
  2137. +
  2138. + dput(au_h_dptr_i(root, bindex));
  2139. + aufs_hiput(iinfo->ii_hinode + bindex);
  2140. + br_id = br->br_id;
  2141. + free_branch(br);
  2142. +
  2143. + //todo: realloc and shrink memeory
  2144. + if (bindex < bend) {
  2145. + const aufs_bindex_t n = bend - bindex;
  2146. + struct aufs_branch **brp;
  2147. + struct aufs_hdentry *hdp;
  2148. + struct aufs_hinode *hip;
  2149. +
  2150. + brp = sbinfo->si_branch + bindex;
  2151. + memmove(brp, brp + 1, sizeof(*brp) * n);
  2152. + hdp = dinfo->di_hdentry + bindex;
  2153. + memmove(hdp, hdp + 1, sizeof(*hdp) * n);
  2154. + hip = iinfo->ii_hinode + bindex;
  2155. + memmove(hip, hip + 1, sizeof(*hip) * n);
  2156. + }
  2157. + sbinfo->si_branch[0 + bend] = NULL;
  2158. + dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
  2159. + iinfo->ii_hinode[0 + bend].hi_inode = NULL;
  2160. + iinfo->ii_hinode[0 + bend].hi_notify = NULL;
  2161. +
  2162. + sbinfo->si_bend--;
  2163. + dinfo->di_bend--;
  2164. + iinfo->ii_bend--;
  2165. + if (!bindex)
  2166. + au_cpup_attr_all(inode);
  2167. + else
  2168. + au_sub_nlink(inode, del->h_root->d_inode);
  2169. + if (au_flag_test(sb, AuFlag_PLINK))
  2170. + half_refresh_plink(sb, br_id);
  2171. +
  2172. + if (sb->s_maxbytes == del->h_root->d_sb->s_maxbytes) {
  2173. + bend--;
  2174. + sb->s_maxbytes = 0;
  2175. + for (bindex = 0; bindex <= bend; bindex++) {
  2176. + unsigned long long maxb;
  2177. + maxb = sbr_sb(sb, bindex)->s_maxbytes;
  2178. + if (sb->s_maxbytes < maxb)
  2179. + sb->s_maxbytes = maxb;
  2180. + }
  2181. + }
  2182. + goto out; /* success */
  2183. +
  2184. + out_wh:
  2185. + /* revert */
  2186. + rerr = init_br_wh(sb, bindex, br, br->br_perm, del->h_root, br->br_mnt);
  2187. + if (rerr)
  2188. + Warn("failed re-creating base whiteout, %s. (%d)\n",
  2189. + del->path, rerr);
  2190. + out:
  2191. + TraceErr(err);
  2192. + return err;
  2193. +}
  2194. +
  2195. +static int do_need_sigen_inc(int a, int b)
  2196. +{
  2197. + return (br_whable(a) && !br_whable(b));
  2198. +}
  2199. +
  2200. +static int need_sigen_inc(int old, int new)
  2201. +{
  2202. + return (do_need_sigen_inc(old, new)
  2203. + || do_need_sigen_inc(new, old));
  2204. +}
  2205. +
  2206. +int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
  2207. + int *do_update)
  2208. +{
  2209. + int err;
  2210. + struct dentry *root;
  2211. + aufs_bindex_t bindex;
  2212. + struct aufs_branch *br;
  2213. + struct inode *hidden_dir;
  2214. +
  2215. + LKTRTrace("%s, %.*s, 0x%x\n",
  2216. + mod->path, DLNPair(mod->h_root), mod->perm);
  2217. + SiMustWriteLock(sb);
  2218. + root = sb->s_root;
  2219. + DiMustWriteLock(root);
  2220. + IiMustWriteLock(root->d_inode);
  2221. +
  2222. + bindex = au_find_dbindex(root, mod->h_root);
  2223. + if (unlikely(bindex < 0)) {
  2224. + if (remount)
  2225. + return 0; /* success */
  2226. + err = -ENOENT;
  2227. + Err("%s no such branch\n", mod->path);
  2228. + goto out;
  2229. + }
  2230. + LKTRTrace("bindex b%d\n", bindex);
  2231. +
  2232. + hidden_dir = mod->h_root->d_inode;
  2233. + err = test_br(sb, hidden_dir, mod->perm, mod->path);
  2234. + if (unlikely(err))
  2235. + goto out;
  2236. +
  2237. + br = stobr(sb, bindex);
  2238. + if (unlikely(br->br_perm == mod->perm))
  2239. + return 0; /* success */
  2240. +
  2241. + if (br_writable(br->br_perm)) {
  2242. +#if 1
  2243. + /* remove whiteout base */
  2244. + //todo: mod->perm?
  2245. + err = init_br_wh(sb, bindex, br, AuBr_RO, mod->h_root,
  2246. + br->br_mnt);
  2247. + if (unlikely(err))
  2248. + goto out;
  2249. +#else
  2250. + dput(br->br_wh);
  2251. + dput(br->br_plink);
  2252. + br->br_wh = br->br_plink = NULL;
  2253. +#endif
  2254. +
  2255. + if (!br_writable(mod->perm)) {
  2256. + /* rw --> ro, file might be mmapped */
  2257. + struct file *file, *hf;
  2258. +
  2259. +#if 1 // test here
  2260. + DiMustNoWaiters(root);
  2261. + IiMustNoWaiters(root->d_inode);
  2262. + di_write_unlock(root);
  2263. +
  2264. + // no need file_list_lock() since sbinfo is locked
  2265. + //file_list_lock();
  2266. + list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
  2267. + LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
  2268. + fi_read_lock(file);
  2269. + if (!S_ISREG(file->f_dentry->d_inode->i_mode)
  2270. + || !(file->f_mode & FMODE_WRITE)
  2271. + || fbstart(file) != bindex) {
  2272. + FiMustNoWaiters(file);
  2273. + fi_read_unlock(file);
  2274. + continue;
  2275. + }
  2276. +
  2277. + // todo: already flushed?
  2278. + hf = au_h_fptr(file);
  2279. + hf->f_flags = au_file_roflags(hf->f_flags);
  2280. + hf->f_mode &= ~FMODE_WRITE;
  2281. + FiMustNoWaiters(file);
  2282. + fi_read_unlock(file);
  2283. + }
  2284. + //file_list_unlock();
  2285. +
  2286. + /* aufs_write_lock() calls ..._child() */
  2287. + di_write_lock_child(root);
  2288. +#endif
  2289. + }
  2290. + }
  2291. +
  2292. + *do_update |= need_sigen_inc(br->br_perm, mod->perm);
  2293. + br->br_perm = mod->perm;
  2294. + return err; /* success */
  2295. +
  2296. + out:
  2297. + TraceErr(err);
  2298. + return err;
  2299. +}
  2300. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/branch.h linux-2.6.22.1/fs/aufs/branch.h
  2301. --- linux-2.6.22.1.oorig/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
  2302. +++ linux-2.6.22.1/fs/aufs/branch.h 2007-07-24 14:17:46.000000000 +0200
  2303. @@ -0,0 +1,235 @@
  2304. +/*
  2305. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  2306. + *
  2307. + * This program, aufs is free software; you can redistribute it and/or modify
  2308. + * it under the terms of the GNU General Public License as published by
  2309. + * the Free Software Foundation; either version 2 of the License, or
  2310. + * (at your option) any later version.
  2311. + *
  2312. + * This program is distributed in the hope that it will be useful,
  2313. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2314. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2315. + * GNU General Public License for more details.
  2316. + *
  2317. + * You should have received a copy of the GNU General Public License
  2318. + * along with this program; if not, write to the Free Software
  2319. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  2320. + */
  2321. +
  2322. +/* $Id: branch.h,v 1.30 2007/05/14 03:41:51 sfjro Exp $ */
  2323. +
  2324. +#ifndef __AUFS_BRANCH_H__
  2325. +#define __AUFS_BRANCH_H__
  2326. +
  2327. +#ifdef __KERNEL__
  2328. +
  2329. +#include <linux/fs.h>
  2330. +#include <linux/mount.h>
  2331. +#include <linux/version.h>
  2332. +#include <linux/aufs_type.h>
  2333. +#include "misc.h"
  2334. +#include "super.h"
  2335. +
  2336. +/* protected by superblock rwsem */
  2337. +struct aufs_branch {
  2338. + struct file *br_xino;
  2339. + readf_t br_xino_read;
  2340. + writef_t br_xino_write;
  2341. +
  2342. + aufs_bindex_t br_id;
  2343. +
  2344. + int br_perm;
  2345. + struct vfsmount *br_mnt;
  2346. + atomic_t br_count;
  2347. +
  2348. + /* whiteout base */
  2349. + struct aufs_rwsem br_wh_rwsem;
  2350. + struct dentry *br_wh;
  2351. + atomic_t br_wh_running;
  2352. +
  2353. + /* pseudo-link dir */
  2354. + struct dentry *br_plink;
  2355. +};
  2356. +
  2357. +/* ---------------------------------------------------------------------- */
  2358. +
  2359. +/* branch permission and attribute */
  2360. +enum {
  2361. + AuBr_RW, /* writable, linkable wh */
  2362. + AuBr_RO, /* readonly, no wh */
  2363. + AuBr_RR, /* natively readonly, no wh */
  2364. +
  2365. + AuBr_RWNoLinkWH, /* un-linkable whiteouts */
  2366. +
  2367. + AuBr_ROWH,
  2368. + AuBr_RRWH, /* whiteout-able */
  2369. +
  2370. + AuBr_Last
  2371. +};
  2372. +
  2373. +static inline int br_writable(int brperm)
  2374. +{
  2375. + return (brperm == AuBr_RW
  2376. + || brperm == AuBr_RWNoLinkWH);
  2377. +}
  2378. +
  2379. +static inline int br_whable(int brperm)
  2380. +{
  2381. + return (brperm == AuBr_RW
  2382. + || brperm == AuBr_ROWH
  2383. + || brperm == AuBr_RRWH);
  2384. +}
  2385. +
  2386. +static inline int br_linkable_wh(int brperm)
  2387. +{
  2388. + return (brperm == AuBr_RW);
  2389. +}
  2390. +
  2391. +/* ---------------------------------------------------------------------- */
  2392. +
  2393. +#define _AuNoNfsBranchMsg "NFS branch is not supported"
  2394. +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,15)
  2395. +#define AuNoNfsBranch
  2396. +#define AuNoNfsBranchMsg _AuNoNfsBranchMsg
  2397. +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) \
  2398. + && !defined(CONFIG_AUFS_LHASH_PATCH)
  2399. +#define AuNoNfsBranch
  2400. +#define AuNoNfsBranchMsg _AuNoNfsBranchMsg \
  2401. + ", try lhash.patch and CONFIG_AUFS_LHASH_PATCH"
  2402. +#endif
  2403. +
  2404. +/* ---------------------------------------------------------------------- */
  2405. +
  2406. +struct aufs_sbinfo;
  2407. +void free_branches(struct aufs_sbinfo *sinfo);
  2408. +int br_rdonly(struct aufs_branch *br);
  2409. +int find_brindex(struct super_block *sb, aufs_bindex_t br_id);
  2410. +int find_rw_br(struct super_block *sb, aufs_bindex_t bend);
  2411. +int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend);
  2412. +struct opt_add;
  2413. +int br_add(struct super_block *sb, struct opt_add *add, int remount);
  2414. +struct opt_del;
  2415. +int br_del(struct super_block *sb, struct opt_del *del, int remount);
  2416. +struct opt_mod;
  2417. +int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
  2418. + int *do_update);
  2419. +
  2420. +/* ---------------------------------------------------------------------- */
  2421. +
  2422. +static inline int br_count(struct aufs_branch *br)
  2423. +{
  2424. + return atomic_read(&br->br_count);
  2425. +}
  2426. +
  2427. +static inline void br_get(struct aufs_branch *br)
  2428. +{
  2429. + atomic_inc(&br->br_count);
  2430. +}
  2431. +
  2432. +static inline void br_put(struct aufs_branch *br)
  2433. +{
  2434. + atomic_dec(&br->br_count);
  2435. +}
  2436. +
  2437. +/* ---------------------------------------------------------------------- */
  2438. +
  2439. +/* Superblock to branch */
  2440. +static inline aufs_bindex_t sbr_id(struct super_block *sb, aufs_bindex_t bindex)
  2441. +{
  2442. + return stobr(sb, bindex)->br_id;
  2443. +}
  2444. +
  2445. +static inline
  2446. +struct vfsmount *sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
  2447. +{
  2448. + return stobr(sb, bindex)->br_mnt;
  2449. +}
  2450. +
  2451. +static inline
  2452. +struct super_block *sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
  2453. +{
  2454. + return sbr_mnt(sb, bindex)->mnt_sb;
  2455. +}
  2456. +
  2457. +#if 0
  2458. +static inline int sbr_count(struct super_block *sb, aufs_bindex_t bindex)
  2459. +{
  2460. + return br_count(stobr(sb, bindex));
  2461. +}
  2462. +
  2463. +static inline void sbr_get(struct super_block *sb, aufs_bindex_t bindex)
  2464. +{
  2465. + br_get(stobr(sb, bindex));
  2466. +}
  2467. +#endif
  2468. +
  2469. +static inline void sbr_put(struct super_block *sb, aufs_bindex_t bindex)
  2470. +{
  2471. + br_put(stobr(sb, bindex));
  2472. +}
  2473. +
  2474. +static inline int sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
  2475. +{
  2476. + return stobr(sb, bindex)->br_perm;
  2477. +}
  2478. +
  2479. +static inline int sbr_is_whable(struct super_block *sb, aufs_bindex_t bindex)
  2480. +{
  2481. + return br_whable(sbr_perm(sb, bindex));
  2482. +}
  2483. +
  2484. +/* ---------------------------------------------------------------------- */
  2485. +
  2486. +#ifdef CONFIG_AUFS_LHASH_PATCH
  2487. +static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
  2488. +{
  2489. + if (!au_is_nfs(h_mnt->mnt_sb))
  2490. + return NULL;
  2491. + return h_mnt;
  2492. +}
  2493. +
  2494. +/* it doesn't mntget() */
  2495. +static inline
  2496. +struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
  2497. +{
  2498. + return au_do_nfsmnt(sbr_mnt(sb, bindex));
  2499. +}
  2500. +#else
  2501. +static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
  2502. +{
  2503. + return NULL;
  2504. +}
  2505. +
  2506. +static inline
  2507. +struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
  2508. +{
  2509. + return NULL;
  2510. +}
  2511. +#endif /* CONFIG_AUFS_LHASH_PATCH */
  2512. +
  2513. +/* ---------------------------------------------------------------------- */
  2514. +
  2515. +/*
  2516. + * br_wh_read_lock, br_wh_write_lock
  2517. + * br_wh_read_unlock, br_wh_write_unlock, br_wh_downgrade_lock
  2518. + */
  2519. +SimpleRwsemFuncs(br_wh, struct aufs_branch *br, br->br_wh_rwsem);
  2520. +
  2521. +/* to debug easier, do not make them inlined functions */
  2522. +#define BrWhMustReadLock(br) do { \
  2523. + /* SiMustAnyLock(sb); */ \
  2524. + RwMustReadLock(&(br)->br_wh_rwsem); \
  2525. +} while (0)
  2526. +
  2527. +#define BrWhMustWriteLock(br) do { \
  2528. + /* SiMustAnyLock(sb); */ \
  2529. + RwMustWriteLock(&(br)->br_wh_rwsem); \
  2530. +} while (0)
  2531. +
  2532. +#define BrWhMustAnyLock(br) do { \
  2533. + /* SiMustAnyLock(sb); */ \
  2534. + RwMustAnyLock(&(br)->br_wh_rwsem); \
  2535. +} while (0)
  2536. +
  2537. +#endif /* __KERNEL__ */
  2538. +#endif /* __AUFS_BRANCH_H__ */
  2539. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/cpup.c linux-2.6.22.1/fs/aufs/cpup.c
  2540. --- linux-2.6.22.1.oorig/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
  2541. +++ linux-2.6.22.1/fs/aufs/cpup.c 2007-07-24 14:17:46.000000000 +0200
  2542. @@ -0,0 +1,773 @@
  2543. +/*
  2544. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  2545. + *
  2546. + * This program, aufs is free software; you can redistribute it and/or modify
  2547. + * it under the terms of the GNU General Public License as published by
  2548. + * the Free Software Foundation; either version 2 of the License, or
  2549. + * (at your option) any later version.
  2550. + *
  2551. + * This program is distributed in the hope that it will be useful,
  2552. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2553. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2554. + * GNU General Public License for more details.
  2555. + *
  2556. + * You should have received a copy of the GNU General Public License
  2557. + * along with this program; if not, write to the Free Software
  2558. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  2559. + */
  2560. +
  2561. +/* $Id: cpup.c,v 1.37 2007/05/14 03:41:52 sfjro Exp $ */
  2562. +
  2563. +#include <asm/uaccess.h>
  2564. +#include "aufs.h"
  2565. +
  2566. +/* violent cpup_attr_*() functions don't care inode lock */
  2567. +void au_cpup_attr_timesizes(struct inode *inode)
  2568. +{
  2569. + struct inode *hidden_inode;
  2570. +
  2571. + LKTRTrace("i%lu\n", inode->i_ino);
  2572. + //IMustLock(inode);
  2573. + hidden_inode = au_h_iptr(inode);
  2574. + DEBUG_ON(!hidden_inode);
  2575. + //IMustLock(!hidden_inode);
  2576. +
  2577. + inode->i_atime = hidden_inode->i_atime;
  2578. + inode->i_mtime = hidden_inode->i_mtime;
  2579. + inode->i_ctime = hidden_inode->i_ctime;
  2580. + spin_lock(&inode->i_lock);
  2581. + i_size_write(inode, i_size_read(hidden_inode));
  2582. + inode->i_blocks = hidden_inode->i_blocks;
  2583. + spin_unlock(&inode->i_lock);
  2584. +}
  2585. +
  2586. +void au_cpup_attr_nlink(struct inode *inode)
  2587. +{
  2588. + struct inode *h_inode;
  2589. +
  2590. + LKTRTrace("i%lu\n", inode->i_ino);
  2591. + //IMustLock(inode);
  2592. + DEBUG_ON(!inode->i_mode);
  2593. +
  2594. + h_inode = au_h_iptr(inode);
  2595. + inode->i_nlink = h_inode->i_nlink;
  2596. +
  2597. + /*
  2598. + * fewer nlink makes find(1) noisy, but larger nlink doesn't.
  2599. + * it may includes whplink directory.
  2600. + */
  2601. + if (unlikely(S_ISDIR(h_inode->i_mode))) {
  2602. + aufs_bindex_t bindex, bend;
  2603. + bend = ibend(inode);
  2604. + for (bindex = ibstart(inode) + 1; bindex <= bend; bindex++) {
  2605. + h_inode = au_h_iptr_i(inode, bindex);
  2606. + if (h_inode)
  2607. + au_add_nlink(inode, h_inode);
  2608. + }
  2609. + }
  2610. +}
  2611. +
  2612. +void au_cpup_attr_changable(struct inode *inode)
  2613. +{
  2614. + struct inode *hidden_inode;
  2615. +
  2616. + LKTRTrace("i%lu\n", inode->i_ino);
  2617. + //IMustLock(inode);
  2618. + hidden_inode = au_h_iptr(inode);
  2619. + DEBUG_ON(!hidden_inode);
  2620. +
  2621. + inode->i_mode = hidden_inode->i_mode;
  2622. + inode->i_uid = hidden_inode->i_uid;
  2623. + inode->i_gid = hidden_inode->i_gid;
  2624. + au_cpup_attr_timesizes(inode);
  2625. +
  2626. + //??
  2627. + inode->i_flags = hidden_inode->i_flags;
  2628. +}
  2629. +
  2630. +void au_cpup_igen(struct inode *inode, struct inode *h_inode)
  2631. +{
  2632. + inode->i_generation = h_inode->i_generation;
  2633. + itoii(inode)->ii_hsb1 = h_inode->i_sb;
  2634. +}
  2635. +
  2636. +void au_cpup_attr_all(struct inode *inode)
  2637. +{
  2638. + struct inode *hidden_inode;
  2639. +
  2640. + LKTRTrace("i%lu\n", inode->i_ino);
  2641. + //IMustLock(inode);
  2642. + hidden_inode = au_h_iptr(inode);
  2643. + DEBUG_ON(!hidden_inode);
  2644. +
  2645. + au_cpup_attr_changable(inode);
  2646. + if (inode->i_nlink > 0)
  2647. + au_cpup_attr_nlink(inode);
  2648. +
  2649. + switch (inode->i_mode & S_IFMT) {
  2650. + case S_IFBLK:
  2651. + case S_IFCHR:
  2652. + inode->i_rdev = hidden_inode->i_rdev;
  2653. + }
  2654. + inode->i_blkbits = hidden_inode->i_blkbits;
  2655. + au_cpup_attr_blksize(inode, hidden_inode);
  2656. + au_cpup_igen(inode, hidden_inode);
  2657. +}
  2658. +
  2659. +/* ---------------------------------------------------------------------- */
  2660. +
  2661. +/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
  2662. +
  2663. +/* keep the timestamps of the parent dir when cpup */
  2664. +void dtime_store(struct dtime *dt, struct dentry *dentry,
  2665. + struct dentry *hidden_dentry)
  2666. +{
  2667. + struct inode *inode;
  2668. +
  2669. + TraceEnter();
  2670. + DEBUG_ON(!dentry || !hidden_dentry || !hidden_dentry->d_inode);
  2671. +
  2672. + dt->dt_dentry = dentry;
  2673. + dt->dt_h_dentry = hidden_dentry;
  2674. + inode = hidden_dentry->d_inode;
  2675. + dt->dt_atime = inode->i_atime;
  2676. + dt->dt_mtime = inode->i_mtime;
  2677. + //smp_mb();
  2678. +}
  2679. +
  2680. +// todo: remove extra parameter
  2681. +void dtime_revert(struct dtime *dt, int h_parent_is_locked)
  2682. +{
  2683. + struct iattr attr;
  2684. + int err;
  2685. + struct dentry *dentry;
  2686. +
  2687. + LKTRTrace("h_parent locked %d\n", h_parent_is_locked);
  2688. +
  2689. + attr.ia_atime = dt->dt_atime;
  2690. + attr.ia_mtime = dt->dt_mtime;
  2691. + attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
  2692. + | ATTR_ATIME | ATTR_ATIME_SET;
  2693. + //smp_mb();
  2694. + dentry = NULL;
  2695. + if (!h_parent_is_locked /* && !IS_ROOT(dt->dt_dentry) */)
  2696. + dentry = dt->dt_dentry;
  2697. + err = vfsub_notify_change(dt->dt_h_dentry, &attr,
  2698. + need_dlgt(dt->dt_dentry->d_sb));
  2699. + if (unlikely(err))
  2700. + Warn("restoring timestamps failed(%d). ignored\n", err);
  2701. +}
  2702. +
  2703. +/* ---------------------------------------------------------------------- */
  2704. +
  2705. +static int cpup_iattr(struct dentry *hidden_dst, struct dentry *hidden_src,
  2706. + int dlgt)
  2707. +{
  2708. + int err;
  2709. + struct iattr ia;
  2710. + struct inode *hidden_isrc, *hidden_idst;
  2711. +
  2712. + LKTRTrace("%.*s\n", DLNPair(hidden_dst));
  2713. + hidden_idst = hidden_dst->d_inode;
  2714. + //IMustLock(hidden_idst);
  2715. + hidden_isrc = hidden_src->d_inode;
  2716. + //IMustLock(hidden_isrc);
  2717. +
  2718. + ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
  2719. + | ATTR_ATIME | ATTR_MTIME
  2720. + | ATTR_ATIME_SET | ATTR_MTIME_SET;
  2721. + ia.ia_mode = hidden_isrc->i_mode;
  2722. + ia.ia_uid = hidden_isrc->i_uid;
  2723. + ia.ia_gid = hidden_isrc->i_gid;
  2724. + ia.ia_atime = hidden_isrc->i_atime;
  2725. + ia.ia_mtime = hidden_isrc->i_mtime;
  2726. + err = vfsub_notify_change(hidden_dst, &ia, dlgt);
  2727. + //if (LktrCond) err = -1;
  2728. + if (!err)
  2729. + hidden_idst->i_flags = hidden_isrc->i_flags; //??
  2730. +
  2731. + TraceErr(err);
  2732. + return err;
  2733. +}
  2734. +
  2735. +/*
  2736. + * to support a sparse file which is opened with O_APPEND,
  2737. + * we need to close the file.
  2738. + */
  2739. +static int cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
  2740. + aufs_bindex_t bsrc, loff_t len)
  2741. +{
  2742. + int err, i, sparse;
  2743. + struct super_block *sb;
  2744. + struct inode *hidden_inode;
  2745. + enum {SRC, DST};
  2746. + struct {
  2747. + aufs_bindex_t bindex;
  2748. + unsigned int flags;
  2749. + struct dentry *dentry;
  2750. + struct file *file;
  2751. + void *label, *label_file;
  2752. + } *h, hidden[] = {
  2753. + {
  2754. + .bindex = bsrc,
  2755. + .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
  2756. + .file = NULL,
  2757. + .label = &&out,
  2758. + .label_file = &&out_src_file
  2759. + },
  2760. + {
  2761. + .bindex = bdst,
  2762. + .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
  2763. + .file = NULL,
  2764. + .label = &&out_src_file,
  2765. + .label_file = &&out_dst_file
  2766. + }
  2767. + };
  2768. +
  2769. + LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
  2770. + DLNPair(dentry), bdst, bsrc, len);
  2771. + DEBUG_ON(bsrc <= bdst);
  2772. + DEBUG_ON(!len);
  2773. + sb = dentry->d_sb;
  2774. + DEBUG_ON(test_ro(sb, bdst, dentry->d_inode));
  2775. + // bsrc branch can be ro/rw.
  2776. +
  2777. + h = hidden;
  2778. + for (i = 0; i < 2; i++, h++) {
  2779. + h->dentry = au_h_dptr_i(dentry, h->bindex);
  2780. + DEBUG_ON(!h->dentry);
  2781. + hidden_inode = h->dentry->d_inode;
  2782. + DEBUG_ON(!hidden_inode || !S_ISREG(hidden_inode->i_mode));
  2783. + h->file = hidden_open(dentry, h->bindex, h->flags);
  2784. + //if (LktrCond)
  2785. + //{fput(h->file); sbr_put(sb, h->bindex); h->file = ERR_PTR(-1);}
  2786. + err = PTR_ERR(h->file);
  2787. + if (IS_ERR(h->file))
  2788. + goto *h->label;
  2789. + err = -EINVAL;
  2790. + if (unlikely(!h->file->f_op))
  2791. + goto *h->label_file;
  2792. + }
  2793. +
  2794. + /* stop updating while we copyup */
  2795. + IMustLock(hidden[SRC].dentry->d_inode);
  2796. + sparse = 0;
  2797. + err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb,
  2798. + &sparse);
  2799. +
  2800. + /* sparse file: update i_blocks next time */
  2801. + if (unlikely(!err && sparse))
  2802. + d_drop(dentry);
  2803. +
  2804. + out_dst_file:
  2805. + fput(hidden[DST].file);
  2806. + sbr_put(sb, hidden[DST].bindex);
  2807. + out_src_file:
  2808. + fput(hidden[SRC].file);
  2809. + sbr_put(sb, hidden[SRC].bindex);
  2810. + out:
  2811. + TraceErr(err);
  2812. + return err;
  2813. +}
  2814. +
  2815. +// unnecessary?
  2816. +unsigned int au_flags_cpup(unsigned int init, struct dentry *parent)
  2817. +{
  2818. + if (unlikely(parent && IS_ROOT(parent)))
  2819. + init |= CPUP_LOCKED_GHDIR;
  2820. + return init;
  2821. +}
  2822. +
  2823. +/* return with hidden dst inode is locked */
  2824. +static int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
  2825. + aufs_bindex_t bsrc, loff_t len, unsigned int flags,
  2826. + int dlgt)
  2827. +{
  2828. + int err, isdir, symlen;
  2829. + struct dentry *hidden_src, *hidden_dst, *hidden_parent, *parent;
  2830. + struct inode *hidden_inode, *hidden_dir, *dir;
  2831. + struct dtime dt;
  2832. + umode_t mode;
  2833. + char *sym;
  2834. + mm_segment_t old_fs;
  2835. + const int do_dt = flags & CPUP_DTIME;
  2836. + struct super_block *sb;
  2837. +
  2838. + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
  2839. + DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
  2840. + flags);
  2841. + sb = dentry->d_sb;
  2842. + DEBUG_ON(bdst >= bsrc || test_ro(sb, bdst, NULL));
  2843. + // bsrc branch can be ro/rw.
  2844. +
  2845. + hidden_src = au_h_dptr_i(dentry, bsrc);
  2846. + DEBUG_ON(!hidden_src);
  2847. + hidden_inode = hidden_src->d_inode;
  2848. + DEBUG_ON(!hidden_inode);
  2849. +
  2850. + /* stop refrencing while we are creating */
  2851. + //parent = dget_parent(dentry);
  2852. + parent = dentry->d_parent;
  2853. + dir = parent->d_inode;
  2854. + hidden_dst = au_h_dptr_i(dentry, bdst);
  2855. + DEBUG_ON(hidden_dst && hidden_dst->d_inode);
  2856. + //hidden_parent = dget_parent(hidden_dst);
  2857. + hidden_parent = hidden_dst->d_parent;
  2858. + hidden_dir = hidden_parent->d_inode;
  2859. + IMustLock(hidden_dir);
  2860. +
  2861. + if (do_dt)
  2862. + dtime_store(&dt, parent, hidden_parent);
  2863. +
  2864. + isdir = 0;
  2865. + mode = hidden_inode->i_mode;
  2866. + switch (mode & S_IFMT) {
  2867. + case S_IFREG:
  2868. + /* stop updating while we are referencing */
  2869. + IMustLock(hidden_inode);
  2870. + err = vfsub_create(hidden_dir, hidden_dst, mode | S_IWUSR, NULL,
  2871. + dlgt);
  2872. + //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
  2873. + if (!err) {
  2874. + loff_t l = i_size_read(hidden_inode);
  2875. + if (len == -1 || l < len)
  2876. + len = l;
  2877. + if (len) {
  2878. + err = cpup_regular(dentry, bdst, bsrc, len);
  2879. + //if (LktrCond) err = -1;
  2880. + }
  2881. + if (unlikely(err)) {
  2882. + int rerr;
  2883. + rerr = vfsub_unlink(hidden_dir, hidden_dst,
  2884. + dlgt);
  2885. + if (rerr) {
  2886. + IOErr("failed unlinking cpup-ed %.*s"
  2887. + "(%d, %d)\n",
  2888. + DLNPair(hidden_dst), err, rerr);
  2889. + err = -EIO;
  2890. + }
  2891. + }
  2892. + }
  2893. + break;
  2894. + case S_IFDIR:
  2895. + isdir = 1;
  2896. + err = vfsub_mkdir(hidden_dir, hidden_dst, mode, dlgt);
  2897. + //if (LktrCond) {vfs_rmdir(hidden_dir, hidden_dst); err = -1;}
  2898. + if (!err) {
  2899. + /* setattr case: dir is not locked */
  2900. + if (0 && ibstart(dir) == bdst)
  2901. + au_cpup_attr_nlink(dir);
  2902. + au_cpup_attr_nlink(dentry->d_inode);
  2903. + }
  2904. + break;
  2905. + case S_IFLNK:
  2906. + err = -ENOMEM;
  2907. + sym = __getname();
  2908. + //if (LktrCond) {__putname(sym); sym = NULL;}
  2909. + if (unlikely(!sym))
  2910. + break;
  2911. + old_fs = get_fs();
  2912. + set_fs(KERNEL_DS);
  2913. + err = symlen = hidden_inode->i_op->readlink
  2914. + (hidden_src, (char __user*)sym, PATH_MAX);
  2915. + //if (LktrCond) err = symlen = -1;
  2916. + set_fs(old_fs);
  2917. + if (symlen > 0) {
  2918. + sym[symlen] = 0;
  2919. + err = vfsub_symlink(hidden_dir, hidden_dst, sym, mode,
  2920. + dlgt);
  2921. + //if (LktrCond)
  2922. + //{vfs_unlink(hidden_dir, hidden_dst); err = -1;}
  2923. + }
  2924. + __putname(sym);
  2925. + break;
  2926. + case S_IFCHR:
  2927. + case S_IFBLK:
  2928. + DEBUG_ON(!capable(CAP_MKNOD));
  2929. + /*FALLTHROUGH*/
  2930. + case S_IFIFO:
  2931. + case S_IFSOCK:
  2932. + err = vfsub_mknod(hidden_dir, hidden_dst, mode,
  2933. + hidden_inode->i_rdev, dlgt);
  2934. + //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
  2935. + break;
  2936. + default:
  2937. + IOErr("Unknown inode type 0%o\n", mode);
  2938. + err = -EIO;
  2939. + }
  2940. +
  2941. + if (do_dt)
  2942. + dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
  2943. + //dput(parent);
  2944. + //dput(hidden_parent);
  2945. + TraceErr(err);
  2946. + return err;
  2947. +}
  2948. +
  2949. +/*
  2950. + * copyup the @dentry from @bsrc to @bdst.
  2951. + * the caller must set the both of hidden dentries.
  2952. + * @len is for trucating when it is -1 copyup the entire file.
  2953. + */
  2954. +int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
  2955. + loff_t len, unsigned int flags)
  2956. +{
  2957. + int err, rerr, isdir, dlgt;
  2958. + struct dentry *hidden_src, *hidden_dst, *parent;//, *h_parent;
  2959. + struct inode *dst_inode, *hidden_dir, *inode, *src_inode;
  2960. + struct super_block *sb;
  2961. + aufs_bindex_t old_ibstart;
  2962. + struct dtime dt;
  2963. +
  2964. + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
  2965. + DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
  2966. + flags);
  2967. + sb = dentry->d_sb;
  2968. + DEBUG_ON(bsrc <= bdst);
  2969. + hidden_dst = au_h_dptr_i(dentry, bdst);
  2970. + DEBUG_ON(!hidden_dst || hidden_dst->d_inode);
  2971. + //h_parent = dget_parent(hidden_dst);
  2972. + //hidden_dir = h_parent->d_inode;
  2973. + hidden_dir = hidden_dst->d_parent->d_inode;
  2974. + IMustLock(hidden_dir);
  2975. + hidden_src = au_h_dptr_i(dentry, bsrc);
  2976. + DEBUG_ON(!hidden_src || !hidden_src->d_inode);
  2977. + inode = dentry->d_inode;
  2978. + IiMustWriteLock(inode);
  2979. +
  2980. + dlgt = need_dlgt(sb);
  2981. + dst_inode = au_h_iptr_i(inode, bdst);
  2982. + if (unlikely(dst_inode)) {
  2983. + if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
  2984. + err = -EIO;
  2985. + IOErr("i%lu exists on a upper branch "
  2986. + "but plink is disabled\n", inode->i_ino);
  2987. + goto out;
  2988. + }
  2989. +
  2990. + if (dst_inode->i_nlink) {
  2991. + hidden_src = lkup_plink(sb, bdst, inode);
  2992. + err = PTR_ERR(hidden_src);
  2993. + if (IS_ERR(hidden_src))
  2994. + goto out;
  2995. + DEBUG_ON(!hidden_src->d_inode);
  2996. + // vfs_link() does lock the inode
  2997. + err = vfsub_link(hidden_src, hidden_dir, hidden_dst, dlgt);
  2998. + dput(hidden_src);
  2999. + goto out;
  3000. + } else
  3001. + /* udba work */
  3002. + au_update_brange(inode, 1);
  3003. + }
  3004. +
  3005. + old_ibstart = ibstart(inode);
  3006. + err = cpup_entry(dentry, bdst, bsrc, len, flags, dlgt);
  3007. + if (unlikely(err))
  3008. + goto out;
  3009. + dst_inode = hidden_dst->d_inode;
  3010. + hi_lock_child2(dst_inode);
  3011. +
  3012. + //todo: test dlgt
  3013. + err = cpup_iattr(hidden_dst, hidden_src, dlgt);
  3014. + //if (LktrCond) err = -1;
  3015. +#if 0 // xattr
  3016. + if (0 && !err)
  3017. + err = cpup_xattrs(hidden_src, hidden_dst);
  3018. +#endif
  3019. + isdir = S_ISDIR(dst_inode->i_mode);
  3020. + if (!err) {
  3021. + if (bdst < old_ibstart)
  3022. + set_ibstart(inode, bdst);
  3023. + set_h_iptr(inode, bdst, igrab(dst_inode),
  3024. + au_hi_flags(inode, isdir));
  3025. + i_unlock(dst_inode);
  3026. + src_inode = hidden_src->d_inode;
  3027. + if (!isdir) {
  3028. + if (src_inode->i_nlink > 1
  3029. + && au_flag_test(sb, AuFlag_PLINK))
  3030. + append_plink(sb, inode, hidden_dst, bdst);
  3031. + else {
  3032. + /* braces are added to stop a warning */
  3033. + ;//xino_write0(sb, bsrc, src_inode->i_ino);
  3034. + /* ignore this error */
  3035. + }
  3036. + }
  3037. + //goto out; /* success */
  3038. + return 0; /* success */
  3039. + }
  3040. +
  3041. + /* revert */
  3042. + i_unlock(dst_inode);
  3043. + parent = dget_parent(dentry);
  3044. + //dtime_store(&dt, parent, h_parent);
  3045. + dtime_store(&dt, parent, hidden_dst->d_parent);
  3046. + dput(parent);
  3047. + if (!isdir)
  3048. + rerr = vfsub_unlink(hidden_dir, hidden_dst, dlgt);
  3049. + else
  3050. + rerr = vfsub_rmdir(hidden_dir, hidden_dst, dlgt);
  3051. + //rerr = -1;
  3052. + dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
  3053. + if (rerr) {
  3054. + IOErr("failed removing broken entry(%d, %d)\n", err, rerr);
  3055. + err = -EIO;
  3056. + }
  3057. +
  3058. + out:
  3059. + //dput(h_parent);
  3060. + TraceErr(err);
  3061. + return err;
  3062. +}
  3063. +
  3064. +struct cpup_single_args {
  3065. + int *errp;
  3066. + struct dentry *dentry;
  3067. + aufs_bindex_t bdst, bsrc;
  3068. + loff_t len;
  3069. + unsigned int flags;
  3070. +};
  3071. +
  3072. +static void call_cpup_single(void *args)
  3073. +{
  3074. + struct cpup_single_args *a = args;
  3075. + *a->errp = cpup_single(a->dentry, a->bdst, a->bsrc, a->len, a->flags);
  3076. +}
  3077. +
  3078. +int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
  3079. + aufs_bindex_t bsrc, loff_t len, unsigned int flags)
  3080. +{
  3081. + int err;
  3082. + struct dentry *hidden_dentry;
  3083. + umode_t mode;
  3084. +
  3085. + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
  3086. + DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
  3087. + flags);
  3088. +
  3089. + hidden_dentry = au_h_dptr_i(dentry, bsrc);
  3090. + mode = hidden_dentry->d_inode->i_mode & S_IFMT;
  3091. + if ((mode != S_IFCHR && mode != S_IFBLK)
  3092. + || capable(CAP_MKNOD))
  3093. + err = cpup_single(dentry, bdst, bsrc, len, flags);
  3094. + else {
  3095. + struct cpup_single_args args = {
  3096. + .errp = &err,
  3097. + .dentry = dentry,
  3098. + .bdst = bdst,
  3099. + .bsrc = bsrc,
  3100. + .len = len,
  3101. + .flags = flags
  3102. + };
  3103. + au_wkq_wait(call_cpup_single, &args, /*dlgt*/0);
  3104. + }
  3105. +
  3106. + TraceErr(err);
  3107. + return err;
  3108. +}
  3109. +
  3110. +/*
  3111. + * copyup the @dentry from the first active hidden branch to @bdst,
  3112. + * using cpup_single().
  3113. + */
  3114. +int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3115. + unsigned int flags)
  3116. +{
  3117. + int err;
  3118. + struct inode *inode;
  3119. + aufs_bindex_t bsrc, bend;
  3120. +
  3121. + LKTRTrace("%.*s, bdst %d, len %Ld, flags 0x%x\n",
  3122. + DLNPair(dentry), bdst, len, flags);
  3123. + inode = dentry->d_inode;
  3124. + DEBUG_ON(!S_ISDIR(inode->i_mode) && dbstart(dentry) < bdst);
  3125. +
  3126. + bend = dbend(dentry);
  3127. + for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
  3128. + if (au_h_dptr_i(dentry, bsrc))
  3129. + break;
  3130. + DEBUG_ON(!au_h_dptr_i(dentry, bsrc));
  3131. +
  3132. + err = lkup_neg(dentry, bdst);
  3133. + //err = -1;
  3134. + if (!err) {
  3135. + err = cpup_single(dentry, bdst, bsrc, len, flags);
  3136. + if (!err)
  3137. + return 0; /* success */
  3138. +
  3139. + /* revert */
  3140. + set_h_dptr(dentry, bdst, NULL);
  3141. + set_dbstart(dentry, bsrc);
  3142. + }
  3143. +
  3144. + TraceErr(err);
  3145. + return err;
  3146. +}
  3147. +
  3148. +struct cpup_simple_args {
  3149. + int *errp;
  3150. + struct dentry *dentry;
  3151. + aufs_bindex_t bdst;
  3152. + loff_t len;
  3153. + unsigned int flags;
  3154. +};
  3155. +
  3156. +static void call_cpup_simple(void *args)
  3157. +{
  3158. + struct cpup_simple_args *a = args;
  3159. + *a->errp = cpup_simple(a->dentry, a->bdst, a->len, a->flags);
  3160. +}
  3161. +
  3162. +int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3163. + unsigned int flags)
  3164. +{
  3165. + int err, do_sio, dlgt;
  3166. + //struct dentry *parent;
  3167. + struct inode *hidden_dir, *dir;
  3168. +
  3169. + LKTRTrace("%.*s, b%d, len %Ld, flags 0x%x\n",
  3170. + DLNPair(dentry), bdst, len, flags);
  3171. +
  3172. + //parent = dget_parent(dentry);
  3173. + //dir = parent->d_inode;
  3174. + dir = dentry->d_parent->d_inode;
  3175. + hidden_dir = au_h_iptr_i(dir, bdst);
  3176. + dlgt = need_dlgt(dir->i_sb);
  3177. + do_sio = au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE, dlgt);
  3178. + if (!do_sio) {
  3179. + umode_t mode = dentry->d_inode->i_mode & S_IFMT;
  3180. + do_sio = ((mode == S_IFCHR || mode == S_IFBLK)
  3181. + && !capable(CAP_MKNOD));
  3182. + }
  3183. + if (!do_sio)
  3184. + err = cpup_simple(dentry, bdst, len, flags);
  3185. + else {
  3186. + struct cpup_simple_args args = {
  3187. + .errp = &err,
  3188. + .dentry = dentry,
  3189. + .bdst = bdst,
  3190. + .len = len,
  3191. + .flags = flags
  3192. + };
  3193. + au_wkq_wait(call_cpup_simple, &args, /*dlgt*/0);
  3194. + }
  3195. +
  3196. + //dput(parent);
  3197. + TraceErr(err);
  3198. + return err;
  3199. +}
  3200. +
  3201. +//todo: dcsub
  3202. +/* cf. revalidate function in file.c */
  3203. +int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked)
  3204. +{
  3205. + int err;
  3206. + struct super_block *sb;
  3207. + struct dentry *d, *parent, *hidden_parent;
  3208. + unsigned int udba;
  3209. +
  3210. + LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
  3211. + DLNPair(dentry), bdst, parent_ino(dentry), locked);
  3212. + sb = dentry->d_sb;
  3213. + DEBUG_ON(test_ro(sb, bdst, NULL));
  3214. + parent = dentry->d_parent;
  3215. + IiMustWriteLock(parent->d_inode);
  3216. + if (unlikely(IS_ROOT(parent)))
  3217. + return 0;
  3218. + if (locked) {
  3219. + DiMustAnyLock(locked);
  3220. + IiMustAnyLock(locked->d_inode);
  3221. + }
  3222. +
  3223. + /* slow loop, keep it simple and stupid */
  3224. + err = 0;
  3225. + udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
  3226. + while (1) {
  3227. + parent = dentry->d_parent; // dget_parent()
  3228. + hidden_parent = au_h_dptr_i(parent, bdst);
  3229. + if (hidden_parent)
  3230. + return 0; /* success */
  3231. +
  3232. + /* find top dir which is needed to cpup */
  3233. + do {
  3234. + d = parent;
  3235. + parent = d->d_parent; // dget_parent()
  3236. + if (parent != locked)
  3237. + di_read_lock_parent3(parent, !AUFS_I_RLOCK);
  3238. + hidden_parent = au_h_dptr_i(parent, bdst);
  3239. + if (parent != locked)
  3240. + di_read_unlock(parent, !AUFS_I_RLOCK);
  3241. + } while (!hidden_parent);
  3242. +
  3243. + if (d != dentry->d_parent)
  3244. + di_write_lock_child3(d);
  3245. +
  3246. + /* somebody else might create while we were sleeping */
  3247. + if (!au_h_dptr_i(d, bdst) || !au_h_dptr_i(d, bdst)->d_inode) {
  3248. + struct inode *h_dir = hidden_parent->d_inode,
  3249. + *dir = parent->d_inode,
  3250. + *h_gdir, *gdir;
  3251. +
  3252. + if (au_h_dptr_i(d, bdst))
  3253. + au_update_dbstart(d);
  3254. + //DEBUG_ON(dbstart(d) <= bdst);
  3255. + if (parent != locked)
  3256. + di_read_lock_parent3(parent, AUFS_I_RLOCK);
  3257. + h_gdir = gdir = NULL;
  3258. + if (unlikely(udba && !IS_ROOT(parent))) {
  3259. + gdir = parent->d_parent->d_inode;
  3260. + h_gdir = hidden_parent->d_parent->d_inode;
  3261. + hgdir_lock(h_gdir, gdir, bdst);
  3262. + }
  3263. + hdir_lock(h_dir, dir, bdst);
  3264. + err = sio_cpup_simple(d, bdst, -1,
  3265. + au_flags_cpup(CPUP_DTIME,
  3266. + parent));
  3267. + //if (LktrCond) err = -1;
  3268. + hdir_unlock(h_dir, dir, bdst);
  3269. + if (unlikely(gdir))
  3270. + hdir_unlock(h_gdir, gdir, bdst);
  3271. + if (parent != locked)
  3272. + di_read_unlock(parent, AUFS_I_RLOCK);
  3273. + }
  3274. +
  3275. + if (d != dentry->d_parent)
  3276. + di_write_unlock(d);
  3277. + if (unlikely(err))
  3278. + break;
  3279. + }
  3280. +
  3281. +// out:
  3282. + TraceErr(err);
  3283. + return err;
  3284. +}
  3285. +
  3286. +int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
  3287. + struct dentry *locked)
  3288. +{
  3289. + int err;
  3290. + struct dentry *parent;
  3291. + struct inode *dir;
  3292. +
  3293. + parent = dentry->d_parent;
  3294. + dir = parent->d_inode;
  3295. + LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
  3296. + DLNPair(dentry), bdst, dir->i_ino, locked);
  3297. + DiMustReadLock(parent);
  3298. + IiMustReadLock(dir);
  3299. +
  3300. + if (au_h_iptr_i(dir, bdst))
  3301. + return 0;
  3302. +
  3303. + err = 0;
  3304. + di_read_unlock(parent, AUFS_I_RLOCK);
  3305. + di_write_lock_parent(parent);
  3306. + if (au_h_iptr_i(dir, bdst))
  3307. + goto out;
  3308. +
  3309. + err = cpup_dirs(dentry, bdst, locked);
  3310. +
  3311. + out:
  3312. + di_downgrade_lock(parent, AUFS_I_RLOCK);
  3313. + TraceErr(err);
  3314. + return err;
  3315. +}
  3316. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/cpup.h linux-2.6.22.1/fs/aufs/cpup.h
  3317. --- linux-2.6.22.1.oorig/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
  3318. +++ linux-2.6.22.1/fs/aufs/cpup.h 2007-07-24 14:17:46.000000000 +0200
  3319. @@ -0,0 +1,72 @@
  3320. +/*
  3321. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  3322. + *
  3323. + * This program, aufs is free software; you can redistribute it and/or modify
  3324. + * it under the terms of the GNU General Public License as published by
  3325. + * the Free Software Foundation; either version 2 of the License, or
  3326. + * (at your option) any later version.
  3327. + *
  3328. + * This program is distributed in the hope that it will be useful,
  3329. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3330. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3331. + * GNU General Public License for more details.
  3332. + *
  3333. + * You should have received a copy of the GNU General Public License
  3334. + * along with this program; if not, write to the Free Software
  3335. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3336. + */
  3337. +
  3338. +/* $Id: cpup.h,v 1.15 2007/05/14 03:41:52 sfjro Exp $ */
  3339. +
  3340. +#ifndef __AUFS_CPUP_H__
  3341. +#define __AUFS_CPUP_H__
  3342. +
  3343. +#ifdef __KERNEL__
  3344. +
  3345. +#include <linux/fs.h>
  3346. +#include <linux/version.h>
  3347. +#include <linux/aufs_type.h>
  3348. +
  3349. +static inline
  3350. +void au_cpup_attr_blksize(struct inode *inode, struct inode *h_inode)
  3351. +{
  3352. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
  3353. + inode->i_blksize = h_inode->i_blksize;
  3354. +#endif
  3355. +}
  3356. +
  3357. +void au_cpup_attr_timesizes(struct inode *inode);
  3358. +void au_cpup_attr_nlink(struct inode *inode);
  3359. +void au_cpup_attr_changable(struct inode *inode);
  3360. +void au_cpup_igen(struct inode *inode, struct inode *h_inode);
  3361. +void au_cpup_attr_all(struct inode *inode);
  3362. +
  3363. +#define CPUP_DTIME 1 // do dtime_store/revert
  3364. +// todo: remove this
  3365. +#define CPUP_LOCKED_GHDIR 2 // grand parent hidden dir is locked
  3366. +unsigned int au_flags_cpup(unsigned int init, struct dentry *parent);
  3367. +
  3368. +int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
  3369. + loff_t len, unsigned int flags);
  3370. +int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
  3371. + aufs_bindex_t bsrc, loff_t len, unsigned int flags);
  3372. +int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3373. + unsigned int flags);
  3374. +int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3375. + unsigned int flags);
  3376. +
  3377. +int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked);
  3378. +int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
  3379. + struct dentry *locked);
  3380. +
  3381. +/* keep timestamps when copyup */
  3382. +struct dtime {
  3383. + struct dentry *dt_dentry, *dt_h_dentry;
  3384. + struct timespec dt_atime, dt_mtime;
  3385. +};
  3386. +void dtime_store(struct dtime *dt, struct dentry *dentry,
  3387. + struct dentry *h_dentry);
  3388. +void dtime_revert(struct dtime *dt, int h_parent_is_locked);
  3389. +
  3390. +#endif /* __KERNEL__ */
  3391. +#endif /* __AUFS_CPUP_H__ */
  3392. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dcsub.c linux-2.6.22.1/fs/aufs/dcsub.c
  3393. --- linux-2.6.22.1.oorig/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
  3394. +++ linux-2.6.22.1/fs/aufs/dcsub.c 2007-07-24 14:17:46.000000000 +0200
  3395. @@ -0,0 +1,175 @@
  3396. +/*
  3397. + * Copyright (C) 2007 Junjiro Okajima
  3398. + *
  3399. + * This program, aufs is free software; you can redistribute it and/or modify
  3400. + * it under the terms of the GNU General Public License as published by
  3401. + * the Free Software Foundation; either version 2 of the License, or
  3402. + * (at your option) any later version.
  3403. + *
  3404. + * This program is distributed in the hope that it will be useful,
  3405. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3406. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3407. + * GNU General Public License for more details.
  3408. + *
  3409. + * You should have received a copy of the GNU General Public License
  3410. + * along with this program; if not, write to the Free Software
  3411. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3412. + */
  3413. +
  3414. +/* $Id: dcsub.c,v 1.3 2007/05/14 03:41:52 sfjro Exp $ */
  3415. +
  3416. +#include "aufs.h"
  3417. +
  3418. +static void au_dpage_free(struct au_dpage *dpage)
  3419. +{
  3420. + int i;
  3421. +
  3422. + TraceEnter();
  3423. + DEBUG_ON(!dpage);
  3424. +
  3425. + for (i = 0; i < dpage->ndentry; i++)
  3426. + dput(dpage->dentries[i]);
  3427. + free_page((unsigned long)dpage->dentries);
  3428. +}
  3429. +
  3430. +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
  3431. +{
  3432. + int err;
  3433. + void *p;
  3434. +
  3435. + TraceEnter();
  3436. +
  3437. + err = -ENOMEM;
  3438. + dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
  3439. + if (unlikely(!dpages->dpages))
  3440. + goto out;
  3441. + p = (void*)__get_free_page(gfp);
  3442. + if (unlikely(!p))
  3443. + goto out_dpages;
  3444. + dpages->dpages[0].ndentry = 0;
  3445. + dpages->dpages[0].dentries = p;
  3446. + dpages->ndpage = 1;
  3447. + return 0; /* success */
  3448. +
  3449. + out_dpages:
  3450. + kfree(dpages->dpages);
  3451. + out:
  3452. + TraceErr(err);
  3453. + return err;
  3454. +}
  3455. +
  3456. +void au_dpages_free(struct au_dcsub_pages *dpages)
  3457. +{
  3458. + int i;
  3459. +
  3460. + TraceEnter();
  3461. +
  3462. + for (i = 0; i < dpages->ndpage; i++)
  3463. + au_dpage_free(dpages->dpages + i);
  3464. + kfree(dpages->dpages);
  3465. +}
  3466. +
  3467. +static int au_dpages_append(struct au_dcsub_pages *dpages,
  3468. + struct dentry *dentry, gfp_t gfp)
  3469. +{
  3470. + int err, sz;
  3471. + struct au_dpage *dpage;
  3472. + void *p;
  3473. +
  3474. + //TraceEnter();
  3475. +
  3476. + dpage = dpages->dpages + dpages->ndpage - 1;
  3477. + DEBUG_ON(!dpage);
  3478. + sz = PAGE_SIZE/sizeof(dentry);
  3479. + if (unlikely(dpage->ndentry >= sz)) {
  3480. + LKTRLabel(new dpage);
  3481. + err = -ENOMEM;
  3482. + sz = dpages->ndpage * sizeof(*dpages->dpages);
  3483. + p = au_kzrealloc(dpages->dpages, sz,
  3484. + sz + sizeof(*dpages->dpages), gfp);
  3485. + if (unlikely(!p))
  3486. + goto out;
  3487. + dpage = dpages->dpages + dpages->ndpage;
  3488. + p = (void*)__get_free_page(gfp);
  3489. + if (unlikely(!p))
  3490. + goto out;
  3491. + dpage->ndentry = 0;
  3492. + dpage->dentries = p;
  3493. + dpages->ndpage++;
  3494. + }
  3495. +
  3496. + dpage->dentries[dpage->ndentry++] = dget(dentry);
  3497. + return 0; /* success */
  3498. +
  3499. + out:
  3500. + //TraceErr(err);
  3501. + return err;
  3502. +}
  3503. +
  3504. +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
  3505. + au_dpages_test test, void *arg)
  3506. +{
  3507. + int err;
  3508. + struct dentry *this_parent = root;
  3509. + struct list_head *next;
  3510. + struct super_block *sb = root->d_sb;
  3511. +
  3512. + TraceEnter();
  3513. +
  3514. + err = 0;
  3515. + spin_lock(&dcache_lock);
  3516. + repeat:
  3517. + next = this_parent->d_subdirs.next;
  3518. + resume:
  3519. + if (this_parent->d_sb == sb
  3520. + && !IS_ROOT(this_parent)
  3521. + && atomic_read(&this_parent->d_count)
  3522. + && this_parent->d_inode
  3523. + && (!test || test(this_parent, arg))) {
  3524. + err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
  3525. + if (unlikely(err))
  3526. + goto out;
  3527. + }
  3528. +
  3529. + while (next != &this_parent->d_subdirs) {
  3530. + struct list_head *tmp = next;
  3531. + struct dentry *dentry = list_entry(tmp, struct dentry, D_CHILD);
  3532. + next = tmp->next;
  3533. + if (unlikely(/*d_unhashed(dentry) || */!dentry->d_inode))
  3534. + continue;
  3535. + if (!list_empty(&dentry->d_subdirs)) {
  3536. + this_parent = dentry;
  3537. + goto repeat;
  3538. + }
  3539. + if (dentry->d_sb == sb
  3540. + && atomic_read(&dentry->d_count)
  3541. + && (!test || test(dentry, arg))) {
  3542. + err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
  3543. + if (unlikely(err))
  3544. + goto out;
  3545. + }
  3546. + }
  3547. +
  3548. + if (this_parent != root) {
  3549. + next = this_parent->D_CHILD.next;
  3550. + this_parent = this_parent->d_parent;
  3551. + goto resume;
  3552. + }
  3553. + out:
  3554. + spin_unlock(&dcache_lock);
  3555. +#if 0
  3556. + if (!err) {
  3557. + int i, j;
  3558. + j = 0;
  3559. + for (i = 0; i < dpages->ndpage; i++) {
  3560. + if ((dpages->dpages + i)->ndentry)
  3561. + Dbg("%d: %d\n", i, (dpages->dpages + i)->ndentry);
  3562. + j += (dpages->dpages + i)->ndentry;
  3563. + }
  3564. + if (j)
  3565. + Dbg("ndpage %d, %d\n", dpages->ndpage, j);
  3566. + }
  3567. +#endif
  3568. + TraceErr(err);
  3569. + return err;
  3570. +}
  3571. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dcsub.h linux-2.6.22.1/fs/aufs/dcsub.h
  3572. --- linux-2.6.22.1.oorig/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
  3573. +++ linux-2.6.22.1/fs/aufs/dcsub.h 2007-07-24 14:17:46.000000000 +0200
  3574. @@ -0,0 +1,47 @@
  3575. +/*
  3576. + * Copyright (C) 2007 Junjiro Okajima
  3577. + *
  3578. + * This program, aufs is free software; you can redistribute it and/or modify
  3579. + * it under the terms of the GNU General Public License as published by
  3580. + * the Free Software Foundation; either version 2 of the License, or
  3581. + * (at your option) any later version.
  3582. + *
  3583. + * This program is distributed in the hope that it will be useful,
  3584. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3585. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3586. + * GNU General Public License for more details.
  3587. + *
  3588. + * You should have received a copy of the GNU General Public License
  3589. + * along with this program; if not, write to the Free Software
  3590. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3591. + */
  3592. +
  3593. +/* $Id: dcsub.h,v 1.2 2007/05/14 03:41:52 sfjro Exp $ */
  3594. +
  3595. +#ifndef __AUFS_DCSUB_H__
  3596. +#define __AUFS_DCSUB_H__
  3597. +
  3598. +#ifdef __KERNEL__
  3599. +
  3600. +#include <linux/dcache.h>
  3601. +
  3602. +struct au_dpage {
  3603. + int ndentry;
  3604. + struct dentry **dentries;
  3605. +};
  3606. +
  3607. +struct au_dcsub_pages {
  3608. + int ndpage;
  3609. + struct au_dpage *dpages;
  3610. +};
  3611. +
  3612. +/* ---------------------------------------------------------------------- */
  3613. +
  3614. +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
  3615. +void au_dpages_free(struct au_dcsub_pages *dpages);
  3616. +typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
  3617. +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
  3618. + au_dpages_test test, void *arg);
  3619. +
  3620. +#endif /* __KERNEL__ */
  3621. +#endif /* __AUFS_DCSUB_H__ */
  3622. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/debug.c linux-2.6.22.1/fs/aufs/debug.c
  3623. --- linux-2.6.22.1.oorig/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
  3624. +++ linux-2.6.22.1/fs/aufs/debug.c 2007-07-24 14:17:46.000000000 +0200
  3625. @@ -0,0 +1,262 @@
  3626. +/*
  3627. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  3628. + *
  3629. + * This program, aufs is free software; you can redistribute it and/or modify
  3630. + * it under the terms of the GNU General Public License as published by
  3631. + * the Free Software Foundation; either version 2 of the License, or
  3632. + * (at your option) any later version.
  3633. + *
  3634. + * This program is distributed in the hope that it will be useful,
  3635. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3636. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3637. + * GNU General Public License for more details.
  3638. + *
  3639. + * You should have received a copy of the GNU General Public License
  3640. + * along with this program; if not, write to the Free Software
  3641. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3642. + */
  3643. +
  3644. +/* $Id: debug.c,v 1.27 2007/04/30 05:48:23 sfjro Exp $ */
  3645. +
  3646. +#include "aufs.h"
  3647. +
  3648. +atomic_t aufs_cond = ATOMIC_INIT(0);
  3649. +
  3650. +#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
  3651. +#define dpri(fmt, arg...) \
  3652. + do {if (LktrCond) printk(KERN_DEBUG fmt, ##arg);} while (0)
  3653. +#else
  3654. +#define dpri(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
  3655. +#endif
  3656. +
  3657. +/* ---------------------------------------------------------------------- */
  3658. +
  3659. +void au_dpri_whlist(struct aufs_nhash *whlist)
  3660. +{
  3661. + int i;
  3662. + struct hlist_head *head;
  3663. + struct aufs_wh *tpos;
  3664. + struct hlist_node *pos;
  3665. +
  3666. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  3667. + head = whlist->heads + i;
  3668. + hlist_for_each_entry(tpos, pos, head, wh_hash)
  3669. + dpri("b%d, %.*s, %d\n",
  3670. + tpos->wh_bindex,
  3671. + tpos->wh_str.len, tpos->wh_str.name,
  3672. + tpos->wh_str.len);
  3673. + }
  3674. +}
  3675. +
  3676. +void au_dpri_vdir(struct aufs_vdir *vdir)
  3677. +{
  3678. + int i;
  3679. + union aufs_deblk_p p;
  3680. + unsigned char *o;
  3681. +
  3682. + if (!vdir || IS_ERR(vdir)) {
  3683. + dpri("err %ld\n", PTR_ERR(vdir));
  3684. + return;
  3685. + }
  3686. +
  3687. + dpri("nblk %d, deblk %p %d, last{%d, %p}, ver %lu\n",
  3688. + vdir->vd_nblk, vdir->vd_deblk, ksize(vdir->vd_deblk),
  3689. + vdir->vd_last.i, vdir->vd_last.p.p, vdir->vd_version);
  3690. + for (i = 0; i < vdir->vd_nblk; i++) {
  3691. + p.deblk = vdir->vd_deblk[i];
  3692. + o = p.p;
  3693. + dpri("[%d]: %p %d\n", i, o, ksize(o));
  3694. +#if 0 // verbose
  3695. + int j;
  3696. + for (j = 0; j < 8; j++) {
  3697. + dpri("%p(+%d) {%02x %02x %02x %02x %02x %02x %02x %02x "
  3698. + "%02x %02x %02x %02x %02x %02x %02x %02x}\n",
  3699. + p.p, p.p - o,
  3700. + p.p[0], p.p[1], p.p[2], p.p[3],
  3701. + p.p[4], p.p[5], p.p[6], p.p[7],
  3702. + p.p[8], p.p[9], p.p[10], p.p[11],
  3703. + p.p[12], p.p[13], p.p[14], p.p[15]);
  3704. + p.p += 16;
  3705. + }
  3706. +#endif
  3707. + }
  3708. +}
  3709. +
  3710. +static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode)
  3711. +{
  3712. + if (!inode || IS_ERR(inode)) {
  3713. + dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
  3714. + return -1;
  3715. + }
  3716. +
  3717. + /* the type of i_blocks depends upon CONFIG_LSF */
  3718. + BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
  3719. + && sizeof(inode->i_blocks) != sizeof(u64));
  3720. + dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %Lu, blk %Lu,"
  3721. + " ct %Ld, np %lu, st 0x%lx, g %x\n",
  3722. + bindex,
  3723. + inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
  3724. + atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
  3725. + i_size_read(inode), (u64)inode->i_blocks,
  3726. + timespec_to_ns(&inode->i_ctime) & 0x0ffff,
  3727. + inode->i_mapping ? inode->i_mapping->nrpages : 0,
  3728. + inode->i_state, inode->i_generation);
  3729. + return 0;
  3730. +}
  3731. +
  3732. +void au_dpri_inode(struct inode *inode)
  3733. +{
  3734. + struct aufs_iinfo *iinfo;
  3735. + aufs_bindex_t bindex;
  3736. + int err;
  3737. +
  3738. + err = do_pri_inode(-1, inode);
  3739. + if (err || !au_is_aufs(inode->i_sb))
  3740. + return;
  3741. +
  3742. + iinfo = itoii(inode);
  3743. + if (!iinfo)
  3744. + return;
  3745. + dpri("i-1: bstart %d, bend %d, gen %d\n",
  3746. + iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
  3747. + if (iinfo->ii_bstart < 0)
  3748. + return;
  3749. + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
  3750. + do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode);
  3751. +}
  3752. +
  3753. +static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
  3754. +{
  3755. + if (!dentry || IS_ERR(dentry)) {
  3756. + dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
  3757. + return -1;
  3758. + }
  3759. + dpri("d%d: %.*s/%.*s, %s, cnt %d, flags 0x%x\n",
  3760. + bindex,
  3761. + DLNPair(dentry->d_parent), DLNPair(dentry),
  3762. + dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
  3763. + atomic_read(&dentry->d_count), dentry->d_flags);
  3764. + do_pri_inode(bindex, dentry->d_inode);
  3765. + return 0;
  3766. +}
  3767. +
  3768. +void au_dpri_dentry(struct dentry *dentry)
  3769. +{
  3770. + struct aufs_dinfo *dinfo;
  3771. + aufs_bindex_t bindex;
  3772. + int err;
  3773. +
  3774. + err = do_pri_dentry(-1, dentry);
  3775. + if (err || !au_is_aufs(dentry->d_sb))
  3776. + return;
  3777. +
  3778. + dinfo = dtodi(dentry);
  3779. + if (!dinfo)
  3780. + return;
  3781. + dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
  3782. + dinfo->di_bstart, dinfo->di_bend,
  3783. + dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
  3784. + if (dinfo->di_bstart < 0)
  3785. + return;
  3786. + for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
  3787. + do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
  3788. +}
  3789. +
  3790. +static int do_pri_file(aufs_bindex_t bindex, struct file *file)
  3791. +{
  3792. + char a[32];
  3793. +
  3794. + if (!file || IS_ERR(file)) {
  3795. + dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
  3796. + return -1;
  3797. + }
  3798. + a[0] = 0;
  3799. + if (bindex == -1 && ftofi(file))
  3800. + snprintf(a, sizeof(a), ", mmapped %d", au_is_mmapped(file));
  3801. + dpri("f%d: mode 0x%x, flags 0%o, cnt %d, pos %Lu%s\n",
  3802. + bindex, file->f_mode, file->f_flags, file_count(file),
  3803. + file->f_pos, a);
  3804. + do_pri_dentry(bindex, file->f_dentry);
  3805. + return 0;
  3806. +}
  3807. +
  3808. +void au_dpri_file(struct file *file)
  3809. +{
  3810. + struct aufs_finfo *finfo;
  3811. + aufs_bindex_t bindex;
  3812. + int err;
  3813. +
  3814. + err = do_pri_file(-1, file);
  3815. + if (err || !file->f_dentry || !au_is_aufs(file->f_dentry->d_sb))
  3816. + return;
  3817. +
  3818. + finfo = ftofi(file);
  3819. + if (!finfo)
  3820. + return;
  3821. + if (finfo->fi_bstart < 0)
  3822. + return;
  3823. + for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
  3824. + struct aufs_hfile *hf;
  3825. + //dpri("bindex %d\n", bindex);
  3826. + hf = finfo->fi_hfile + bindex;
  3827. + do_pri_file(bindex, hf ? hf->hf_file : NULL);
  3828. + }
  3829. +}
  3830. +
  3831. +static int do_pri_br(aufs_bindex_t bindex, struct aufs_branch *br)
  3832. +{
  3833. + struct vfsmount *mnt;
  3834. + struct super_block *sb;
  3835. +
  3836. + if (!br || IS_ERR(br)
  3837. + || !(mnt = br->br_mnt) || IS_ERR(mnt)
  3838. + || !(sb = mnt->mnt_sb) || IS_ERR(sb)) {
  3839. + dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
  3840. + return -1;
  3841. + }
  3842. +
  3843. + dpri("s%d: {perm 0x%x, cnt %d}, "
  3844. + "%s, flags 0x%lx, cnt(BIAS) %d, active %d, xino %p %p\n",
  3845. + bindex, br->br_perm, br_count(br),
  3846. + au_sbtype(sb), sb->s_flags, sb->s_count - S_BIAS,
  3847. + atomic_read(&sb->s_active), br->br_xino,
  3848. + br->br_xino ? br->br_xino->f_dentry : NULL);
  3849. + return 0;
  3850. +}
  3851. +
  3852. +void au_dpri_sb(struct super_block *sb)
  3853. +{
  3854. + struct aufs_sbinfo *sbinfo;
  3855. + aufs_bindex_t bindex;
  3856. + int err;
  3857. + struct vfsmount mnt = {.mnt_sb = sb};
  3858. + struct aufs_branch fake = {
  3859. + .br_perm = 0,
  3860. + .br_mnt = &mnt,
  3861. + .br_count = ATOMIC_INIT(0),
  3862. + .br_xino = NULL
  3863. + };
  3864. +
  3865. + atomic_set(&fake.br_count, 0);
  3866. + err = do_pri_br(-1, &fake);
  3867. + dpri("dev 0x%x\n", sb->s_dev);
  3868. + if (err || !au_is_aufs(sb))
  3869. + return;
  3870. +
  3871. + sbinfo = stosi(sb);
  3872. + if (!sbinfo)
  3873. + return;
  3874. + for (bindex = 0; bindex <= sbinfo->si_bend; bindex++) {
  3875. + //dpri("bindex %d\n", bindex);
  3876. + do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
  3877. + }
  3878. +}
  3879. +
  3880. +/* ---------------------------------------------------------------------- */
  3881. +
  3882. +void DbgSleep(int sec)
  3883. +{
  3884. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  3885. + Dbg("sleep %d sec\n", sec);
  3886. + wait_event_timeout(wq, 0, sec * HZ);
  3887. +}
  3888. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/debug.h linux-2.6.22.1/fs/aufs/debug.h
  3889. --- linux-2.6.22.1.oorig/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
  3890. +++ linux-2.6.22.1/fs/aufs/debug.h 2007-07-24 14:17:46.000000000 +0200
  3891. @@ -0,0 +1,129 @@
  3892. +/*
  3893. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  3894. + *
  3895. + * This program, aufs is free software; you can redistribute it and/or modify
  3896. + * it under the terms of the GNU General Public License as published by
  3897. + * the Free Software Foundation; either version 2 of the License, or
  3898. + * (at your option) any later version.
  3899. + *
  3900. + * This program is distributed in the hope that it will be useful,
  3901. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3902. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3903. + * GNU General Public License for more details.
  3904. + *
  3905. + * You should have received a copy of the GNU General Public License
  3906. + * along with this program; if not, write to the Free Software
  3907. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3908. + */
  3909. +
  3910. +/* $Id: debug.h,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
  3911. +
  3912. +#ifndef __AUFS_DEBUG_H__
  3913. +#define __AUFS_DEBUG_H__
  3914. +
  3915. +#ifdef __KERNEL__
  3916. +
  3917. +#include <linux/fs.h>
  3918. +
  3919. +#ifdef CONFIG_AUFS_DEBUG
  3920. +#define DEBUG_ON(a) BUG_ON(a)
  3921. +extern atomic_t aufs_cond;
  3922. +#define au_debug_on() atomic_inc(&aufs_cond)
  3923. +#define au_debug_off() atomic_dec(&aufs_cond)
  3924. +#define au_is_debug() atomic_read(&aufs_cond)
  3925. +#else
  3926. +#define DEBUG_ON(a) /* */
  3927. +#define au_debug_on() /* */
  3928. +#define au_debug_off() /* */
  3929. +#define au_is_debug() 0
  3930. +#endif
  3931. +
  3932. +#define MtxMustLock(mtx) DEBUG_ON(!mutex_is_locked(mtx))
  3933. +
  3934. +/* ---------------------------------------------------------------------- */
  3935. +
  3936. +/* debug print */
  3937. +#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
  3938. +#include <linux/lktr.h>
  3939. +#ifdef CONFIG_AUFS_DEBUG
  3940. +#undef LktrCond
  3941. +#define LktrCond unlikely((lktr_cond && lktr_cond()) || au_is_debug())
  3942. +#endif
  3943. +#else
  3944. +#define LktrCond au_is_debug()
  3945. +#define LKTRDumpVma(pre, vma, suf) /* */
  3946. +#define LKTRDumpStack() /* */
  3947. +#define LKTRTrace(fmt, args...) do { \
  3948. + if (LktrCond) \
  3949. + Dbg(fmt, ##args); \
  3950. +} while (0)
  3951. +#define LKTRLabel(label) LKTRTrace("%s\n", #label)
  3952. +#endif /* CONFIG_LKTR */
  3953. +
  3954. +#define TraceErr(e) do { \
  3955. + if (unlikely((e) < 0)) \
  3956. + LKTRTrace("err %d\n", (int)(e)); \
  3957. +} while (0)
  3958. +#define TraceErrPtr(p) do { \
  3959. + if (IS_ERR(p)) \
  3960. + LKTRTrace("err %ld\n", PTR_ERR(p)); \
  3961. +} while (0)
  3962. +#define TraceEnter() LKTRLabel(enter)
  3963. +
  3964. +/* dirty macros for debug print, use with "%.*s" and caution */
  3965. +#define LNPair(qstr) (qstr)->len,(qstr)->name
  3966. +#define DLNPair(d) LNPair(&(d)->d_name)
  3967. +
  3968. +/* ---------------------------------------------------------------------- */
  3969. +
  3970. +#define Dpri(lvl, fmt, arg...) \
  3971. + printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
  3972. + __func__, __LINE__, current->comm, current->pid, ##arg)
  3973. +#define Dbg(fmt, arg...) Dpri(KERN_DEBUG, fmt, ##arg)
  3974. +#define Warn(fmt, arg...) Dpri(KERN_WARNING, fmt, ##arg)
  3975. +#define Warn1(fmt, arg...) do { \
  3976. + static unsigned char c; \
  3977. + if (!c++) Warn(fmt, ##arg); \
  3978. + } while (0)
  3979. +#define Err(fmt, arg...) Dpri(KERN_ERR, fmt, ##arg)
  3980. +#define Err1(fmt, arg...) do { \
  3981. + static unsigned char c; \
  3982. + if (!c++) Err(fmt, ##arg); \
  3983. + } while (0)
  3984. +#define IOErr(fmt, arg...) Err("I/O Error, " fmt, ##arg)
  3985. +#define IOErr1(fmt, arg...) do { \
  3986. + static unsigned char c; \
  3987. + if (!c++) IOErr(fmt, ##arg); \
  3988. + } while (0)
  3989. +#define IOErrWhck(fmt, arg...) Err("I/O Error, try whck. " fmt, ##arg)
  3990. +
  3991. +/* ---------------------------------------------------------------------- */
  3992. +
  3993. +#ifdef CONFIG_AUFS_DEBUG
  3994. +struct aufs_nhash;
  3995. +void au_dpri_whlist(struct aufs_nhash *whlist);
  3996. +struct aufs_vdir;
  3997. +void au_dpri_vdir(struct aufs_vdir *vdir);
  3998. +void au_dpri_inode(struct inode *inode);
  3999. +void au_dpri_dentry(struct dentry *dentry);
  4000. +void au_dpri_file(struct file *filp);
  4001. +void au_dpri_sb(struct super_block *sb);
  4002. +#define DbgWhlist(w) do{LKTRTrace(#w "\n"); au_dpri_whlist(w);}while(0)
  4003. +#define DbgVdir(v) do{LKTRTrace(#v "\n"); au_dpri_vdir(v);}while(0)
  4004. +#define DbgInode(i) do{LKTRTrace(#i "\n"); au_dpri_inode(i);}while(0)
  4005. +#define DbgDentry(d) do{LKTRTrace(#d "\n"); au_dpri_dentry(d);}while(0)
  4006. +#define DbgFile(f) do{LKTRTrace(#f "\n"); au_dpri_file(f);}while(0)
  4007. +#define DbgSb(sb) do{LKTRTrace(#sb "\n"); au_dpri_sb(sb);}while(0)
  4008. +void DbgSleep(int sec);
  4009. +#else
  4010. +#define DbgWhlist(w) /* */
  4011. +#define DbgVdir(v) /* */
  4012. +#define DbgInode(i) /* */
  4013. +#define DbgDentry(d) /* */
  4014. +#define DbgFile(f) /* */
  4015. +#define DbgSb(sb) /* */
  4016. +#define DbgSleep(sec) /* */
  4017. +#endif
  4018. +
  4019. +#endif /* __KERNEL__ */
  4020. +#endif /* __AUFS_DEBUG_H__ */
  4021. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dentry.c linux-2.6.22.1/fs/aufs/dentry.c
  4022. --- linux-2.6.22.1.oorig/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
  4023. +++ linux-2.6.22.1/fs/aufs/dentry.c 2007-07-24 14:17:46.000000000 +0200
  4024. @@ -0,0 +1,946 @@
  4025. +/*
  4026. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  4027. + *
  4028. + * This program, aufs is free software; you can redistribute it and/or modify
  4029. + * it under the terms of the GNU General Public License as published by
  4030. + * the Free Software Foundation; either version 2 of the License, or
  4031. + * (at your option) any later version.
  4032. + *
  4033. + * This program is distributed in the hope that it will be useful,
  4034. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  4035. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  4036. + * GNU General Public License for more details.
  4037. + *
  4038. + * You should have received a copy of the GNU General Public License
  4039. + * along with this program; if not, write to the Free Software
  4040. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  4041. + */
  4042. +
  4043. +/* $Id: dentry.c,v 1.41 2007/05/14 03:38:38 sfjro Exp $ */
  4044. +
  4045. +//#include <linux/fs.h>
  4046. +//#include <linux/namei.h>
  4047. +#include "aufs.h"
  4048. +
  4049. +#ifdef CONFIG_AUFS_LHASH_PATCH
  4050. +
  4051. +#ifdef CONFIG_AUFS_DLGT
  4052. +struct lookup_hash_args {
  4053. + struct dentry **errp;
  4054. + struct qstr *name;
  4055. + struct dentry *base;
  4056. + struct nameidata *nd;
  4057. +};
  4058. +
  4059. +static void call_lookup_hash(void *args)
  4060. +{
  4061. + struct lookup_hash_args *a = args;
  4062. + *a->errp = __lookup_hash(a->name, a->base, a->nd);
  4063. +}
  4064. +#endif /* CONFIG_AUFS_DLGT */
  4065. +
  4066. +static struct dentry *lkup_hash(const char *name, struct dentry *parent,
  4067. + int len, struct lkup_args *lkup)
  4068. +{
  4069. + struct dentry *dentry;
  4070. + char *p;
  4071. + unsigned long hash;
  4072. + struct qstr this;
  4073. + unsigned int c;
  4074. + struct nameidata tmp_nd;
  4075. +
  4076. + dentry = ERR_PTR(-EACCES);
  4077. + this.name = name;
  4078. + this.len = len;
  4079. + if (unlikely(!len))
  4080. + goto out;
  4081. +
  4082. + p = (void*)name;
  4083. + hash = init_name_hash();
  4084. + while (len--) {
  4085. + c = *p++;
  4086. + if (unlikely(c == '/' || c == '\0'))
  4087. + goto out;
  4088. + hash = partial_name_hash(c, hash);
  4089. + }
  4090. + this.hash = end_name_hash(hash);
  4091. +
  4092. + memset(&tmp_nd, 0, sizeof(tmp_nd));
  4093. + tmp_nd.dentry = dget(parent);
  4094. + tmp_nd.mnt = mntget(lkup->nfsmnt);
  4095. +#ifndef CONFIG_AUFS_DLGT
  4096. + dentry = __lookup_hash(&this, parent, &tmp_nd);
  4097. +#else
  4098. + if (!lkup->dlgt)
  4099. + dentry = __lookup_hash(&this, parent, &tmp_nd);
  4100. + else {
  4101. + struct lookup_hash_args args = {
  4102. + .errp = &dentry,
  4103. + .name = &this,
  4104. + .base = parent,
  4105. + .nd = &tmp_nd
  4106. + };
  4107. + au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1);
  4108. + }
  4109. +#endif
  4110. + path_release(&tmp_nd);
  4111. +
  4112. + out:
  4113. + TraceErrPtr(dentry);
  4114. + return dentry;
  4115. +}
  4116. +#elif defined(CONFIG_AUFS_DLGT)
  4117. +static struct dentry *lkup_hash(const char *name, struct dentry *parent,
  4118. + int len, struct lkup_args *lkup)
  4119. +{
  4120. + return ERR_PTR(-ENOSYS);
  4121. +}
  4122. +#endif
  4123. +
  4124. +#ifdef CONFIG_AUFS_DLGT
  4125. +struct lookup_one_len_args {
  4126. + struct dentry **errp;
  4127. + const char *name;
  4128. + struct dentry *parent;
  4129. + int len;
  4130. +};
  4131. +
  4132. +static void call_lookup_one_len(void *args)
  4133. +{
  4134. + struct lookup_one_len_args *a = args;
  4135. + *a->errp = lookup_one_len(a->name, a->parent, a->len);
  4136. +}
  4137. +#endif /* CONFIG_AUFS_DLGT */
  4138. +
  4139. +#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
  4140. +/* cf. lookup_one_len() in linux/fs/namei.c */
  4141. +struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
  4142. + struct lkup_args *lkup)
  4143. +{
  4144. + struct dentry *dentry;
  4145. +
  4146. + LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n",
  4147. + DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt);
  4148. +
  4149. + if (!lkup->nfsmnt) {
  4150. +#ifndef CONFIG_AUFS_DLGT
  4151. + dentry = lookup_one_len(name, parent, len);
  4152. +#else
  4153. + if (!lkup->dlgt)
  4154. + dentry = lookup_one_len(name, parent, len);
  4155. + else {
  4156. + struct lookup_one_len_args args = {
  4157. + .errp = &dentry,
  4158. + .name = name,
  4159. + .parent = parent,
  4160. + .len = len
  4161. + };
  4162. + au_wkq_wait(call_lookup_one_len, &args, /*dlgt*/1);
  4163. + }
  4164. +#endif
  4165. + } else
  4166. + dentry = lkup_hash(name, parent, len, lkup);
  4167. +
  4168. + TraceErrPtr(dentry);
  4169. + return dentry;
  4170. +}
  4171. +#endif
  4172. +
  4173. +struct lkup_one_args {
  4174. + struct dentry **errp;
  4175. + const char *name;
  4176. + struct dentry *parent;
  4177. + int len;
  4178. + struct lkup_args *lkup;
  4179. +};
  4180. +
  4181. +static void call_lkup_one(void *args)
  4182. +{
  4183. + struct lkup_one_args *a = args;
  4184. + *a->errp = lkup_one(a->name, a->parent, a->len, a->lkup);
  4185. +}
  4186. +
  4187. +/*
  4188. + * returns positive/negative dentry, NULL or an error.
  4189. + * NULL means whiteout-ed or not-found.
  4190. + */
  4191. +static struct dentry *do_lookup(struct dentry *hidden_parent,
  4192. + struct dentry *dentry, aufs_bindex_t bindex,
  4193. + struct qstr *wh_name, int allow_neg,
  4194. + mode_t type, int dlgt)
  4195. +{
  4196. + struct dentry *hidden_dentry;
  4197. + int wh_found, wh_able, opq;
  4198. + struct inode *hidden_dir, *hidden_inode;
  4199. + struct qstr *name;
  4200. + struct super_block *sb;
  4201. + struct lkup_args lkup = {.dlgt = dlgt};
  4202. +
  4203. + LKTRTrace("%.*s/%.*s, b%d, allow_neg %d, type 0%o, dlgt %d\n",
  4204. + DLNPair(hidden_parent), DLNPair(dentry), bindex, allow_neg,
  4205. + type, dlgt);
  4206. + DEBUG_ON(IS_ROOT(dentry));
  4207. + hidden_dir = hidden_parent->d_inode;
  4208. + IMustLock(hidden_dir);
  4209. +
  4210. + wh_found = 0;
  4211. + sb = dentry->d_sb;
  4212. + wh_able = sbr_is_whable(sb, bindex);
  4213. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  4214. + name = &dentry->d_name;
  4215. + if (unlikely(wh_able)) {
  4216. +#if 0 //def CONFIG_AUFS_ROBR
  4217. + if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
  4218. + wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0,
  4219. + &lkup);
  4220. + else
  4221. + wh_found = -EPERM;
  4222. +#else
  4223. + wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0, &lkup);
  4224. +#endif
  4225. + }
  4226. + //if (LktrCond) wh_found = -1;
  4227. + hidden_dentry = ERR_PTR(wh_found);
  4228. + if (!wh_found)
  4229. + goto real_lookup;
  4230. + if (unlikely(wh_found < 0))
  4231. + goto out;
  4232. +
  4233. + /* We found a whiteout */
  4234. + //set_dbend(dentry, bindex);
  4235. + set_dbwh(dentry, bindex);
  4236. + if (!allow_neg)
  4237. + return NULL; /* success */
  4238. +
  4239. + real_lookup:
  4240. + // do not superio.
  4241. + hidden_dentry = lkup_one(name->name, hidden_parent, name->len, &lkup);
  4242. + //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
  4243. + if (IS_ERR(hidden_dentry))
  4244. + goto out;
  4245. + DEBUG_ON(d_unhashed(hidden_dentry));
  4246. + hidden_inode = hidden_dentry->d_inode;
  4247. + if (!hidden_inode) {
  4248. + if (!allow_neg)
  4249. + goto out_neg;
  4250. + } else if (wh_found
  4251. + || (type && type != (hidden_inode->i_mode & S_IFMT)))
  4252. + goto out_neg;
  4253. +
  4254. + if (dbend(dentry) <= bindex)
  4255. + set_dbend(dentry, bindex);
  4256. + if (dbstart(dentry) == -1 || bindex < dbstart(dentry))
  4257. + set_dbstart(dentry, bindex);
  4258. + set_h_dptr(dentry, bindex, hidden_dentry);
  4259. +
  4260. + if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode) || !wh_able)
  4261. + return hidden_dentry; /* success */
  4262. +
  4263. + hi_lock_child(hidden_inode);
  4264. + opq = is_diropq(hidden_dentry, &lkup);
  4265. + //if (LktrCond) opq = -1;
  4266. + i_unlock(hidden_inode);
  4267. + if (opq > 0)
  4268. + set_dbdiropq(dentry, bindex);
  4269. + else if (unlikely(opq < 0)) {
  4270. + set_h_dptr(dentry, bindex, NULL);
  4271. + hidden_dentry = ERR_PTR(opq);
  4272. + }
  4273. + goto out;
  4274. +
  4275. + out_neg:
  4276. + dput(hidden_dentry);
  4277. + hidden_dentry = NULL;
  4278. + out:
  4279. + TraceErrPtr(hidden_dentry);
  4280. + return hidden_dentry;
  4281. +}
  4282. +
  4283. +/*
  4284. + * returns the number of hidden positive dentries,
  4285. + * otherwise an error.
  4286. + */
  4287. +int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type)
  4288. +{
  4289. + int npositive, err, allow_neg, dlgt;
  4290. + struct dentry *parent;
  4291. + aufs_bindex_t bindex, btail;
  4292. + const struct qstr *name = &dentry->d_name;
  4293. + struct qstr whname;
  4294. + struct super_block *sb;
  4295. +
  4296. + LKTRTrace("%.*s, b%d, type 0%o\n", LNPair(name), bstart, type);
  4297. + DEBUG_ON(bstart < 0 || IS_ROOT(dentry));
  4298. + parent = dget_parent(dentry);
  4299. +
  4300. +#if 1 //ndef CONFIG_AUFS_ROBR
  4301. + err = -EPERM;
  4302. + if (unlikely(!strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
  4303. + goto out;
  4304. +#endif
  4305. +
  4306. + err = au_alloc_whname(name->name, name->len, &whname);
  4307. + //if (LktrCond) {au_free_whname(&whname); err = -1;}
  4308. + if (unlikely(err))
  4309. + goto out;
  4310. +
  4311. + sb = dentry->d_sb;
  4312. + dlgt = need_dlgt(sb);
  4313. + allow_neg = !type;
  4314. + npositive = 0;
  4315. + btail = dbtaildir(parent);
  4316. + for (bindex = bstart; bindex <= btail; bindex++) {
  4317. + struct dentry *hidden_parent, *hidden_dentry;
  4318. + struct inode *hidden_inode;
  4319. + struct inode *hidden_dir;
  4320. +
  4321. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  4322. + if (hidden_dentry) {
  4323. + if (hidden_dentry->d_inode)
  4324. + npositive++;
  4325. + if (type != S_IFDIR)
  4326. + break;
  4327. + continue;
  4328. + }
  4329. + hidden_parent = au_h_dptr_i(parent, bindex);
  4330. + if (!hidden_parent)
  4331. + continue;
  4332. + hidden_dir = hidden_parent->d_inode;
  4333. + if (!hidden_dir || !S_ISDIR(hidden_dir->i_mode))
  4334. + continue;
  4335. +
  4336. + hi_lock_parent(hidden_dir);
  4337. + hidden_dentry = do_lookup(hidden_parent, dentry, bindex,
  4338. + &whname, allow_neg, type, dlgt);
  4339. + // do not dput for testing
  4340. + //if (LktrCond) {hidden_dentry = ERR_PTR(-1);}
  4341. + i_unlock(hidden_dir);
  4342. + err = PTR_ERR(hidden_dentry);
  4343. + if (IS_ERR(hidden_dentry))
  4344. + goto out_wh;
  4345. + allow_neg = 0;
  4346. +
  4347. + if (dbwh(dentry) != -1)
  4348. + break;
  4349. + if (!hidden_dentry)
  4350. + continue;
  4351. + hidden_inode = hidden_dentry->d_inode;
  4352. + if (!hidden_inode)
  4353. + continue;
  4354. + npositive++;
  4355. + if (!type)
  4356. + type = hidden_inode->i_mode & S_IFMT;
  4357. + if (type != S_IFDIR)
  4358. + break;
  4359. + else if (dbdiropq(dentry) != -1)
  4360. + break;
  4361. + }
  4362. +
  4363. + if (npositive) {
  4364. + LKTRLabel(positive);
  4365. + au_update_dbstart(dentry);
  4366. + }
  4367. + err = npositive;
  4368. +
  4369. + out_wh:
  4370. + au_free_whname(&whname);
  4371. + out:
  4372. + dput(parent);
  4373. + TraceErr(err);
  4374. + return err;
  4375. +}
  4376. +
  4377. +struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
  4378. + struct lkup_args *lkup)
  4379. +{
  4380. + struct dentry *dentry;
  4381. +
  4382. + LKTRTrace("%.*s/%.*s\n", DLNPair(parent), len, name);
  4383. + IMustLock(parent->d_inode);
  4384. +
  4385. + if (!au_test_perm(parent->d_inode, MAY_EXEC, lkup->dlgt))
  4386. + dentry = lkup_one(name, parent, len, lkup);
  4387. + else {
  4388. + // ugly
  4389. + int dlgt = lkup->dlgt;
  4390. + struct lkup_one_args args = {
  4391. + .errp = &dentry,
  4392. + .name = name,
  4393. + .parent = parent,
  4394. + .len = len,
  4395. + .lkup = lkup
  4396. + };
  4397. +
  4398. + lkup->dlgt = 0;
  4399. + au_wkq_wait(call_lkup_one, &args, /*dlgt*/0);
  4400. + lkup->dlgt = dlgt;
  4401. + }
  4402. +
  4403. + TraceErrPtr(dentry);
  4404. + return dentry;
  4405. +}
  4406. +
  4407. +/*
  4408. + * lookup @dentry on @bindex which should be negative.
  4409. + */
  4410. +int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
  4411. +{
  4412. + int err;
  4413. + struct dentry *parent, *hidden_parent, *hidden_dentry;
  4414. + struct inode *hidden_dir;
  4415. + struct lkup_args lkup;
  4416. +
  4417. + LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
  4418. + parent = dget_parent(dentry);
  4419. + DEBUG_ON(!parent || !parent->d_inode
  4420. + || !S_ISDIR(parent->d_inode->i_mode));
  4421. + hidden_parent = au_h_dptr_i(parent, bindex);
  4422. + DEBUG_ON(!hidden_parent);
  4423. + hidden_dir = hidden_parent->d_inode;
  4424. + DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
  4425. + IMustLock(hidden_dir);
  4426. +
  4427. + lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bindex);
  4428. + lkup.dlgt = need_dlgt(dentry->d_sb);
  4429. + hidden_dentry = sio_lkup_one(dentry->d_name.name, hidden_parent,
  4430. + dentry->d_name.len, &lkup);
  4431. + //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
  4432. + err = PTR_ERR(hidden_dentry);
  4433. + if (IS_ERR(hidden_dentry))
  4434. + goto out;
  4435. + if (unlikely(hidden_dentry->d_inode)) {
  4436. + err = -EIO;
  4437. + IOErr("b%d %.*s should be negative.%s\n",
  4438. + bindex, DLNPair(hidden_dentry),
  4439. + au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY) ? "" :
  4440. + " Try udba=inotify.");
  4441. + dput(hidden_dentry);
  4442. + goto out;
  4443. + }
  4444. +
  4445. + if (bindex < dbstart(dentry))
  4446. + set_dbstart(dentry, bindex);
  4447. + if (dbend(dentry) < bindex)
  4448. + set_dbend(dentry, bindex);
  4449. + set_h_dptr(dentry, bindex, hidden_dentry);
  4450. + err = 0;
  4451. +
  4452. + out:
  4453. + dput(parent);
  4454. + TraceErr(err);
  4455. + return err;
  4456. +}
  4457. +
  4458. +/*
  4459. + * returns the number of found hidden positive dentries,
  4460. + * otherwise an error.
  4461. + */
  4462. +int au_refresh_hdentry(struct dentry *dentry, mode_t type)
  4463. +{
  4464. + int npositive, pgen, new_sz, sgen, dgen;
  4465. + struct aufs_dinfo *dinfo;
  4466. + struct super_block *sb;
  4467. + struct dentry *parent;
  4468. + aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend;
  4469. + struct aufs_hdentry *p;
  4470. + //struct nameidata nd;
  4471. +
  4472. + LKTRTrace("%.*s, type 0%o\n", DLNPair(dentry), type);
  4473. + DiMustWriteLock(dentry);
  4474. + sb = dentry->d_sb;
  4475. + DEBUG_ON(IS_ROOT(dentry));
  4476. + parent = dget_parent(dentry);
  4477. + pgen = au_digen(parent);
  4478. + sgen = au_sigen(sb);
  4479. + dgen = au_digen(dentry);
  4480. + DEBUG_ON(pgen != sgen);
  4481. +
  4482. + npositive = -ENOMEM;
  4483. + new_sz = sizeof(*dinfo->di_hdentry) * (sbend(sb) + 1);
  4484. + dinfo = dtodi(dentry);
  4485. + p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1),
  4486. + new_sz, GFP_KERNEL);
  4487. + //p = NULL;
  4488. + if (unlikely(!p))
  4489. + goto out;
  4490. + dinfo->di_hdentry = p;
  4491. +
  4492. + bend = dinfo->di_bend;
  4493. + bwh = dinfo->di_bwh;
  4494. + bdiropq = dinfo->di_bdiropq;
  4495. + p += dinfo->di_bstart;
  4496. + for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
  4497. + struct dentry *hd, *hdp;
  4498. + struct aufs_hdentry tmp, *q;
  4499. + aufs_bindex_t new_bindex;
  4500. +
  4501. + hd = p->hd_dentry;
  4502. + if (!hd)
  4503. + continue;
  4504. + hdp = dget_parent(hd);
  4505. + if (hdp == au_h_dptr_i(parent, bindex)) {
  4506. + dput(hdp);
  4507. + continue;
  4508. + }
  4509. +
  4510. + new_bindex = au_find_dbindex(parent, hdp);
  4511. + dput(hdp);
  4512. + DEBUG_ON(new_bindex == bindex);
  4513. + if (dinfo->di_bwh == bindex)
  4514. + bwh = new_bindex;
  4515. + if (dinfo->di_bdiropq == bindex)
  4516. + bdiropq = new_bindex;
  4517. + if (new_bindex < 0) { // test here
  4518. + hdput(p);
  4519. + p->hd_dentry = NULL;
  4520. + continue;
  4521. + }
  4522. + /* swap two hidden dentries, and loop again */
  4523. + q = dinfo->di_hdentry + new_bindex;
  4524. + tmp = *q;
  4525. + *q = *p;
  4526. + *p = tmp;
  4527. + if (tmp.hd_dentry) {
  4528. + bindex--;
  4529. + p--;
  4530. + }
  4531. + }
  4532. +
  4533. + // test here
  4534. + dinfo->di_bwh = -1;
  4535. + if (unlikely(bwh != -1 && bwh <= sbend(sb) && sbr_is_whable(sb, bwh)))
  4536. + dinfo->di_bwh = bwh;
  4537. + dinfo->di_bdiropq = -1;
  4538. + if (unlikely(bdiropq != -1 && bdiropq <= sbend(sb)
  4539. + && sbr_is_whable(sb, bdiropq)))
  4540. + dinfo->di_bdiropq = bdiropq;
  4541. + parent_bend = dbend(parent);
  4542. + p = dinfo->di_hdentry;
  4543. + for (bindex = 0; bindex <= parent_bend; bindex++, p++)
  4544. + if (p->hd_dentry) {
  4545. + dinfo->di_bstart = bindex;
  4546. + break;
  4547. + }
  4548. + p = dinfo->di_hdentry + parent_bend;
  4549. + //for (bindex = parent_bend; bindex > dinfo->di_bstart; bindex--, p--)
  4550. + for (bindex = parent_bend; bindex >= 0; bindex--, p--)
  4551. + if (p->hd_dentry) {
  4552. + dinfo->di_bend = bindex;
  4553. + break;
  4554. + }
  4555. +
  4556. + npositive = 0;
  4557. + parent_bstart = dbstart(parent);
  4558. + if (type != S_IFDIR && dinfo->di_bstart == parent_bstart)
  4559. + goto out_dgen; /* success */
  4560. +
  4561. +#if 0
  4562. + nd.last_type = LAST_ROOT;
  4563. + nd.flags = LOOKUP_FOLLOW;
  4564. + nd.depth = 0;
  4565. + nd.mnt = mntget(??);
  4566. + nd.dentry = dget(parent);
  4567. +#endif
  4568. + npositive = lkup_dentry(dentry, parent_bstart, type);
  4569. + //if (LktrCond) npositive = -1;
  4570. + if (npositive < 0)
  4571. + goto out;
  4572. +
  4573. + out_dgen:
  4574. + au_update_digen(dentry);
  4575. + out:
  4576. + dput(parent);
  4577. + TraceErr(npositive);
  4578. + return npositive;
  4579. +}
  4580. +
  4581. +static int h_d_revalidate(struct dentry *dentry, struct nameidata *nd,
  4582. + int do_udba)
  4583. +{
  4584. + int err, plus, locked, unhashed, is_root, h_plus, is_nfs;
  4585. + struct nameidata fake_nd, *p;
  4586. + aufs_bindex_t bindex, btail, bstart, ibs, ibe;
  4587. + struct super_block *sb;
  4588. + struct inode *inode, *first, *h_inode, *h_cached_inode;
  4589. + umode_t mode, h_mode;
  4590. + struct dentry *h_dentry;
  4591. + int (*reval)(struct dentry *, struct nameidata *);
  4592. + struct qstr *name;
  4593. +
  4594. + LKTRTrace("%.*s\n", DLNPair(dentry));
  4595. + inode = dentry->d_inode;
  4596. + DEBUG_ON(inode && au_digen(dentry) != au_iigen(inode));
  4597. + //DbgDentry(dentry);
  4598. + //DbgInode(inode);
  4599. +
  4600. + err = 0;
  4601. + sb = dentry->d_sb;
  4602. + plus = 0;
  4603. + mode = 0;
  4604. + first = NULL;
  4605. + ibs = ibe = -1;
  4606. + unhashed = d_unhashed(dentry);
  4607. + is_root = IS_ROOT(dentry);
  4608. + name = &dentry->d_name;
  4609. +
  4610. + /*
  4611. + * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
  4612. + * But inotify doesn't fire some necessary events,
  4613. + * IN_ATTRIB for atime/nlink/pageio
  4614. + * IN_DELETE for NFS dentry
  4615. + * Let's do REVAL test too.
  4616. + */
  4617. + if (do_udba && inode) {
  4618. + mode = (inode->i_mode & S_IFMT);
  4619. + plus = (inode->i_nlink > 0);
  4620. + first = au_h_iptr(inode);
  4621. + ibs = ibstart(inode);
  4622. + ibe = ibend(inode);
  4623. + }
  4624. +
  4625. + btail = bstart = dbstart(dentry);
  4626. + if (inode && S_ISDIR(inode->i_mode))
  4627. + btail = dbtaildir(dentry);
  4628. + locked = 0;
  4629. + if (nd) {
  4630. + fake_nd = *nd;
  4631. +#ifndef CONFIG_AUFS_FAKE_DM
  4632. + if (dentry != nd->dentry) {
  4633. + di_read_lock_parent(nd->dentry, 0);
  4634. + locked = 1;
  4635. + }
  4636. +#endif
  4637. + }
  4638. + for (bindex = bstart; bindex <= btail; bindex++) {
  4639. + h_dentry = au_h_dptr_i(dentry, bindex);
  4640. + if (unlikely(!h_dentry))
  4641. + continue;
  4642. + if (unlikely(do_udba
  4643. + && !is_root
  4644. + && (unhashed != d_unhashed(h_dentry)
  4645. +#if 1
  4646. + || name->len != h_dentry->d_name.len
  4647. + || memcmp(name->name, h_dentry->d_name.name,
  4648. + name->len)
  4649. +#endif
  4650. + ))) {
  4651. + LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n",
  4652. + unhashed, d_unhashed(h_dentry),
  4653. + DLNPair(dentry), DLNPair(h_dentry));
  4654. + goto err;
  4655. + }
  4656. +
  4657. + reval = NULL;
  4658. + if (h_dentry->d_op)
  4659. + reval = h_dentry->d_op->d_revalidate;
  4660. + if (unlikely(reval)) {
  4661. + //LKTRLabel(hidden reval);
  4662. + p = fake_dm(&fake_nd, nd, sb, bindex);
  4663. + DEBUG_ON(IS_ERR(p));
  4664. + err = !reval(h_dentry, p);
  4665. + fake_dm_release(p);
  4666. + if (unlikely(err)) {
  4667. + //Dbg("here\n");
  4668. + goto err;
  4669. + }
  4670. + }
  4671. +
  4672. + if (unlikely(!do_udba))
  4673. + continue;
  4674. +
  4675. + /* UDBA tests */
  4676. + h_inode = h_dentry->d_inode;
  4677. + if (unlikely(!!inode != !!h_inode)) {
  4678. + //Dbg("here\n");
  4679. + goto err;
  4680. + }
  4681. +
  4682. + h_plus = plus;
  4683. + h_mode = mode;
  4684. + h_cached_inode = h_inode;
  4685. + is_nfs = 0;
  4686. + if (h_inode) {
  4687. + h_mode = (h_inode->i_mode & S_IFMT);
  4688. + h_plus = (h_inode->i_nlink > 0);
  4689. + }
  4690. + if (inode && ibs <= bindex && bindex <= ibe) {
  4691. + h_cached_inode = au_h_iptr_i(inode, bindex);
  4692. + //is_nfs = au_is_nfs(h_cached_inode->i_sb);
  4693. + }
  4694. +
  4695. + LKTRTrace("{%d, 0%o, %p}, h{%d, 0%o, %p}\n",
  4696. + plus, mode, h_cached_inode,
  4697. + h_plus, h_mode, h_inode);
  4698. + if (unlikely(plus != h_plus || mode != h_mode
  4699. + || (h_cached_inode != h_inode /* && !is_nfs */))) {
  4700. + //Dbg("here\n");
  4701. + goto err;
  4702. + }
  4703. + continue;
  4704. +
  4705. + err:
  4706. + err = -EINVAL;
  4707. + break;
  4708. + }
  4709. +#ifndef CONFIG_AUFS_FAKE_DM
  4710. + if (unlikely(locked))
  4711. + di_read_unlock(nd->dentry, 0);
  4712. +#endif
  4713. +
  4714. +#if 0
  4715. + // some filesystem uses CURRENT_TIME_SEC instead of CURRENT_TIME.
  4716. + // NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED.
  4717. +#if 0
  4718. + && (!timespec_equal(&inode->i_ctime, &first->i_ctime)
  4719. + || !timespec_equal(&inode->i_atime, &first->i_atime))
  4720. +#endif
  4721. + if (unlikely(!err && udba && first))
  4722. + au_cpup_attr_all(inode);
  4723. +#endif
  4724. +
  4725. + TraceErr(err);
  4726. + return err;
  4727. +}
  4728. +
  4729. +static int simple_reval_dpath(struct dentry *dentry, int sgen)
  4730. +{
  4731. + int err;
  4732. + mode_t type;
  4733. + struct dentry *parent;
  4734. + struct inode *inode;
  4735. +
  4736. + LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
  4737. + SiMustAnyLock(dentry->d_sb);
  4738. + DiMustWriteLock(dentry);
  4739. + inode = dentry->d_inode;
  4740. + DEBUG_ON(!inode);
  4741. +
  4742. + if (au_digen(dentry) == sgen)
  4743. + return 0;
  4744. +
  4745. + parent = dget_parent(dentry);
  4746. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  4747. + DEBUG_ON(au_digen(parent) != sgen);
  4748. +#ifdef CONFIG_AUFS_DEBUG
  4749. + {
  4750. + struct dentry *d = parent;
  4751. + while (!IS_ROOT(d)) {
  4752. + DEBUG_ON(au_digen(d) != sgen);
  4753. + d = d->d_parent;
  4754. + }
  4755. + }
  4756. +#endif
  4757. + type = (inode->i_mode & S_IFMT);
  4758. + /* returns a number of positive dentries */
  4759. + err = au_refresh_hdentry(dentry, type);
  4760. + if (err >= 0)
  4761. + err = au_refresh_hinode(inode, dentry);
  4762. + di_read_unlock(parent, AUFS_I_RLOCK);
  4763. + dput(parent);
  4764. + TraceErr(err);
  4765. + return err;
  4766. +}
  4767. +
  4768. +int au_reval_dpath(struct dentry *dentry, int sgen)
  4769. +{
  4770. + int err;
  4771. + struct dentry *d, *parent;
  4772. + struct inode *inode;
  4773. +
  4774. + LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
  4775. + DEBUG_ON(!dentry->d_inode);
  4776. + DiMustWriteLock(dentry);
  4777. +
  4778. + if (!stosi(dentry->d_sb)->si_failed_refresh_dirs)
  4779. + return simple_reval_dpath(dentry, sgen);
  4780. +
  4781. + /* slow loop, keep it simple and stupid */
  4782. + /* cf: cpup_dirs() */
  4783. + err = 0;
  4784. + while (au_digen(dentry) != sgen) {
  4785. + d = dentry;
  4786. + while (1) {
  4787. + parent = d->d_parent; // dget_parent()
  4788. + if (au_digen(parent) == sgen)
  4789. + break;
  4790. + d = parent;
  4791. + }
  4792. +
  4793. + inode = d->d_inode;
  4794. + if (d != dentry) {
  4795. + //i_lock(inode);
  4796. + di_write_lock_child(d);
  4797. + }
  4798. +
  4799. + /* someone might update our dentry while we were sleeping */
  4800. + if (au_digen(d) != sgen) {
  4801. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  4802. + /* returns a number of positive dentries */
  4803. + err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
  4804. + //err = -1;
  4805. + if (err >= 0)
  4806. + err = au_refresh_hinode(inode, d);
  4807. + //err = -1;
  4808. + di_read_unlock(parent, AUFS_I_RLOCK);
  4809. + }
  4810. +
  4811. + if (d != dentry) {
  4812. + di_write_unlock(d);
  4813. + //i_unlock(inode);
  4814. + }
  4815. + if (unlikely(err))
  4816. + break;
  4817. + }
  4818. +
  4819. + TraceErr(err);
  4820. + return err;
  4821. +}
  4822. +
  4823. +/*
  4824. + * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise.
  4825. + * nfsd passes NULL as nameidata.
  4826. + */
  4827. +static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
  4828. +{
  4829. + int valid, sgen, err, do_udba;
  4830. + struct super_block *sb;
  4831. + struct inode *inode;
  4832. +
  4833. + LKTRTrace("dentry %.*s\n", DLNPair(dentry));
  4834. + if (nd && nd->dentry)
  4835. + LKTRTrace("nd %.*s\n", DLNPair(nd->dentry));
  4836. + //dir case: DEBUG_ON(dentry->d_parent != nd->dentry);
  4837. + //remove failure case: DEBUG_ON(!IS_ROOT(dentry) && d_unhashed(dentry));
  4838. + DEBUG_ON(!dentry->d_fsdata);
  4839. + //DbgDentry(dentry);
  4840. +
  4841. + err = -EINVAL;
  4842. + inode = dentry->d_inode;
  4843. + //DbgInode(inode);
  4844. + sb = dentry->d_sb;
  4845. + si_read_lock(sb);
  4846. + sgen = au_sigen(sb);
  4847. + if (au_digen(dentry) == sgen)
  4848. + di_read_lock_child(dentry, !AUFS_I_RLOCK);
  4849. + else {
  4850. + DEBUG_ON(IS_ROOT(dentry));
  4851. +#ifdef ForceInotify
  4852. + Dbg("UDBA or digen, %.*s\n", DLNPair(dentry));
  4853. +#endif
  4854. + //i_lock(inode);
  4855. + di_write_lock_child(dentry);
  4856. + if (inode)
  4857. + err = au_reval_dpath(dentry, sgen);
  4858. + //err = -1;
  4859. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  4860. + //i_unlock(inode);
  4861. + if (unlikely(err))
  4862. + goto out;
  4863. + ii_read_unlock(inode);
  4864. + DEBUG_ON(au_iigen(inode) != sgen);
  4865. + }
  4866. +
  4867. + if (inode) {
  4868. + if (au_iigen(inode) == sgen)
  4869. + ii_read_lock_child(inode);
  4870. + else {
  4871. + DEBUG_ON(IS_ROOT(dentry));
  4872. +#ifdef ForceInotify
  4873. + Dbg("UDBA or survived, %.*s\n", DLNPair(dentry));
  4874. +#endif
  4875. + ii_write_lock_child(inode);
  4876. + err = au_refresh_hinode(inode, dentry);
  4877. + ii_downgrade_lock(inode);
  4878. + if (unlikely(err))
  4879. + goto out;
  4880. + DEBUG_ON(au_iigen(inode) != sgen);
  4881. + }
  4882. + }
  4883. +
  4884. +#if 0 // fix it
  4885. + /* parent dir i_nlink is not updated in the case of setattr */
  4886. + if (S_ISDIR(inode->i_mode)) {
  4887. + i_lock(inode);
  4888. + ii_write_lock(inode);
  4889. + au_cpup_attr_nlink(inode);
  4890. + ii_write_unlock(inode);
  4891. + i_unlock(inode);
  4892. + }
  4893. +#endif
  4894. +
  4895. + err = -EINVAL;
  4896. + do_udba = !au_flag_test(sb, AuFlag_UDBA_NONE);
  4897. + if (do_udba && inode && ibstart(inode) >= 0
  4898. + && au_test_higen(inode, au_h_iptr(inode)))
  4899. + goto out;
  4900. + err = h_d_revalidate(dentry, nd, do_udba);
  4901. + //err = -1;
  4902. +
  4903. + out:
  4904. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  4905. + TraceErr(err);
  4906. + valid = !err;
  4907. + //au_debug_on();
  4908. + if (!valid)
  4909. + LKTRTrace("%.*s invalid\n", DLNPair(dentry));
  4910. + //au_debug_off();
  4911. + return valid;
  4912. +}
  4913. +
  4914. +static void aufs_d_release(struct dentry *dentry)
  4915. +{
  4916. + struct aufs_dinfo *dinfo;
  4917. + aufs_bindex_t bend, bindex;
  4918. +
  4919. + LKTRTrace("%.*s\n", DLNPair(dentry));
  4920. + DEBUG_ON(!d_unhashed(dentry));
  4921. +
  4922. + dinfo = dentry->d_fsdata;
  4923. + if (unlikely(!dinfo))
  4924. + return;
  4925. +
  4926. + /* dentry may not be revalidated */
  4927. + bindex = dinfo->di_bstart;
  4928. + if (bindex >= 0) {
  4929. + struct aufs_hdentry *p;
  4930. + bend = dinfo->di_bend;
  4931. + DEBUG_ON(bend < bindex);
  4932. + p = dinfo->di_hdentry + bindex;
  4933. + while (bindex++ <= bend) {
  4934. + if (p->hd_dentry)
  4935. + hdput(p);
  4936. + p++;
  4937. + }
  4938. + }
  4939. + kfree(dinfo->di_hdentry);
  4940. + cache_free_dinfo(dinfo);
  4941. +}
  4942. +
  4943. +#if 0
  4944. +/* it may be called at remount time, too */
  4945. +static void aufs_d_iput(struct dentry *dentry, struct inode *inode)
  4946. +{
  4947. + struct super_block *sb;
  4948. +
  4949. + LKTRTrace("%.*s, i%lu\n", DLNPair(dentry), inode->i_ino);
  4950. +
  4951. + sb = dentry->d_sb;
  4952. +#if 0
  4953. + si_read_lock(sb);
  4954. + if (unlikely(au_flag_test(sb, AuFlag_PLINK)
  4955. + && au_is_plinked(sb, inode))) {
  4956. + ii_write_lock(inode);
  4957. + au_update_brange(inode, 1);
  4958. + ii_write_unlock(inode);
  4959. + }
  4960. + si_read_unlock(sb);
  4961. +#endif
  4962. + iput(inode);
  4963. +}
  4964. +#endif
  4965. +
  4966. +struct dentry_operations aufs_dop = {
  4967. + .d_revalidate = aufs_d_revalidate,
  4968. + .d_release = aufs_d_release
  4969. + //.d_iput = aufs_d_iput
  4970. +};
  4971. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dentry.h linux-2.6.22.1/fs/aufs/dentry.h
  4972. --- linux-2.6.22.1.oorig/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
  4973. +++ linux-2.6.22.1/fs/aufs/dentry.h 2007-07-24 14:17:46.000000000 +0200
  4974. @@ -0,0 +1,183 @@
  4975. +/*
  4976. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  4977. + *
  4978. + * This program, aufs is free software; you can redistribute it and/or modify
  4979. + * it under the terms of the GNU General Public License as published by
  4980. + * the Free Software Foundation; either version 2 of the License, or
  4981. + * (at your option) any later version.
  4982. + *
  4983. + * This program is distributed in the hope that it will be useful,
  4984. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  4985. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  4986. + * GNU General Public License for more details.
  4987. + *
  4988. + * You should have received a copy of the GNU General Public License
  4989. + * along with this program; if not, write to the Free Software
  4990. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  4991. + */
  4992. +
  4993. +/* $Id: dentry.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
  4994. +
  4995. +#ifndef __AUFS_DENTRY_H__
  4996. +#define __AUFS_DENTRY_H__
  4997. +
  4998. +#ifdef __KERNEL__
  4999. +
  5000. +#include <linux/fs.h>
  5001. +#include <linux/aufs_type.h>
  5002. +#include "misc.h"
  5003. +
  5004. +struct aufs_hdentry {
  5005. + struct dentry *hd_dentry;
  5006. +};
  5007. +
  5008. +struct aufs_dinfo {
  5009. + atomic_t di_generation;
  5010. +
  5011. + struct aufs_rwsem di_rwsem;
  5012. + aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
  5013. + struct aufs_hdentry *di_hdentry;
  5014. +};
  5015. +
  5016. +struct lkup_args {
  5017. + struct vfsmount *nfsmnt;
  5018. + int dlgt;
  5019. + //struct super_block *sb;
  5020. +};
  5021. +
  5022. +/* ---------------------------------------------------------------------- */
  5023. +
  5024. +/* dentry.c */
  5025. +#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
  5026. +struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
  5027. + struct lkup_args *lkup);
  5028. +#else
  5029. +static inline
  5030. +struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
  5031. + struct lkup_args *lkup)
  5032. +{
  5033. + return lookup_one_len(name, parent, len);
  5034. +}
  5035. +#endif
  5036. +
  5037. +extern struct dentry_operations aufs_dop;
  5038. +struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
  5039. + struct lkup_args *lkup);
  5040. +int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type);
  5041. +int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
  5042. +int au_refresh_hdentry(struct dentry *dentry, mode_t type);
  5043. +int au_reval_dpath(struct dentry *dentry, int sgen);
  5044. +
  5045. +/* dinfo.c */
  5046. +int au_alloc_dinfo(struct dentry *dentry);
  5047. +struct aufs_dinfo *dtodi(struct dentry *dentry);
  5048. +
  5049. +void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
  5050. +void di_read_unlock(struct dentry *d, int flags);
  5051. +void di_downgrade_lock(struct dentry *d, int flags);
  5052. +void di_write_lock(struct dentry *d, unsigned int lsc);
  5053. +void di_write_unlock(struct dentry *d);
  5054. +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
  5055. +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
  5056. +void di_write_unlock2(struct dentry *d1, struct dentry *d2);
  5057. +
  5058. +aufs_bindex_t dbstart(struct dentry *dentry);
  5059. +aufs_bindex_t dbend(struct dentry *dentry);
  5060. +aufs_bindex_t dbwh(struct dentry *dentry);
  5061. +aufs_bindex_t dbdiropq(struct dentry *dentry);
  5062. +struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex);
  5063. +struct dentry *au_h_dptr(struct dentry *dentry);
  5064. +
  5065. +aufs_bindex_t dbtail(struct dentry *dentry);
  5066. +aufs_bindex_t dbtaildir(struct dentry *dentry);
  5067. +aufs_bindex_t dbtail_generic(struct dentry *dentry);
  5068. +
  5069. +void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex);
  5070. +void set_dbend(struct dentry *dentry, aufs_bindex_t bindex);
  5071. +void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex);
  5072. +void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex);
  5073. +void hdput(struct aufs_hdentry *hdentry);
  5074. +void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
  5075. + struct dentry *h_dentry);
  5076. +
  5077. +void au_update_digen(struct dentry *dentry);
  5078. +void au_update_dbstart(struct dentry *dentry);
  5079. +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
  5080. +
  5081. +/* ---------------------------------------------------------------------- */
  5082. +
  5083. +static inline int au_digen(struct dentry *d)
  5084. +{
  5085. + return atomic_read(&dtodi(d)->di_generation);
  5086. +}
  5087. +
  5088. +#ifdef CONFIG_AUFS_HINOTIFY
  5089. +static inline void au_digen_dec(struct dentry *d)
  5090. +{
  5091. + atomic_dec(&dtodi(d)->di_generation);
  5092. +}
  5093. +#endif /* CONFIG_AUFS_HINOTIFY */
  5094. +
  5095. +/* ---------------------------------------------------------------------- */
  5096. +
  5097. +/* lock subclass for dinfo */
  5098. +enum {
  5099. + AuLsc_DI_CHILD, /* child first */
  5100. + AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
  5101. + AuLsc_DI_CHILD3, /* copyup dirs */
  5102. + AuLsc_DI_PARENT,
  5103. + AuLsc_DI_PARENT2,
  5104. + AuLsc_DI_PARENT3
  5105. +};
  5106. +
  5107. +/*
  5108. + * di_read_lock_child, di_write_lock_child,
  5109. + * di_read_lock_child2, di_write_lock_child2,
  5110. + * di_read_lock_child3, di_write_lock_child3,
  5111. + * di_read_lock_parent, di_write_lock_parent,
  5112. + * di_read_lock_parent2, di_write_lock_parent2,
  5113. + * di_read_lock_parent3, di_write_lock_parent3,
  5114. + */
  5115. +#define ReadLockFunc(name, lsc) \
  5116. +static inline void di_read_lock_##name(struct dentry *d, int flags) \
  5117. +{di_read_lock(d, flags, AuLsc_DI_##lsc);}
  5118. +
  5119. +#define WriteLockFunc(name, lsc) \
  5120. +static inline void di_write_lock_##name(struct dentry *d) \
  5121. +{di_write_lock(d, AuLsc_DI_##lsc);}
  5122. +
  5123. +#define RWLockFuncs(name, lsc) \
  5124. + ReadLockFunc(name, lsc); \
  5125. + WriteLockFunc(name, lsc)
  5126. +
  5127. +RWLockFuncs(child, CHILD);
  5128. +RWLockFuncs(child2, CHILD2);
  5129. +RWLockFuncs(child3, CHILD3);
  5130. +RWLockFuncs(parent, PARENT);
  5131. +RWLockFuncs(parent2, PARENT2);
  5132. +RWLockFuncs(parent3, PARENT3);
  5133. +
  5134. +#undef ReadLockFunc
  5135. +#undef WriteLockFunc
  5136. +#undef RWLockFunc
  5137. +
  5138. +/* to debug easier, do not make them inlined functions */
  5139. +#define DiMustReadLock(d) do { \
  5140. + SiMustAnyLock((d)->d_sb); \
  5141. + RwMustReadLock(&dtodi(d)->di_rwsem); \
  5142. +} while (0)
  5143. +
  5144. +#define DiMustWriteLock(d) do { \
  5145. + SiMustAnyLock((d)->d_sb); \
  5146. + RwMustWriteLock(&dtodi(d)->di_rwsem); \
  5147. +} while (0)
  5148. +
  5149. +#define DiMustAnyLock(d) do { \
  5150. + SiMustAnyLock((d)->d_sb); \
  5151. + RwMustAnyLock(&dtodi(d)->di_rwsem); \
  5152. +} while (0)
  5153. +
  5154. +#define DiMustNoWaiters(d) RwMustNoWaiters(&dtodi(d)->di_rwsem)
  5155. +
  5156. +#endif /* __KERNEL__ */
  5157. +#endif /* __AUFS_DENTRY_H__ */
  5158. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dinfo.c linux-2.6.22.1/fs/aufs/dinfo.c
  5159. --- linux-2.6.22.1.oorig/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
  5160. +++ linux-2.6.22.1/fs/aufs/dinfo.c 2007-07-24 14:17:46.000000000 +0200
  5161. @@ -0,0 +1,419 @@
  5162. +/*
  5163. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  5164. + *
  5165. + * This program, aufs is free software; you can redistribute it and/or modify
  5166. + * it under the terms of the GNU General Public License as published by
  5167. + * the Free Software Foundation; either version 2 of the License, or
  5168. + * (at your option) any later version.
  5169. + *
  5170. + * This program is distributed in the hope that it will be useful,
  5171. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5172. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5173. + * GNU General Public License for more details.
  5174. + *
  5175. + * You should have received a copy of the GNU General Public License
  5176. + * along with this program; if not, write to the Free Software
  5177. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  5178. + */
  5179. +
  5180. +/* $Id: dinfo.c,v 1.23 2007/05/07 03:43:36 sfjro Exp $ */
  5181. +
  5182. +#include "aufs.h"
  5183. +
  5184. +int au_alloc_dinfo(struct dentry *dentry)
  5185. +{
  5186. + struct aufs_dinfo *dinfo;
  5187. + struct super_block *sb;
  5188. + int nbr;
  5189. +
  5190. + LKTRTrace("%.*s\n", DLNPair(dentry));
  5191. + DEBUG_ON(dentry->d_fsdata);
  5192. +
  5193. + dinfo = cache_alloc_dinfo();
  5194. + //if (LktrCond) {cache_free_dinfo(dinfo); dinfo = NULL;}
  5195. + if (dinfo) {
  5196. + sb = dentry->d_sb;
  5197. + nbr = sbend(sb) + 1;
  5198. + if (unlikely(!nbr))
  5199. + nbr++;
  5200. + dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
  5201. + GFP_KERNEL);
  5202. + //if (LktrCond)
  5203. + //{kfree(dinfo->di_hdentry); dinfo->di_hdentry = NULL;}
  5204. + if (dinfo->di_hdentry) {
  5205. + rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_PARENT);
  5206. + dinfo->di_bstart = dinfo->di_bend = -1;
  5207. + dinfo->di_bwh = dinfo->di_bdiropq = -1;
  5208. + atomic_set(&dinfo->di_generation, au_sigen(sb));
  5209. +
  5210. + dentry->d_fsdata = dinfo;
  5211. + dentry->d_op = &aufs_dop;
  5212. + return 0; /* success */
  5213. + }
  5214. + cache_free_dinfo(dinfo);
  5215. + }
  5216. + TraceErr(-ENOMEM);
  5217. + return -ENOMEM;
  5218. +}
  5219. +
  5220. +struct aufs_dinfo *dtodi(struct dentry *dentry)
  5221. +{
  5222. + struct aufs_dinfo *dinfo = dentry->d_fsdata;
  5223. + DEBUG_ON(!dinfo
  5224. + || !dinfo->di_hdentry
  5225. + /* || stosi(dentry->d_sb)->si_bend < dinfo->di_bend */
  5226. + || dinfo->di_bend < dinfo->di_bstart
  5227. + /* dbwh can be outside of this range */
  5228. + || (0 <= dinfo->di_bdiropq
  5229. + && (dinfo->di_bdiropq < dinfo->di_bstart
  5230. + /* || dinfo->di_bend < dinfo->di_bdiropq */))
  5231. + );
  5232. + return dinfo;
  5233. +}
  5234. +
  5235. +/* ---------------------------------------------------------------------- */
  5236. +
  5237. +static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
  5238. +{
  5239. + switch (lsc) {
  5240. + case AuLsc_DI_CHILD:
  5241. + ii_write_lock_child(inode);
  5242. + break;
  5243. + case AuLsc_DI_CHILD2:
  5244. + ii_write_lock_child2(inode);
  5245. + break;
  5246. + case AuLsc_DI_CHILD3:
  5247. + ii_write_lock_child3(inode);
  5248. + break;
  5249. + case AuLsc_DI_PARENT:
  5250. + ii_write_lock_parent(inode);
  5251. + break;
  5252. + case AuLsc_DI_PARENT2:
  5253. + ii_write_lock_parent2(inode);
  5254. + break;
  5255. + case AuLsc_DI_PARENT3:
  5256. + ii_write_lock_parent3(inode);
  5257. + break;
  5258. + default:
  5259. + BUG();
  5260. + }
  5261. +}
  5262. +
  5263. +static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
  5264. +{
  5265. + switch (lsc) {
  5266. + case AuLsc_DI_CHILD:
  5267. + ii_read_lock_child(inode);
  5268. + break;
  5269. + case AuLsc_DI_CHILD2:
  5270. + ii_read_lock_child2(inode);
  5271. + break;
  5272. + case AuLsc_DI_CHILD3:
  5273. + ii_read_lock_child3(inode);
  5274. + break;
  5275. + case AuLsc_DI_PARENT:
  5276. + ii_read_lock_parent(inode);
  5277. + break;
  5278. + case AuLsc_DI_PARENT2:
  5279. + ii_read_lock_parent2(inode);
  5280. + break;
  5281. + case AuLsc_DI_PARENT3:
  5282. + ii_read_lock_parent3(inode);
  5283. + break;
  5284. + default:
  5285. + BUG();
  5286. + }
  5287. +}
  5288. +
  5289. +void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
  5290. +{
  5291. + SiMustAnyLock(d->d_sb);
  5292. + // todo: always nested?
  5293. + rw_read_lock_nested(&dtodi(d)->di_rwsem, lsc);
  5294. + if (d->d_inode) {
  5295. + if (flags & AUFS_I_WLOCK)
  5296. + do_ii_write_lock(d->d_inode, lsc);
  5297. + else if (flags & AUFS_I_RLOCK)
  5298. + do_ii_read_lock(d->d_inode, lsc);
  5299. + }
  5300. +}
  5301. +
  5302. +void di_read_unlock(struct dentry *d, int flags)
  5303. +{
  5304. + SiMustAnyLock(d->d_sb);
  5305. + if (d->d_inode) {
  5306. + if (flags & AUFS_I_WLOCK)
  5307. + ii_write_unlock(d->d_inode);
  5308. + else if (flags & AUFS_I_RLOCK)
  5309. + ii_read_unlock(d->d_inode);
  5310. + }
  5311. + rw_read_unlock(&dtodi(d)->di_rwsem);
  5312. +}
  5313. +
  5314. +void di_downgrade_lock(struct dentry *d, int flags)
  5315. +{
  5316. + SiMustAnyLock(d->d_sb);
  5317. + rw_dgrade_lock(&dtodi(d)->di_rwsem);
  5318. + if (d->d_inode && (flags & AUFS_I_RLOCK))
  5319. + ii_downgrade_lock(d->d_inode);
  5320. +}
  5321. +
  5322. +void di_write_lock(struct dentry *d, unsigned int lsc)
  5323. +{
  5324. + SiMustAnyLock(d->d_sb);
  5325. + // todo: always nested?
  5326. + rw_write_lock_nested(&dtodi(d)->di_rwsem, lsc);
  5327. + if (d->d_inode)
  5328. + do_ii_write_lock(d->d_inode, lsc);
  5329. +}
  5330. +
  5331. +void di_write_unlock(struct dentry *d)
  5332. +{
  5333. + SiMustAnyLock(d->d_sb);
  5334. + if (d->d_inode)
  5335. + ii_write_unlock(d->d_inode);
  5336. + rw_write_unlock(&dtodi(d)->di_rwsem);
  5337. +}
  5338. +
  5339. +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
  5340. +{
  5341. + struct dentry *d;
  5342. +
  5343. + TraceEnter();
  5344. + DEBUG_ON(d1 == d2
  5345. + || d1->d_inode == d2->d_inode
  5346. + || d1->d_sb != d2->d_sb);
  5347. +
  5348. + if (isdir)
  5349. + for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
  5350. + if (d->d_parent == d2) {
  5351. + di_write_lock_child(d1);
  5352. + di_write_lock_child2(d2);
  5353. + return;
  5354. + }
  5355. +
  5356. + di_write_lock_child(d2);
  5357. + di_write_lock_child2(d1);
  5358. +}
  5359. +
  5360. +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
  5361. +{
  5362. + struct dentry *d;
  5363. +
  5364. + TraceEnter();
  5365. + DEBUG_ON(d1 == d2
  5366. + || d1->d_inode == d2->d_inode
  5367. + || d1->d_sb != d2->d_sb);
  5368. +
  5369. + if (isdir)
  5370. + for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
  5371. + if (d->d_parent == d2) {
  5372. + di_write_lock_parent(d1);
  5373. + di_write_lock_parent2(d2);
  5374. + return;
  5375. + }
  5376. +
  5377. + di_write_lock_parent(d2);
  5378. + di_write_lock_parent2(d1);
  5379. +}
  5380. +
  5381. +void di_write_unlock2(struct dentry *d1, struct dentry *d2)
  5382. +{
  5383. + di_write_unlock(d1);
  5384. + if (d1->d_inode == d2->d_inode)
  5385. + rw_write_unlock(&dtodi(d2)->di_rwsem);
  5386. + else
  5387. + di_write_unlock(d2);
  5388. +}
  5389. +
  5390. +/* ---------------------------------------------------------------------- */
  5391. +
  5392. +aufs_bindex_t dbstart(struct dentry *dentry)
  5393. +{
  5394. + DiMustAnyLock(dentry);
  5395. + return dtodi(dentry)->di_bstart;
  5396. +}
  5397. +
  5398. +aufs_bindex_t dbend(struct dentry *dentry)
  5399. +{
  5400. + DiMustAnyLock(dentry);
  5401. + return dtodi(dentry)->di_bend;
  5402. +}
  5403. +
  5404. +aufs_bindex_t dbwh(struct dentry *dentry)
  5405. +{
  5406. + DiMustAnyLock(dentry);
  5407. + return dtodi(dentry)->di_bwh;
  5408. +}
  5409. +
  5410. +aufs_bindex_t dbdiropq(struct dentry *dentry)
  5411. +{
  5412. + DiMustAnyLock(dentry);
  5413. + DEBUG_ON(dentry->d_inode
  5414. + && dentry->d_inode->i_mode
  5415. + && !S_ISDIR(dentry->d_inode->i_mode));
  5416. + return dtodi(dentry)->di_bdiropq;
  5417. +}
  5418. +
  5419. +struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex)
  5420. +{
  5421. + struct dentry *d;
  5422. +
  5423. + DiMustAnyLock(dentry);
  5424. + if (dbstart(dentry) < 0 || bindex < dbstart(dentry))
  5425. + return NULL;
  5426. + DEBUG_ON(bindex < 0
  5427. + /* || bindex > sbend(dentry->d_sb) */);
  5428. + d = dtodi(dentry)->di_hdentry[0 + bindex].hd_dentry;
  5429. + DEBUG_ON(d && (atomic_read(&d->d_count) <= 0));
  5430. + return d;
  5431. +}
  5432. +
  5433. +struct dentry *au_h_dptr(struct dentry *dentry)
  5434. +{
  5435. + return au_h_dptr_i(dentry, dbstart(dentry));
  5436. +}
  5437. +
  5438. +aufs_bindex_t dbtail(struct dentry *dentry)
  5439. +{
  5440. + aufs_bindex_t bend, bwh;
  5441. +
  5442. + bend = dbend(dentry);
  5443. + if (0 <= bend) {
  5444. + bwh = dbwh(dentry);
  5445. + //DEBUG_ON(bend < bwh);
  5446. + if (!bwh)
  5447. + return bwh;
  5448. + if (0 < bwh && bwh < bend)
  5449. + return bwh - 1;
  5450. + }
  5451. + return bend;
  5452. +}
  5453. +
  5454. +aufs_bindex_t dbtaildir(struct dentry *dentry)
  5455. +{
  5456. + aufs_bindex_t bend, bopq;
  5457. +
  5458. + DEBUG_ON(dentry->d_inode
  5459. + && dentry->d_inode->i_mode
  5460. + && !S_ISDIR(dentry->d_inode->i_mode));
  5461. +
  5462. + bend = dbtail(dentry);
  5463. + if (0 <= bend) {
  5464. + bopq = dbdiropq(dentry);
  5465. + DEBUG_ON(bend < bopq);
  5466. + if (0 <= bopq && bopq < bend)
  5467. + bend = bopq;
  5468. + }
  5469. + return bend;
  5470. +}
  5471. +
  5472. +aufs_bindex_t dbtail_generic(struct dentry *dentry)
  5473. +{
  5474. + struct inode *inode;
  5475. +
  5476. + inode = dentry->d_inode;
  5477. + if (inode && S_ISDIR(inode->i_mode))
  5478. + return dbtaildir(dentry);
  5479. + else
  5480. + return dbtail(dentry);
  5481. +}
  5482. +
  5483. +/* ---------------------------------------------------------------------- */
  5484. +
  5485. +// hard/soft set
  5486. +void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
  5487. +{
  5488. + DiMustWriteLock(dentry);
  5489. + DEBUG_ON(sbend(dentry->d_sb) < bindex);
  5490. + /* */
  5491. + dtodi(dentry)->di_bstart = bindex;
  5492. +}
  5493. +
  5494. +void set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
  5495. +{
  5496. + DiMustWriteLock(dentry);
  5497. + DEBUG_ON(sbend(dentry->d_sb) < bindex
  5498. + || bindex < dbstart(dentry));
  5499. + dtodi(dentry)->di_bend = bindex;
  5500. +}
  5501. +
  5502. +void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
  5503. +{
  5504. + DiMustWriteLock(dentry);
  5505. + DEBUG_ON(sbend(dentry->d_sb) < bindex);
  5506. + /* dbwh can be outside of bstart - bend range */
  5507. + dtodi(dentry)->di_bwh = bindex;
  5508. +}
  5509. +
  5510. +void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
  5511. +{
  5512. + DiMustWriteLock(dentry);
  5513. + DEBUG_ON(sbend(dentry->d_sb) < bindex);
  5514. + DEBUG_ON((bindex != -1
  5515. + && (bindex < dbstart(dentry) || dbend(dentry) < bindex))
  5516. + || (dentry->d_inode
  5517. + && dentry->d_inode->i_mode
  5518. + && !S_ISDIR(dentry->d_inode->i_mode)));
  5519. + dtodi(dentry)->di_bdiropq = bindex;
  5520. +}
  5521. +
  5522. +void hdput(struct aufs_hdentry *hd)
  5523. +{
  5524. + dput(hd->hd_dentry);
  5525. +}
  5526. +
  5527. +void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
  5528. + struct dentry *h_dentry)
  5529. +{
  5530. + struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
  5531. + DiMustWriteLock(dentry);
  5532. + DEBUG_ON(bindex < dtodi(dentry)->di_bstart
  5533. + || bindex > dtodi(dentry)->di_bend
  5534. + || (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
  5535. + || (h_dentry && hd->hd_dentry)
  5536. + );
  5537. + if (hd->hd_dentry)
  5538. + hdput(hd);
  5539. + hd->hd_dentry = h_dentry;
  5540. +}
  5541. +
  5542. +/* ---------------------------------------------------------------------- */
  5543. +
  5544. +void au_update_digen(struct dentry *dentry)
  5545. +{
  5546. + //DiMustWriteLock(dentry);
  5547. + DEBUG_ON(!dentry->d_sb);
  5548. + atomic_set(&dtodi(dentry)->di_generation, au_sigen(dentry->d_sb));
  5549. +}
  5550. +
  5551. +void au_update_dbstart(struct dentry *dentry)
  5552. +{
  5553. + aufs_bindex_t bindex, bstart = dbstart(dentry), bend = dbend(dentry);
  5554. + struct dentry *hidden_dentry;
  5555. +
  5556. + DiMustWriteLock(dentry);
  5557. + for (bindex = bstart; bindex <= bend; bindex++) {
  5558. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  5559. + if (!hidden_dentry)
  5560. + continue;
  5561. + if (hidden_dentry->d_inode) {
  5562. + set_dbstart(dentry, bindex);
  5563. + return;
  5564. + }
  5565. + set_h_dptr(dentry, bindex, NULL);
  5566. + }
  5567. + //set_dbstart(dentry, -1);
  5568. + //set_dbend(dentry, -1);
  5569. +}
  5570. +
  5571. +int au_find_dbindex(struct dentry *dentry, struct dentry *hidden_dentry)
  5572. +{
  5573. + aufs_bindex_t bindex, bend;
  5574. +
  5575. + bend = dbend(dentry);
  5576. + for (bindex = dbstart(dentry); bindex <= bend; bindex++)
  5577. + if (au_h_dptr_i(dentry, bindex) == hidden_dentry)
  5578. + return bindex;
  5579. + return -1;
  5580. +}
  5581. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dir.c linux-2.6.22.1/fs/aufs/dir.c
  5582. --- linux-2.6.22.1.oorig/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
  5583. +++ linux-2.6.22.1/fs/aufs/dir.c 2007-07-24 14:17:46.000000000 +0200
  5584. @@ -0,0 +1,564 @@
  5585. +/*
  5586. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  5587. + *
  5588. + * This program, aufs is free software; you can redistribute it and/or modify
  5589. + * it under the terms of the GNU General Public License as published by
  5590. + * the Free Software Foundation; either version 2 of the License, or
  5591. + * (at your option) any later version.
  5592. + *
  5593. + * This program is distributed in the hope that it will be useful,
  5594. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5595. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5596. + * GNU General Public License for more details.
  5597. + *
  5598. + * You should have received a copy of the GNU General Public License
  5599. + * along with this program; if not, write to the Free Software
  5600. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  5601. + */
  5602. +
  5603. +/* $Id: dir.c,v 1.36 2007/05/14 03:38:52 sfjro Exp $ */
  5604. +
  5605. +#include "aufs.h"
  5606. +
  5607. +static int reopen_dir(struct file *file)
  5608. +{
  5609. + int err;
  5610. + struct dentry *dentry, *hidden_dentry;
  5611. + aufs_bindex_t bindex, btail, bstart;
  5612. + struct file *hidden_file;
  5613. +
  5614. + dentry = file->f_dentry;
  5615. + LKTRTrace("%.*s\n", DLNPair(dentry));
  5616. + DEBUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
  5617. +
  5618. + /* open all hidden dirs */
  5619. + bstart = dbstart(dentry);
  5620. +#if 1
  5621. + for (bindex = fbstart(file); bindex < bstart; bindex++)
  5622. + set_h_fptr(file, bindex, NULL);
  5623. +#endif
  5624. + set_fbstart(file, bstart);
  5625. + btail = dbtaildir(dentry);
  5626. +#if 1
  5627. + for (bindex = fbend(file); btail < bindex; bindex--)
  5628. + set_h_fptr(file, bindex, NULL);
  5629. +#endif
  5630. + set_fbend(file, btail);
  5631. + for (bindex = bstart; bindex <= btail; bindex++) {
  5632. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  5633. + if (!hidden_dentry)
  5634. + continue;
  5635. + hidden_file = au_h_fptr_i(file, bindex);
  5636. + if (hidden_file) {
  5637. + DEBUG_ON(hidden_file->f_dentry != hidden_dentry);
  5638. + continue;
  5639. + }
  5640. +
  5641. + hidden_file = hidden_open(dentry, bindex, file->f_flags);
  5642. + // unavailable
  5643. + //if (LktrCond) {fput(hidden_file);
  5644. + //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
  5645. + err = PTR_ERR(hidden_file);
  5646. + if (IS_ERR(hidden_file))
  5647. + goto out; // close all?
  5648. + //cpup_file_flags(hidden_file, file);
  5649. + set_h_fptr(file, bindex, hidden_file);
  5650. + }
  5651. + err = 0;
  5652. +
  5653. + out:
  5654. + TraceErr(err);
  5655. + return err;
  5656. +}
  5657. +
  5658. +static int do_open_dir(struct file *file, int flags)
  5659. +{
  5660. + int err;
  5661. + aufs_bindex_t bindex, btail;
  5662. + struct dentry *dentry, *hidden_dentry;
  5663. + struct file *hidden_file;
  5664. +
  5665. + dentry = file->f_dentry;
  5666. + LKTRTrace("%.*s, 0x%x\n", DLNPair(dentry), flags);
  5667. + DEBUG_ON(!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode));
  5668. +
  5669. + err = 0;
  5670. + set_fvdir_cache(file, NULL);
  5671. + file->f_version = dentry->d_inode->i_version;
  5672. + bindex = dbstart(dentry);
  5673. + set_fbstart(file, bindex);
  5674. + btail = dbtaildir(dentry);
  5675. + set_fbend(file, btail);
  5676. + for (; !err && bindex <= btail; bindex++) {
  5677. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  5678. + if (!hidden_dentry)
  5679. + continue;
  5680. +
  5681. + hidden_file = hidden_open(dentry, bindex, flags);
  5682. + //if (LktrCond) {fput(hidden_file);
  5683. + //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
  5684. + if (!IS_ERR(hidden_file)) {
  5685. + set_h_fptr(file, bindex, hidden_file);
  5686. + continue;
  5687. + }
  5688. + err = PTR_ERR(hidden_file);
  5689. + }
  5690. + if (!err)
  5691. + return 0; /* success */
  5692. +
  5693. + /* close all */
  5694. + for (bindex = fbstart(file); !err && bindex <= btail; bindex++)
  5695. + set_h_fptr(file, bindex, NULL);
  5696. + set_fbstart(file, -1);
  5697. + set_fbend(file, -1);
  5698. + return err;
  5699. +}
  5700. +
  5701. +static int aufs_open_dir(struct inode *inode, struct file *file)
  5702. +{
  5703. + return au_do_open(inode, file, do_open_dir);
  5704. +}
  5705. +
  5706. +static int aufs_release_dir(struct inode *inode, struct file *file)
  5707. +{
  5708. + struct aufs_vdir *vdir_cache;
  5709. + struct super_block *sb;
  5710. +
  5711. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
  5712. +
  5713. + sb = file->f_dentry->d_sb;
  5714. + si_read_lock(sb);
  5715. + fi_write_lock(file);
  5716. + vdir_cache = fvdir_cache(file);
  5717. + if (vdir_cache)
  5718. + free_vdir(vdir_cache);
  5719. + fi_write_unlock(file);
  5720. + au_fin_finfo(file);
  5721. + si_read_unlock(sb);
  5722. + return 0;
  5723. +}
  5724. +
  5725. +static int fsync_dir(struct dentry *dentry, int datasync)
  5726. +{
  5727. + int err;
  5728. + struct inode *inode;
  5729. + struct super_block *sb;
  5730. + aufs_bindex_t bend, bindex;
  5731. +
  5732. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
  5733. + DiMustAnyLock(dentry);
  5734. + sb = dentry->d_sb;
  5735. + SiMustAnyLock(sb);
  5736. + inode = dentry->d_inode;
  5737. + IMustLock(inode);
  5738. + IiMustAnyLock(inode);
  5739. +
  5740. + err = 0;
  5741. + bend = dbend(dentry);
  5742. + for (bindex = dbstart(dentry); !err && bindex <= bend; bindex++) {
  5743. + struct dentry *h_dentry;
  5744. + struct inode *h_inode;
  5745. + struct file_operations *fop;
  5746. +
  5747. + if (test_ro(sb, bindex, inode))
  5748. + continue;
  5749. + h_dentry = au_h_dptr_i(dentry, bindex);
  5750. + if (!h_dentry)
  5751. + continue;
  5752. + h_inode = h_dentry->d_inode;
  5753. + if (!h_inode)
  5754. + continue;
  5755. +
  5756. + /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
  5757. + //hdir_lock(h_inode, inode, bindex);
  5758. + i_lock(h_inode);
  5759. + fop = (void*)h_inode->i_fop;
  5760. + err = filemap_fdatawrite(h_inode->i_mapping);
  5761. + if (!err && fop && fop->fsync)
  5762. + err = fop->fsync(NULL, h_dentry, datasync);
  5763. + if (!err)
  5764. + err = filemap_fdatawrite(h_inode->i_mapping);
  5765. + //hdir_unlock(h_inode, inode, bindex);
  5766. + i_unlock(h_inode);
  5767. + }
  5768. +
  5769. + TraceErr(err);
  5770. + return err;
  5771. +}
  5772. +
  5773. +/*
  5774. + * @file may be NULL
  5775. + */
  5776. +static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
  5777. + int datasync)
  5778. +{
  5779. + int err;
  5780. + struct inode *inode;
  5781. + struct file *hidden_file;
  5782. + struct super_block *sb;
  5783. + aufs_bindex_t bend, bindex;
  5784. +
  5785. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
  5786. + inode = dentry->d_inode;
  5787. + IMustLock(inode);
  5788. +
  5789. + err = 0;
  5790. + sb = dentry->d_sb;
  5791. + si_read_lock(sb);
  5792. + if (file) {
  5793. + err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
  5794. + /*locked*/1);
  5795. + //err = -1;
  5796. + if (unlikely(err))
  5797. + goto out;
  5798. + } else
  5799. + di_read_lock_child(dentry, !AUFS_I_WLOCK);
  5800. +
  5801. + ii_write_lock_child(inode);
  5802. + if (file) {
  5803. + bend = fbend(file);
  5804. + for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
  5805. + hidden_file = au_h_fptr_i(file, bindex);
  5806. + if (!hidden_file || test_ro(sb, bindex, inode))
  5807. + continue;
  5808. +
  5809. + err = -EINVAL;
  5810. + if (hidden_file->f_op && hidden_file->f_op->fsync) {
  5811. + // todo: try do_fsync() in fs/sync.c
  5812. +#if 0
  5813. + DEBUG_ON(hidden_file->f_dentry->d_inode
  5814. + != au_h_iptr_i(inode, bindex));
  5815. + hdir_lock(hidden_file->f_dentry->d_inode, inode,
  5816. + bindex);
  5817. +#else
  5818. + i_lock(hidden_file->f_dentry->d_inode);
  5819. +#endif
  5820. + err = hidden_file->f_op->fsync
  5821. + (hidden_file, hidden_file->f_dentry,
  5822. + datasync);
  5823. + //err = -1;
  5824. +#if 0
  5825. + hdir_unlock(hidden_file->f_dentry->d_inode,
  5826. + inode, bindex);
  5827. +#else
  5828. + i_unlock(hidden_file->f_dentry->d_inode);
  5829. +#endif
  5830. + }
  5831. + }
  5832. + } else
  5833. + err = fsync_dir(dentry, datasync);
  5834. + au_cpup_attr_timesizes(inode);
  5835. + ii_write_unlock(inode);
  5836. + if (file)
  5837. + fi_write_unlock(file);
  5838. + else
  5839. + di_read_unlock(dentry, !AUFS_I_WLOCK);
  5840. +
  5841. + out:
  5842. + si_read_unlock(sb);
  5843. + TraceErr(err);
  5844. + return err;
  5845. +}
  5846. +
  5847. +/* ---------------------------------------------------------------------- */
  5848. +
  5849. +static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
  5850. +{
  5851. + int err;
  5852. + struct dentry *dentry;
  5853. + struct inode *inode;
  5854. + struct super_block *sb;
  5855. +
  5856. + dentry = file->f_dentry;
  5857. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  5858. + inode = dentry->d_inode;
  5859. + IMustLock(inode);
  5860. +
  5861. + au_nfsd_lockdep_off();
  5862. + sb = dentry->d_sb;
  5863. + si_read_lock(sb);
  5864. + err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
  5865. + /*locked*/1);
  5866. + if (unlikely(err))
  5867. + goto out;
  5868. +
  5869. + ii_write_lock_child(inode);
  5870. + err = au_init_vdir(file);
  5871. + if (unlikely(err)) {
  5872. + ii_write_unlock(inode);
  5873. + goto out_unlock;
  5874. + }
  5875. + //DbgVdir(fvdir_cache(file));// goto out_unlock;
  5876. +
  5877. + /* nfsd filldir calls lookup_one_len(). */
  5878. + ii_downgrade_lock(inode);
  5879. + err = au_fill_de(file, dirent, filldir);
  5880. + //DbgVdir(fvdir_cache(file));// goto out_unlock;
  5881. +
  5882. + inode->i_atime = au_h_iptr(inode)->i_atime;
  5883. + ii_read_unlock(inode);
  5884. +
  5885. + out_unlock:
  5886. + fi_write_unlock(file);
  5887. + out:
  5888. + si_read_unlock(sb);
  5889. + au_nfsd_lockdep_on();
  5890. +#if 0 // debug
  5891. + if (LktrCond)
  5892. + igrab(inode);
  5893. +#endif
  5894. + TraceErr(err);
  5895. + return err;
  5896. +}
  5897. +
  5898. +/* ---------------------------------------------------------------------- */
  5899. +
  5900. +struct test_empty_arg {
  5901. + struct aufs_nhash *whlist;
  5902. + int whonly;
  5903. + aufs_bindex_t bindex;
  5904. + int err, called;
  5905. +};
  5906. +
  5907. +static int test_empty_cb(void *__arg, const char *__name, int namelen,
  5908. + loff_t offset, filldir_ino_t ino, unsigned int d_type)
  5909. +{
  5910. + struct test_empty_arg *arg = __arg;
  5911. + char *name = (void*)__name;
  5912. +
  5913. + LKTRTrace("%.*s\n", namelen, name);
  5914. +
  5915. + arg->err = 0;
  5916. + arg->called++;
  5917. + //smp_mb();
  5918. + if (name[0] == '.'
  5919. + && (namelen == 1 || (name[1] == '.' && namelen == 2)))
  5920. + return 0; /* success */
  5921. +
  5922. + if (namelen <= AUFS_WH_PFX_LEN
  5923. + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
  5924. + if (arg->whonly && !test_known_wh(arg->whlist, name, namelen))
  5925. + arg->err = -ENOTEMPTY;
  5926. + goto out;
  5927. + }
  5928. +
  5929. + name += AUFS_WH_PFX_LEN;
  5930. + namelen -= AUFS_WH_PFX_LEN;
  5931. + if (!test_known_wh(arg->whlist, name, namelen))
  5932. + arg->err = append_wh(arg->whlist, name, namelen, arg->bindex);
  5933. +
  5934. + out:
  5935. + //smp_mb();
  5936. + TraceErr(arg->err);
  5937. + return arg->err;
  5938. +}
  5939. +
  5940. +static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
  5941. +{
  5942. + int err, dlgt;
  5943. + struct file *hidden_file;
  5944. +
  5945. + LKTRTrace("%.*s, {%p, %d, %d}\n",
  5946. + DLNPair(dentry), arg->whlist, arg->whonly, arg->bindex);
  5947. +
  5948. + hidden_file = hidden_open(dentry, arg->bindex,
  5949. + O_RDONLY | O_NONBLOCK | O_DIRECTORY
  5950. + | O_LARGEFILE);
  5951. + err = PTR_ERR(hidden_file);
  5952. + if (IS_ERR(hidden_file))
  5953. + goto out;
  5954. +
  5955. + dlgt = need_dlgt(dentry->d_sb);
  5956. + //hidden_file->f_pos = 0;
  5957. + do {
  5958. + arg->err = 0;
  5959. + arg->called = 0;
  5960. + //smp_mb();
  5961. + err = vfsub_readdir(hidden_file, test_empty_cb, arg, dlgt);
  5962. + if (err >= 0)
  5963. + err = arg->err;
  5964. + } while (!err && arg->called);
  5965. + fput(hidden_file);
  5966. + sbr_put(dentry->d_sb, arg->bindex);
  5967. +
  5968. + out:
  5969. + TraceErr(err);
  5970. + return err;
  5971. +}
  5972. +
  5973. +struct do_test_empty_args {
  5974. + int *errp;
  5975. + struct dentry *dentry;
  5976. + struct test_empty_arg *arg;
  5977. +};
  5978. +
  5979. +static void call_do_test_empty(void *args)
  5980. +{
  5981. + struct do_test_empty_args *a = args;
  5982. + *a->errp = do_test_empty(a->dentry, a->arg);
  5983. +}
  5984. +
  5985. +static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
  5986. +{
  5987. + int err;
  5988. + struct dentry *hidden_dentry;
  5989. + struct inode *hidden_inode;
  5990. +
  5991. + LKTRTrace("%.*s\n", DLNPair(dentry));
  5992. + hidden_dentry = au_h_dptr_i(dentry, arg->bindex);
  5993. + DEBUG_ON(!hidden_dentry);
  5994. + hidden_inode = hidden_dentry->d_inode;
  5995. + DEBUG_ON(!hidden_inode || !S_ISDIR(hidden_inode->i_mode));
  5996. +
  5997. + hi_lock_child(hidden_inode);
  5998. + err = au_test_perm(hidden_inode, MAY_EXEC | MAY_READ,
  5999. + need_dlgt(dentry->d_sb));
  6000. + i_unlock(hidden_inode);
  6001. + if (!err)
  6002. + err = do_test_empty(dentry, arg);
  6003. + else {
  6004. + struct do_test_empty_args args = {
  6005. + .errp = &err,
  6006. + .dentry = dentry,
  6007. + .arg = arg
  6008. + };
  6009. + au_wkq_wait(call_do_test_empty, &args, /*dlgt*/0);
  6010. + }
  6011. +
  6012. + TraceErr(err);
  6013. + return err;
  6014. +}
  6015. +
  6016. +int au_test_empty_lower(struct dentry *dentry)
  6017. +{
  6018. + int err;
  6019. + struct inode *inode;
  6020. + struct test_empty_arg arg;
  6021. + struct aufs_nhash *whlist;
  6022. + aufs_bindex_t bindex, bstart, btail;
  6023. +
  6024. + LKTRTrace("%.*s\n", DLNPair(dentry));
  6025. + inode = dentry->d_inode;
  6026. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  6027. +
  6028. + whlist = nhash_new(GFP_KERNEL);
  6029. + err = PTR_ERR(whlist);
  6030. + if (IS_ERR(whlist))
  6031. + goto out;
  6032. +
  6033. + bstart = dbstart(dentry);
  6034. + arg.whlist = whlist;
  6035. + arg.whonly = 0;
  6036. + arg.bindex = bstart;
  6037. + err = do_test_empty(dentry, &arg);
  6038. + if (unlikely(err))
  6039. + goto out_whlist;
  6040. +
  6041. + arg.whonly = 1;
  6042. + btail = dbtaildir(dentry);
  6043. + for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
  6044. + struct dentry *hidden_dentry;
  6045. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  6046. + if (hidden_dentry && hidden_dentry->d_inode) {
  6047. + DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
  6048. + arg.bindex = bindex;
  6049. + err = do_test_empty(dentry, &arg);
  6050. + }
  6051. + }
  6052. +
  6053. + out_whlist:
  6054. + nhash_del(whlist);
  6055. + out:
  6056. + TraceErr(err);
  6057. + return err;
  6058. +}
  6059. +
  6060. +int test_empty(struct dentry *dentry, struct aufs_nhash *whlist)
  6061. +{
  6062. + int err;
  6063. + struct inode *inode;
  6064. + struct test_empty_arg arg;
  6065. + aufs_bindex_t bindex, btail;
  6066. +
  6067. + LKTRTrace("%.*s\n", DLNPair(dentry));
  6068. + inode = dentry->d_inode;
  6069. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  6070. +
  6071. + err = 0;
  6072. + arg.whlist = whlist;
  6073. + arg.whonly = 1;
  6074. + btail = dbtaildir(dentry);
  6075. + for (bindex = dbstart(dentry); !err && bindex <= btail; bindex++) {
  6076. + struct dentry *hidden_dentry;
  6077. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  6078. + if (hidden_dentry && hidden_dentry->d_inode) {
  6079. + DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
  6080. + arg.bindex = bindex;
  6081. + err = sio_test_empty(dentry, &arg);
  6082. + }
  6083. + }
  6084. +
  6085. + TraceErr(err);
  6086. + return err;
  6087. +}
  6088. +
  6089. +/* ---------------------------------------------------------------------- */
  6090. +
  6091. +void au_add_nlink(struct inode *dir, struct inode *h_dir)
  6092. +{
  6093. + DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
  6094. + dir->i_nlink += h_dir->i_nlink - 2;
  6095. + if (unlikely(h_dir->i_nlink < 2))
  6096. + dir->i_nlink += 2;
  6097. +}
  6098. +
  6099. +void au_sub_nlink(struct inode *dir, struct inode *h_dir)
  6100. +{
  6101. + DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
  6102. + dir->i_nlink -= h_dir->i_nlink - 2;
  6103. + if (unlikely(h_dir->i_nlink < 2))
  6104. + dir->i_nlink -= 2;
  6105. +}
  6106. +
  6107. +/* ---------------------------------------------------------------------- */
  6108. +
  6109. +#if 0 // comment
  6110. +struct file_operations {
  6111. + struct module *owner;
  6112. + loff_t (*llseek) (struct file *, loff_t, int);
  6113. + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
  6114. + ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
  6115. + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
  6116. + ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
  6117. + int (*readdir) (struct file *, void *, filldir_t);
  6118. + unsigned int (*poll) (struct file *, struct poll_table_struct *);
  6119. + int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
  6120. + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
  6121. + long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
  6122. + int (*mmap) (struct file *, struct vm_area_struct *);
  6123. + int (*open) (struct inode *, struct file *);
  6124. + int (*flush) (struct file *);
  6125. + int (*release) (struct inode *, struct file *);
  6126. + int (*fsync) (struct file *, struct dentry *, int datasync);
  6127. + int (*aio_fsync) (struct kiocb *, int datasync);
  6128. + int (*fasync) (int, struct file *, int);
  6129. + int (*lock) (struct file *, int, struct file_lock *);
  6130. + ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
  6131. + ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
  6132. + ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
  6133. + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
  6134. + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
  6135. + int (*check_flags)(int);
  6136. + int (*dir_notify)(struct file *file, unsigned long arg);
  6137. + int (*flock) (struct file *, int, struct file_lock *);
  6138. +};
  6139. +#endif
  6140. +
  6141. +struct file_operations aufs_dir_fop = {
  6142. + .read = generic_read_dir,
  6143. + .readdir = aufs_readdir,
  6144. + .open = aufs_open_dir,
  6145. + .release = aufs_release_dir,
  6146. + .flush = aufs_flush,
  6147. + .fsync = aufs_fsync_dir,
  6148. +};
  6149. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/dir.h linux-2.6.22.1/fs/aufs/dir.h
  6150. --- linux-2.6.22.1.oorig/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
  6151. +++ linux-2.6.22.1/fs/aufs/dir.h 2007-07-24 14:17:46.000000000 +0200
  6152. @@ -0,0 +1,125 @@
  6153. +/*
  6154. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  6155. + *
  6156. + * This program, aufs is free software; you can redistribute it and/or modify
  6157. + * it under the terms of the GNU General Public License as published by
  6158. + * the Free Software Foundation; either version 2 of the License, or
  6159. + * (at your option) any later version.
  6160. + *
  6161. + * This program is distributed in the hope that it will be useful,
  6162. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  6163. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  6164. + * GNU General Public License for more details.
  6165. + *
  6166. + * You should have received a copy of the GNU General Public License
  6167. + * along with this program; if not, write to the Free Software
  6168. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  6169. + */
  6170. +
  6171. +/* $Id: dir.h,v 1.18 2007/05/14 03:41:52 sfjro Exp $ */
  6172. +
  6173. +#ifndef __AUFS_DIR_H__
  6174. +#define __AUFS_DIR_H__
  6175. +
  6176. +#ifdef __KERNEL__
  6177. +
  6178. +#include <linux/fs.h>
  6179. +#include <linux/version.h>
  6180. +#include <linux/aufs_type.h>
  6181. +
  6182. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
  6183. +#define filldir_ino_t u64
  6184. +#else
  6185. +#define filldir_ino_t ino_t
  6186. +#endif
  6187. +
  6188. +/* ---------------------------------------------------------------------- */
  6189. +
  6190. +/* need to be faster and smaller */
  6191. +
  6192. +#define AUFS_DEBLK_SIZE 512 // todo: changable
  6193. +#define AUFS_NHASH_SIZE 32 // todo: changable
  6194. +#if AUFS_DEBLK_SIZE < NAME_MAX || PAGE_SIZE < AUFS_DEBLK_SIZE
  6195. +#error invalid size AUFS_DEBLK_SIZE
  6196. +#endif
  6197. +
  6198. +typedef char aufs_deblk_t[AUFS_DEBLK_SIZE];
  6199. +
  6200. +struct aufs_nhash {
  6201. + struct hlist_head heads[AUFS_NHASH_SIZE];
  6202. +};
  6203. +
  6204. +struct aufs_destr {
  6205. + unsigned char len;
  6206. + char name[0];
  6207. +} __attribute__ ((packed));
  6208. +
  6209. +struct aufs_dehstr {
  6210. + struct hlist_node hash;
  6211. + struct aufs_destr *str;
  6212. +};
  6213. +
  6214. +struct aufs_de {
  6215. + ino_t de_ino;
  6216. + unsigned char de_type;
  6217. + //caution: packed
  6218. + struct aufs_destr de_str;
  6219. +} __attribute__ ((packed));
  6220. +
  6221. +struct aufs_wh {
  6222. + struct hlist_node wh_hash;
  6223. + aufs_bindex_t wh_bindex;
  6224. + struct aufs_destr wh_str;
  6225. +} __attribute__ ((packed));
  6226. +
  6227. +union aufs_deblk_p {
  6228. + unsigned char *p;
  6229. + aufs_deblk_t *deblk;
  6230. + struct aufs_de *de;
  6231. +};
  6232. +
  6233. +struct aufs_vdir {
  6234. + aufs_deblk_t **vd_deblk;
  6235. + int vd_nblk;
  6236. + struct {
  6237. + int i;
  6238. + union aufs_deblk_p p;
  6239. + } vd_last;
  6240. +
  6241. + unsigned long vd_version;
  6242. + unsigned long vd_jiffy;
  6243. +};
  6244. +
  6245. +/* ---------------------------------------------------------------------- */
  6246. +
  6247. +/* dir.c */
  6248. +extern struct file_operations aufs_dir_fop;
  6249. +int au_test_empty_lower(struct dentry *dentry);
  6250. +int test_empty(struct dentry *dentry, struct aufs_nhash *whlist);
  6251. +void au_add_nlink(struct inode *dir, struct inode *h_dir);
  6252. +void au_sub_nlink(struct inode *dir, struct inode *h_dir);
  6253. +
  6254. +/* vdir.c */
  6255. +struct aufs_nhash *nhash_new(gfp_t gfp);
  6256. +void nhash_del(struct aufs_nhash *nhash);
  6257. +void nhash_init(struct aufs_nhash *nhash);
  6258. +void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src);
  6259. +void nhash_fin(struct aufs_nhash *nhash);
  6260. +int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit);
  6261. +int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen);
  6262. +int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
  6263. + aufs_bindex_t bindex);
  6264. +void free_vdir(struct aufs_vdir *vdir);
  6265. +int au_init_vdir(struct file *file);
  6266. +int au_fill_de(struct file *file, void *dirent, filldir_t filldir);
  6267. +
  6268. +/* ---------------------------------------------------------------------- */
  6269. +
  6270. +static inline
  6271. +unsigned int au_name_hash(const unsigned char *name, unsigned int len)
  6272. +{
  6273. + return (full_name_hash(name, len) % AUFS_NHASH_SIZE);
  6274. +}
  6275. +
  6276. +#endif /* __KERNEL__ */
  6277. +#endif /* __AUFS_DIR_H__ */
  6278. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/export.c linux-2.6.22.1/fs/aufs/export.c
  6279. --- linux-2.6.22.1.oorig/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
  6280. +++ linux-2.6.22.1/fs/aufs/export.c 2007-07-24 14:17:46.000000000 +0200
  6281. @@ -0,0 +1,585 @@
  6282. +/*
  6283. + * Copyright (C) 2007 Junjiro Okajima
  6284. + *
  6285. + * This program, aufs is free software; you can redistribute it and/or modify
  6286. + * it under the terms of the GNU General Public License as published by
  6287. + * the Free Software Foundation; either version 2 of the License, or
  6288. + * (at your option) any later version.
  6289. + *
  6290. + * This program is distributed in the hope that it will be useful,
  6291. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  6292. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  6293. + * GNU General Public License for more details.
  6294. + *
  6295. + * You should have received a copy of the GNU General Public License
  6296. + * along with this program; if not, write to the Free Software
  6297. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  6298. + */
  6299. +
  6300. +/* $Id: export.c,v 1.7 2007/05/14 03:38:24 sfjro Exp $ */
  6301. +
  6302. +#include "aufs.h"
  6303. +
  6304. +extern struct export_operations export_op_default;
  6305. +#define CALL(ops, func) (((ops)->func) ? ((ops)->func) : export_op_default.func)
  6306. +#define is_anon(d) ((d)->d_flags & DCACHE_DISCONNECTED)
  6307. +
  6308. +union conv {
  6309. +#if BITS_PER_LONG == 32
  6310. + __u32 a[1];
  6311. +#else
  6312. + __u32 a[2];
  6313. +#endif
  6314. + ino_t ino;
  6315. +};
  6316. +
  6317. +static ino_t decode_ino(__u32 *a)
  6318. +{
  6319. + union conv u;
  6320. + u.a[0] = a[0];
  6321. +#if BITS_PER_LONG == 64
  6322. + u.a[1] = a[1];
  6323. +#endif
  6324. + return u.ino;
  6325. +}
  6326. +
  6327. +static void encode_ino(__u32 *a, ino_t ino)
  6328. +{
  6329. + union conv u;
  6330. + u.ino = ino;
  6331. + a[0] = u.a[0];
  6332. +#if BITS_PER_LONG == 64
  6333. + a[1] = u.a[1];
  6334. +#endif
  6335. +}
  6336. +
  6337. +static void decode_br_id_sigen(__u32 a, aufs_bindex_t *br_id,
  6338. + aufs_bindex_t *sigen)
  6339. +{
  6340. + BUILD_BUG_ON((sizeof(*br_id) + sizeof(*sigen)) > sizeof(a));
  6341. + *br_id = a >> 16;
  6342. + DEBUG_ON(*br_id < 0);
  6343. + *sigen = a;
  6344. + DEBUG_ON(*sigen < 0);
  6345. +}
  6346. +
  6347. +static __u32 encode_br_id_sigen(aufs_bindex_t br_id, aufs_bindex_t sigen)
  6348. +{
  6349. + DEBUG_ON(br_id < 0 || sigen < 0);
  6350. + return (br_id << 16) | sigen;
  6351. +}
  6352. +
  6353. +/* NFS file handle */
  6354. +enum {
  6355. + /* support 64bit inode number */
  6356. + /* but untested */
  6357. + Fh_br_id_sigen,
  6358. + Fh_ino1,
  6359. +#if BITS_PER_LONG == 64
  6360. + Fh_ino2,
  6361. +#endif
  6362. + Fh_dir_ino1,
  6363. +#if BITS_PER_LONG == 64
  6364. + Fh_dir_ino2,
  6365. +#endif
  6366. + Fh_h_ino1,
  6367. +#if BITS_PER_LONG == 64
  6368. + Fh_h_ino2,
  6369. +#endif
  6370. + Fh_h_igen,
  6371. + Fh_h_type,
  6372. + Fh_tail,
  6373. +
  6374. + Fh_ino = Fh_ino1,
  6375. + Fh_dir_ino = Fh_dir_ino1,
  6376. + Fh_h_ino = Fh_h_ino1,
  6377. +};
  6378. +
  6379. +/* ---------------------------------------------------------------------- */
  6380. +
  6381. +static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
  6382. + ino_t dir_ino)
  6383. +{
  6384. + struct dentry *dentry;
  6385. + struct inode *inode;
  6386. +
  6387. + LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
  6388. +
  6389. + dentry = NULL;
  6390. + inode = ilookup(sb, ino);
  6391. + if (unlikely(!inode))
  6392. + goto out;
  6393. +
  6394. + dentry = ERR_PTR(-ESTALE);
  6395. + if (unlikely(is_bad_inode(inode)))
  6396. + goto out_iput;
  6397. +
  6398. + dentry = NULL;
  6399. + if (!S_ISDIR(inode->i_mode)) {
  6400. + struct dentry *d;
  6401. + spin_lock(&dcache_lock);
  6402. + list_for_each_entry(d, &inode->i_dentry, d_alias)
  6403. + if (!is_anon(d)
  6404. + && d->d_parent->d_inode->i_ino == dir_ino) {
  6405. + dentry = dget_locked(d);
  6406. + break;
  6407. + }
  6408. + spin_unlock(&dcache_lock);
  6409. + } else {
  6410. + dentry = d_find_alias(inode);
  6411. + if (dentry
  6412. + && !is_anon(dentry)
  6413. + && dentry->d_parent->d_inode->i_ino == dir_ino)
  6414. + goto out_iput; /* success */
  6415. +
  6416. + dput(dentry);
  6417. + dentry = NULL;
  6418. + }
  6419. +
  6420. + out_iput:
  6421. + iput(inode);
  6422. + out:
  6423. + TraceErrPtr(dentry);
  6424. + return dentry;
  6425. +}
  6426. +
  6427. +/* ---------------------------------------------------------------------- */
  6428. +
  6429. +struct find_name_by_ino {
  6430. + int called, found;
  6431. + ino_t ino;
  6432. + char *name;
  6433. + int namelen;
  6434. +};
  6435. +
  6436. +static int
  6437. +find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
  6438. + filldir_ino_t ino, unsigned int d_type)
  6439. +{
  6440. + struct find_name_by_ino *a = arg;
  6441. +
  6442. + a->called++;
  6443. + if (a->ino != ino)
  6444. + return 0;
  6445. +
  6446. + memcpy(a->name, name, namelen);
  6447. + a->namelen = namelen;
  6448. + a->found = 1;
  6449. + return 1;
  6450. +}
  6451. +
  6452. +static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
  6453. + ino_t dir_ino)
  6454. +{
  6455. + struct dentry *dentry, *parent;
  6456. + struct inode *dir;
  6457. + struct find_name_by_ino arg;
  6458. + struct file *file;
  6459. + int err;
  6460. +
  6461. + LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
  6462. +
  6463. + dentry = NULL;
  6464. + dir = ilookup(sb, dir_ino);
  6465. + if (unlikely(!dir))
  6466. + goto out;
  6467. +
  6468. + dentry = ERR_PTR(-ESTALE);
  6469. + if (unlikely(is_bad_inode(dir)))
  6470. + goto out_iput;
  6471. +
  6472. + dentry = NULL;
  6473. + parent = d_find_alias(dir);
  6474. + if (parent) {
  6475. + if (unlikely(is_anon(parent))) {
  6476. + dput(parent);
  6477. + goto out_iput;
  6478. + }
  6479. + } else
  6480. + goto out_iput;
  6481. +
  6482. + file = dentry_open(parent, NULL, au_dir_roflags);
  6483. + dentry = (void*)file;
  6484. + if (IS_ERR(file))
  6485. + goto out_iput;
  6486. +
  6487. + dentry = ERR_PTR(-ENOMEM);
  6488. + arg.name = __getname();
  6489. + if (unlikely(!arg.name))
  6490. + goto out_fput;
  6491. + arg.ino = ino;
  6492. + arg.found = 0;
  6493. +
  6494. + do {
  6495. + arg.called = 0;
  6496. + //smp_mb();
  6497. + err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
  6498. + } while (!err && !arg.found && arg.called);
  6499. + dentry = ERR_PTR(err);
  6500. + if (arg.found) {
  6501. + /* do not call lkup_one(), nor dlgt */
  6502. + i_lock(dir);
  6503. + dentry = lookup_one_len(arg.name, parent, arg.namelen);
  6504. + i_unlock(dir);
  6505. + TraceErrPtr(dentry);
  6506. + }
  6507. +
  6508. + //out_putname:
  6509. + __putname(arg.name);
  6510. + out_fput:
  6511. + fput(file);
  6512. + out_iput:
  6513. + iput(dir);
  6514. + out:
  6515. + TraceErrPtr(dentry);
  6516. + return dentry;
  6517. +}
  6518. +
  6519. +/* ---------------------------------------------------------------------- */
  6520. +
  6521. +struct append_name {
  6522. + int found, called, len;
  6523. + char *h_path;
  6524. + ino_t h_ino;
  6525. +};
  6526. +
  6527. +static int append_name(void *arg, const char *name, int len, loff_t pos,
  6528. + filldir_ino_t ino, unsigned int d_type)
  6529. +{
  6530. + struct append_name *a = arg;
  6531. + char *p;
  6532. +
  6533. + a->called++;
  6534. + if (ino != a->h_ino)
  6535. + return 0;
  6536. +
  6537. + DEBUG_ON(len == 1 && *name == '.');
  6538. + DEBUG_ON(len == 2 && name[0] == '.' && name[1] == '.');
  6539. + a->len = strlen(a->h_path);
  6540. + memmove(a->h_path - a->len - 1, a->h_path, a->len);
  6541. + a->h_path -= a->len + 1;
  6542. + p = a->h_path + a->len;
  6543. + *p++ = '/';
  6544. + memcpy(p, name, a->len);
  6545. + a->len += 1 + len;
  6546. + a->found++;
  6547. + return 1;
  6548. +}
  6549. +
  6550. +static int h_acceptable(void *expv, struct dentry *dentry)
  6551. +{
  6552. + return 1;
  6553. +}
  6554. +
  6555. +static struct dentry*
  6556. +decode_by_path(struct super_block *sb, aufs_bindex_t bindex, __u32 *fh,
  6557. + int fh_len, void *context)
  6558. +{
  6559. + struct dentry *dentry, *h_parent, *root, *h_root;
  6560. + struct super_block *h_sb;
  6561. + char *path, *p;
  6562. + struct vfsmount *h_mnt;
  6563. + struct append_name arg;
  6564. + int len, err;
  6565. + struct file *h_file;
  6566. + struct nameidata nd;
  6567. + struct aufs_branch *br;
  6568. +
  6569. + LKTRTrace("b%d\n", bindex);
  6570. + SiMustAnyLock(sb);
  6571. +
  6572. + br = stobr(sb, bindex);
  6573. + //br_get(br);
  6574. + h_mnt = br->br_mnt;
  6575. + h_sb = h_mnt->mnt_sb;
  6576. + LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb));
  6577. + h_parent = CALL(h_sb->s_export_op, decode_fh)
  6578. + (h_sb, fh + Fh_tail, fh_len - Fh_tail, fh[Fh_h_type],
  6579. + h_acceptable, /*context*/NULL);
  6580. + dentry = h_parent;
  6581. + if (unlikely(!h_parent || IS_ERR(h_parent))) {
  6582. + Warn1("%s decode_fh failed\n", au_sbtype(h_sb));
  6583. + goto out;
  6584. + }
  6585. + dentry = NULL;
  6586. + if (unlikely(is_anon(h_parent))) {
  6587. + Warn1("%s decode_fh returned a disconnected dentry\n",
  6588. + au_sbtype(h_sb));
  6589. + dput(h_parent);
  6590. + goto out;
  6591. + }
  6592. +
  6593. + dentry = ERR_PTR(-ENOMEM);
  6594. + path = __getname();
  6595. + if (unlikely(!path)) {
  6596. + dput(h_parent);
  6597. + goto out;
  6598. + }
  6599. +
  6600. + root = sb->s_root;
  6601. + di_read_lock_parent(root, !AUFS_I_RLOCK);
  6602. + h_root = au_h_dptr_i(root, bindex);
  6603. + di_read_unlock(root, !AUFS_I_RLOCK);
  6604. + arg.h_path = d_path(h_root, h_mnt, path, PATH_MAX);
  6605. + dentry = (void*)arg.h_path;
  6606. + if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
  6607. + goto out_putname;
  6608. + len = strlen(arg.h_path);
  6609. + arg.h_path = d_path(h_parent, h_mnt, path, PATH_MAX);
  6610. + dentry = (void*)arg.h_path;
  6611. + if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
  6612. + goto out_putname;
  6613. + LKTRTrace("%s\n", arg.h_path);
  6614. + if (len != 1)
  6615. + arg.h_path += len;
  6616. + LKTRTrace("%s\n", arg.h_path);
  6617. +
  6618. + /* cf. fs/exportfs/expfs.c */
  6619. + h_file = dentry_open(h_parent, NULL, au_dir_roflags);
  6620. + dentry = (void*)h_file;
  6621. + if (IS_ERR(h_file))
  6622. + goto out_putname;
  6623. +
  6624. + arg.found = 0;
  6625. + arg.h_ino = decode_ino(fh + Fh_h_ino);
  6626. + do {
  6627. + arg.called = 0;
  6628. + err = vfsub_readdir(h_file, append_name, &arg, /*dlgt*/0);
  6629. + } while (!err && !arg.found && arg.called);
  6630. + LKTRTrace("%s, %d\n", arg.h_path, arg.len);
  6631. +
  6632. + p = d_path(root, stosi(sb)->si_mnt, path, PATH_MAX - arg.len - 2);
  6633. + dentry = (void*)p;
  6634. + if (unlikely(!p || IS_ERR(p)))
  6635. + goto out_fput;
  6636. + p[strlen(p)] = '/';
  6637. + LKTRTrace("%s\n", p);
  6638. +
  6639. + err = path_lookup(p, LOOKUP_FOLLOW, &nd);
  6640. + dentry = ERR_PTR(err);
  6641. + if (!err) {
  6642. + dentry = dget(nd.dentry);
  6643. + if (unlikely(is_anon(dentry))) {
  6644. + dput(dentry);
  6645. + dentry = ERR_PTR(-ESTALE);
  6646. + }
  6647. + path_release(&nd);
  6648. + }
  6649. +
  6650. + out_fput:
  6651. + fput(h_file);
  6652. + out_putname:
  6653. + __putname(path);
  6654. + out:
  6655. + //br_put(br);
  6656. + TraceErrPtr(dentry);
  6657. + return dentry;
  6658. +}
  6659. +
  6660. +/* ---------------------------------------------------------------------- */
  6661. +
  6662. +static struct dentry*
  6663. +aufs_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
  6664. + int (*acceptable)(void *context, struct dentry *de),
  6665. + void *context)
  6666. +{
  6667. + struct dentry *dentry;
  6668. + ino_t ino, dir_ino;
  6669. + aufs_bindex_t bindex, br_id, sigen_v;
  6670. + struct inode *inode, *h_inode;
  6671. +
  6672. + //au_debug_on();
  6673. + LKTRTrace("%d, fh{i%u, br_id_sigen 0x%x, hi%u}\n",
  6674. + fh_type, fh[Fh_ino], fh[Fh_br_id_sigen], fh[Fh_h_ino]);
  6675. + DEBUG_ON(fh_len < Fh_tail);
  6676. +
  6677. + si_read_lock(sb);
  6678. + lockdep_off();
  6679. +
  6680. + /* branch id may be wrapped around */
  6681. + dentry = ERR_PTR(-ESTALE);
  6682. + decode_br_id_sigen(fh[Fh_br_id_sigen], &br_id, &sigen_v);
  6683. + bindex = find_brindex(sb, br_id);
  6684. + if (unlikely(bindex < 0 || au_sigen(sb) < sigen_v))
  6685. + goto out;
  6686. +
  6687. + /* is this inode still cached? */
  6688. + ino = decode_ino(fh + Fh_ino);
  6689. + dir_ino = decode_ino(fh + Fh_dir_ino);
  6690. + dentry = decode_by_ino(sb, ino, dir_ino);
  6691. + if (IS_ERR(dentry))
  6692. + goto out;
  6693. + if (dentry)
  6694. + goto accept;
  6695. +
  6696. + /* is the parent dir cached? */
  6697. + dentry = decode_by_dir_ino(sb, ino, dir_ino);
  6698. + if (IS_ERR(dentry))
  6699. + goto out;
  6700. + if (dentry)
  6701. + goto accept;
  6702. +
  6703. + /* lookup path */
  6704. + dentry = decode_by_path(sb, bindex, fh, fh_len, context);
  6705. + if (IS_ERR(dentry))
  6706. + goto out;
  6707. + if (unlikely(!dentry))
  6708. + goto out_stale;
  6709. + if (unlikely(dentry->d_inode->i_ino != ino))
  6710. + goto out_dput;
  6711. +
  6712. + accept:
  6713. + inode = dentry->d_inode;
  6714. + h_inode = NULL;
  6715. + ii_read_lock_child(inode);
  6716. + if (ibstart(inode) <= bindex && bindex <= ibend(inode))
  6717. + h_inode = au_h_iptr_i(inode, bindex);
  6718. + ii_read_unlock(inode);
  6719. + if (h_inode
  6720. + && h_inode->i_generation == fh[Fh_h_igen]
  6721. + && acceptable(context, dentry))
  6722. + goto out; /* success */
  6723. + out_dput:
  6724. + dput(dentry);
  6725. + out_stale:
  6726. + dentry = ERR_PTR(-ESTALE);
  6727. + out:
  6728. + lockdep_on();
  6729. + si_read_unlock(sb);
  6730. + TraceErrPtr(dentry);
  6731. + //au_debug_off();
  6732. + return dentry;
  6733. +}
  6734. +
  6735. +/* ---------------------------------------------------------------------- */
  6736. +
  6737. +static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
  6738. + int connectable)
  6739. +{
  6740. + int err;
  6741. + struct super_block *sb, *h_sb;
  6742. + struct inode *inode, *h_inode, *dir;
  6743. + aufs_bindex_t bindex;
  6744. + union conv u;
  6745. + struct dentry *parent, *h_parent;
  6746. +
  6747. + //au_debug_on();
  6748. + BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
  6749. + LKTRTrace("%.*s, max %d, conn %d\n",
  6750. + DLNPair(dentry), *max_len, connectable);
  6751. + DEBUG_ON(is_anon(dentry));
  6752. + inode = dentry->d_inode;
  6753. + DEBUG_ON(!inode);
  6754. + parent = dentry->d_parent;
  6755. + DEBUG_ON(is_anon(parent));
  6756. +
  6757. + err = -ENOSPC;
  6758. + if (unlikely(*max_len <= Fh_tail)) {
  6759. + Warn1("NFSv2 client (max_len %d)?\n", *max_len);
  6760. + goto out;
  6761. + }
  6762. +
  6763. + sb = dentry->d_sb;
  6764. + si_read_lock(sb);
  6765. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  6766. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  6767. +#ifdef CONFIG_AUFS_DEBUG
  6768. + if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
  6769. + Warn1("NFS-exporting requires xino\n");
  6770. +#if 0
  6771. + if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
  6772. + Warn1("udba=inotify is not recommended when exporting\n");
  6773. +#endif
  6774. +#endif
  6775. +
  6776. + err = -EPERM;
  6777. + bindex = ibstart(inode);
  6778. + h_sb = sbr_sb(sb, bindex);
  6779. + if (unlikely(!h_sb->s_export_op)) {
  6780. + Err1("%s branch is not exportable\n", au_sbtype(h_sb));
  6781. + goto out_unlock;
  6782. + }
  6783. +
  6784. +#if 0 //def CONFIG_AUFS_ROBR
  6785. + if (unlikely(SB_AUFS(h_sb))) {
  6786. + Err1("aufs branch is not supported\n");
  6787. + goto out_unlock;
  6788. + }
  6789. +#endif
  6790. +
  6791. + /* doesn't support pseudo-link */
  6792. + if (unlikely(bindex < dbstart(dentry)
  6793. + || dbend(dentry) < bindex
  6794. + || !au_h_dptr_i(dentry, bindex))) {
  6795. + Err("%.*s/%.*s, b%d, pseudo-link?\n",
  6796. + DLNPair(dentry->d_parent), DLNPair(dentry), bindex);
  6797. + goto out_unlock;
  6798. + }
  6799. +
  6800. + fh[Fh_br_id_sigen] = encode_br_id_sigen(sbr_id(sb, bindex),
  6801. + au_sigen(sb));
  6802. + encode_ino(fh + Fh_ino, inode->i_ino);
  6803. + dir = parent->d_inode;
  6804. + encode_ino(fh + Fh_dir_ino, dir->i_ino);
  6805. + h_inode = au_h_iptr(inode);
  6806. + encode_ino(fh + Fh_h_ino, h_inode->i_ino);
  6807. + fh[Fh_h_igen] = h_inode->i_generation;
  6808. +
  6809. + /* it should be set at exporting time */
  6810. + if (unlikely(!h_sb->s_export_op->find_exported_dentry)) {
  6811. + Warn("set default find_exported_dentry for %s\n",
  6812. + au_sbtype(h_sb));
  6813. + h_sb->s_export_op->find_exported_dentry = find_exported_dentry;
  6814. + }
  6815. +
  6816. + *max_len -= Fh_tail;
  6817. + //LKTRTrace("Fh_tail %d, max_len %d\n", Fh_tail, *max_len);
  6818. + h_parent = au_h_dptr_i(parent, bindex);
  6819. + DEBUG_ON(is_anon(h_parent));
  6820. + err = fh[Fh_h_type] = CALL(h_sb->s_export_op, encode_fh)
  6821. + (h_parent, fh + Fh_tail, max_len, connectable);
  6822. + *max_len += Fh_tail;
  6823. + if (err != 255)
  6824. + err = 2; //??
  6825. + else
  6826. + Warn1("%s encode_fh failed\n", au_sbtype(h_sb));
  6827. +
  6828. + out_unlock:
  6829. + di_read_unlock(parent, AUFS_I_RLOCK);
  6830. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  6831. + out:
  6832. + TraceErr(err);
  6833. + //au_debug_off();
  6834. + if (unlikely(err < 0))
  6835. + err = 255;
  6836. + return err;
  6837. +}
  6838. +
  6839. +/* ---------------------------------------------------------------------- */
  6840. +
  6841. +#if 0
  6842. +struct export_operations {
  6843. + struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
  6844. + int (*acceptable)(void *context, struct dentry *de),
  6845. + void *context);
  6846. + int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
  6847. + int connectable);
  6848. +
  6849. + /* the following are only called from the filesystem itself */
  6850. + int (*get_name)(struct dentry *parent, char *name,
  6851. + struct dentry *child);
  6852. + struct dentry * (*get_parent)(struct dentry *child);
  6853. + struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
  6854. +
  6855. + /* This is set by the exporting module to a standard helper */
  6856. + struct dentry * (*find_exported_dentry)(
  6857. + struct super_block *sb, void *obj, void *parent,
  6858. + int (*acceptable)(void *context, struct dentry *de),
  6859. + void *context);
  6860. +};
  6861. +#endif
  6862. +
  6863. +struct export_operations aufs_export_op = {
  6864. + .decode_fh = aufs_decode_fh,
  6865. + .encode_fh = aufs_encode_fh
  6866. +};
  6867. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/f_op.c linux-2.6.22.1/fs/aufs/f_op.c
  6868. --- linux-2.6.22.1.oorig/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
  6869. +++ linux-2.6.22.1/fs/aufs/f_op.c 2007-07-24 14:17:46.000000000 +0200
  6870. @@ -0,0 +1,684 @@
  6871. +/*
  6872. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  6873. + *
  6874. + * This program, aufs is free software; you can redistribute it and/or modify
  6875. + * it under the terms of the GNU General Public License as published by
  6876. + * the Free Software Foundation; either version 2 of the License, or
  6877. + * (at your option) any later version.
  6878. + *
  6879. + * This program is distributed in the hope that it will be useful,
  6880. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  6881. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  6882. + * GNU General Public License for more details.
  6883. + *
  6884. + * You should have received a copy of the GNU General Public License
  6885. + * along with this program; if not, write to the Free Software
  6886. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  6887. + */
  6888. +
  6889. +/* $Id: f_op.c,v 1.27 2007/05/14 03:38:24 sfjro Exp $ */
  6890. +
  6891. +#include <linux/fsnotify.h>
  6892. +#include <linux/pagemap.h>
  6893. +#include <linux/poll.h>
  6894. +#include <linux/security.h>
  6895. +#include <linux/version.h>
  6896. +#include "aufs.h"
  6897. +
  6898. +/* common function to regular file and dir */
  6899. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  6900. +#define FlushArgs hidden_file, id
  6901. +int aufs_flush(struct file *file, fl_owner_t id)
  6902. +#else
  6903. +#define FlushArgs hidden_file
  6904. +int aufs_flush(struct file *file)
  6905. +#endif
  6906. +{
  6907. + int err;
  6908. + struct dentry *dentry;
  6909. + aufs_bindex_t bindex, bend;
  6910. +
  6911. + dentry = file->f_dentry;
  6912. + LKTRTrace("%.*s\n", DLNPair(dentry));
  6913. +
  6914. + // aufs_read_lock_file()
  6915. + si_read_lock(dentry->d_sb);
  6916. + fi_read_lock(file);
  6917. + di_read_lock_child(dentry, !AUFS_I_RLOCK);
  6918. +
  6919. + err = 0;
  6920. + bend = fbend(file);
  6921. + for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
  6922. + struct file *hidden_file;
  6923. + hidden_file = au_h_fptr_i(file, bindex);
  6924. + if (hidden_file && hidden_file->f_op
  6925. + && hidden_file->f_op->flush)
  6926. + err = hidden_file->f_op->flush(FlushArgs);
  6927. + }
  6928. +
  6929. + di_read_unlock(dentry, !AUFS_I_RLOCK);
  6930. + fi_read_unlock(file);
  6931. + si_read_unlock(dentry->d_sb);
  6932. + TraceErr(err);
  6933. + return err;
  6934. +}
  6935. +#undef FlushArgs
  6936. +
  6937. +/* ---------------------------------------------------------------------- */
  6938. +
  6939. +static int do_open_nondir(struct file *file, int flags)
  6940. +{
  6941. + int err;
  6942. + aufs_bindex_t bindex;
  6943. + struct super_block *sb;
  6944. + struct file *hidden_file;
  6945. + struct dentry *dentry;
  6946. + struct inode *inode;
  6947. + struct aufs_finfo *finfo;
  6948. +
  6949. + dentry = file->f_dentry;
  6950. + LKTRTrace("%.*s, flags 0%o\n", DLNPair(dentry), flags);
  6951. + FiMustWriteLock(file);
  6952. + inode = dentry->d_inode;
  6953. + DEBUG_ON(!inode || S_ISDIR(inode->i_mode));
  6954. +
  6955. + err = 0;
  6956. + finfo = ftofi(file);
  6957. + finfo->fi_h_vm_ops = NULL;
  6958. + sb = dentry->d_sb;
  6959. + bindex = dbstart(dentry);
  6960. + DEBUG_ON(!au_h_dptr(dentry)->d_inode);
  6961. + /* O_TRUNC is processed already */
  6962. + BUG_ON(test_ro(sb, bindex, inode) && (flags & O_TRUNC));
  6963. +
  6964. + hidden_file = hidden_open(dentry, bindex, flags);
  6965. + //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bindex));
  6966. + //hidden_file = ERR_PTR(-1);}
  6967. + if (!IS_ERR(hidden_file)) {
  6968. + set_fbstart(file, bindex);
  6969. + set_fbend(file, bindex);
  6970. + set_h_fptr(file, bindex, hidden_file);
  6971. + return 0; /* success */
  6972. + }
  6973. + err = PTR_ERR(hidden_file);
  6974. + TraceErr(err);
  6975. + return err;
  6976. +}
  6977. +
  6978. +static int aufs_open_nondir(struct inode *inode, struct file *file)
  6979. +{
  6980. + return au_do_open(inode, file, do_open_nondir);
  6981. +}
  6982. +
  6983. +static int aufs_release_nondir(struct inode *inode, struct file *file)
  6984. +{
  6985. + struct super_block *sb = file->f_dentry->d_sb;
  6986. +
  6987. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
  6988. +
  6989. + si_read_lock(sb);
  6990. + au_fin_finfo(file);
  6991. + si_read_unlock(sb);
  6992. + return 0;
  6993. +}
  6994. +
  6995. +/* ---------------------------------------------------------------------- */
  6996. +
  6997. +static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
  6998. + loff_t *ppos)
  6999. +{
  7000. + ssize_t err;
  7001. + struct dentry *dentry;
  7002. + struct file *hidden_file;
  7003. + struct super_block *sb;
  7004. + struct inode *h_inode;
  7005. + int dlgt;
  7006. +
  7007. + dentry = file->f_dentry;
  7008. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  7009. + DLNPair(dentry), (unsigned long)count, *ppos);
  7010. +
  7011. + sb = dentry->d_sb;
  7012. + si_read_lock(sb);
  7013. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7014. + /*locked*/0);
  7015. + //if (LktrCond) {fi_read_unlock(file); err = -1;}
  7016. + if (unlikely(err))
  7017. + goto out;
  7018. +
  7019. + /* support LSM and notify */
  7020. + dlgt = need_dlgt(sb);
  7021. + hidden_file = au_h_fptr(file);
  7022. + h_inode = hidden_file->f_dentry->d_inode;
  7023. + if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
  7024. + err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
  7025. + else {
  7026. + struct inode *dir = dentry->d_parent->d_inode,
  7027. + *h_dir = hidden_file->f_dentry->d_parent->d_inode;
  7028. + aufs_bindex_t bstart = fbstart(file);
  7029. + hdir_lock(h_dir, dir, bstart);
  7030. + err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
  7031. + hdir_unlock(h_dir, dir, bstart);
  7032. + }
  7033. + memcpy(&file->f_ra, &hidden_file->f_ra, sizeof(file->f_ra)); //??
  7034. + dentry->d_inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
  7035. +
  7036. + fi_read_unlock(file);
  7037. + out:
  7038. + si_read_unlock(sb);
  7039. + TraceErr(err);
  7040. + return err;
  7041. +}
  7042. +
  7043. +static ssize_t aufs_write(struct file *file, const char __user *__buf,
  7044. + size_t count, loff_t *ppos)
  7045. +{
  7046. + ssize_t err;
  7047. + struct dentry *dentry;
  7048. + struct inode *inode;
  7049. + struct super_block *sb;
  7050. + struct file *hidden_file;
  7051. + char __user *buf = (char __user*)__buf;
  7052. + struct inode *h_inode;
  7053. + int dlgt;
  7054. +
  7055. + dentry = file->f_dentry;
  7056. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  7057. + DLNPair(dentry), (unsigned long)count, *ppos);
  7058. +
  7059. + inode = dentry->d_inode;
  7060. + i_lock(inode);
  7061. + sb = dentry->d_sb;
  7062. + si_read_lock(sb);
  7063. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
  7064. + /*locked*/1);
  7065. + //if (LktrCond) {fi_write_unlock(file); err = -1;}
  7066. + if (unlikely(err))
  7067. + goto out;
  7068. + err = au_ready_to_write(file, -1);
  7069. + //if (LktrCond) err = -1;
  7070. + if (unlikely(err))
  7071. + goto out_unlock;
  7072. +
  7073. + /* support LSM and notify */
  7074. + dlgt = need_dlgt(sb);
  7075. + hidden_file = au_h_fptr(file);
  7076. + h_inode = hidden_file->f_dentry->d_inode;
  7077. + if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
  7078. + err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
  7079. + else {
  7080. + struct inode *dir = dentry->d_parent->d_inode,
  7081. + *h_dir = hidden_file->f_dentry->d_parent->d_inode;
  7082. + aufs_bindex_t bstart = fbstart(file);
  7083. + hdir_lock(h_dir, dir, bstart);
  7084. + err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
  7085. + hdir_unlock(h_dir, dir, bstart);
  7086. + }
  7087. + ii_write_lock_child(inode);
  7088. + au_cpup_attr_timesizes(inode);
  7089. + ii_write_unlock(inode);
  7090. +
  7091. + out_unlock:
  7092. + fi_write_unlock(file);
  7093. + out:
  7094. + si_read_unlock(sb);
  7095. + i_unlock(inode);
  7096. + TraceErr(err);
  7097. + return err;
  7098. +}
  7099. +
  7100. +/* ---------------------------------------------------------------------- */
  7101. +
  7102. +#if 0 //def CONFIG_AUFS_ROBR
  7103. +struct lvma {
  7104. + struct list_head list;
  7105. + struct vm_area_struct *vma;
  7106. +};
  7107. +
  7108. +static struct file *safe_file(struct vm_area_struct *vma)
  7109. +{
  7110. + struct file *file = vma->vm_file;
  7111. + struct super_block *sb = file->f_dentry->d_sb;
  7112. + struct lvma *lvma, *entry;
  7113. + struct aufs_sbinfo *sbinfo;
  7114. + int found, warn;
  7115. +
  7116. + TraceEnter();
  7117. + DEBUG_ON(!SB_AUFS(sb));
  7118. +
  7119. + warn = 0;
  7120. + found = 0;
  7121. + sbinfo = stosi(sb);
  7122. + spin_lock(&sbinfo->si_lvma_lock);
  7123. + list_for_each_entry(entry, &sbinfo->si_lvma, list) {
  7124. + found = (entry->vma == vma);
  7125. + if (unlikely(found))
  7126. + break;
  7127. + }
  7128. + if (!found) {
  7129. + lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC);
  7130. + if (lvma) {
  7131. + lvma->vma = vma;
  7132. + list_add(&lvma->list, &sbinfo->si_lvma);
  7133. + } else {
  7134. + warn = 1;
  7135. + file = NULL;
  7136. + }
  7137. + } else
  7138. + file = NULL;
  7139. + spin_unlock(&sbinfo->si_lvma_lock);
  7140. +
  7141. + if (unlikely(warn))
  7142. + Warn1("no memory for lvma\n");
  7143. + return file;
  7144. +}
  7145. +
  7146. +static void reset_file(struct vm_area_struct *vma, struct file *file)
  7147. +{
  7148. + struct super_block *sb = file->f_dentry->d_sb;
  7149. + struct lvma *entry, *found;
  7150. + struct aufs_sbinfo *sbinfo;
  7151. +
  7152. + TraceEnter();
  7153. + DEBUG_ON(!SB_AUFS(sb));
  7154. +
  7155. + vma->vm_file = file;
  7156. +
  7157. + found = NULL;
  7158. + sbinfo = stosi(sb);
  7159. + spin_lock(&sbinfo->si_lvma_lock);
  7160. + list_for_each_entry(entry, &sbinfo->si_lvma, list)
  7161. + if (entry->vma == vma){
  7162. + found = entry;
  7163. + break;
  7164. + }
  7165. + DEBUG_ON(!found);
  7166. + list_del(&found->list);
  7167. + spin_unlock(&sbinfo->si_lvma_lock);
  7168. + kfree(found);
  7169. +}
  7170. +
  7171. +#else
  7172. +
  7173. +static struct file *safe_file(struct vm_area_struct *vma)
  7174. +{
  7175. + struct file *file;
  7176. +
  7177. + file = vma->vm_file;
  7178. + if (file->private_data && au_is_aufs(file->f_dentry->d_sb))
  7179. + return file;
  7180. + return NULL;
  7181. +}
  7182. +
  7183. +static void reset_file(struct vm_area_struct *vma, struct file *file)
  7184. +{
  7185. + vma->vm_file = file;
  7186. + smp_mb();
  7187. +}
  7188. +#endif /* CONFIG_AUFS_ROBR */
  7189. +
  7190. +static struct page *aufs_nopage(struct vm_area_struct *vma, unsigned long addr,
  7191. + int *type)
  7192. +{
  7193. + struct page *page;
  7194. + struct dentry *dentry;
  7195. + struct file *file, *hidden_file;
  7196. + struct inode *inode;
  7197. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  7198. + struct aufs_finfo *finfo;
  7199. +
  7200. + TraceEnter();
  7201. + DEBUG_ON(!vma || !vma->vm_file);
  7202. + wait_event(wq, (file = safe_file(vma)));
  7203. + DEBUG_ON(!au_is_aufs(file->f_dentry->d_sb));
  7204. + dentry = file->f_dentry;
  7205. + LKTRTrace("%.*s, addr %lx\n", DLNPair(dentry), addr);
  7206. + inode = dentry->d_inode;
  7207. + DEBUG_ON(!S_ISREG(inode->i_mode));
  7208. +
  7209. + // do not revalidate, nor lock
  7210. + finfo = ftofi(file);
  7211. + hidden_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
  7212. + DEBUG_ON(!hidden_file || !au_is_mmapped(file));
  7213. + vma->vm_file = hidden_file;
  7214. + //smp_mb();
  7215. + page = finfo->fi_h_vm_ops->nopage(vma, addr, type);
  7216. + reset_file(vma, file);
  7217. +#if 0 //def CONFIG_SMP
  7218. + //wake_up_nr(&wq, online_cpu - 1);
  7219. + wake_up_all(&wq);
  7220. +#else
  7221. + wake_up(&wq);
  7222. +#endif
  7223. + if (!IS_ERR(page)) {
  7224. + //page->mapping = file->f_mapping;
  7225. + //get_page(page);
  7226. + //file->f_mapping = hidden_file->f_mapping;
  7227. + //touch_atime(NULL, dentry);
  7228. + //inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
  7229. + }
  7230. + TraceErrPtr(page);
  7231. + return page;
  7232. +}
  7233. +
  7234. +static int aufs_populate(struct vm_area_struct *vma, unsigned long addr,
  7235. + unsigned long len, pgprot_t prot, unsigned long pgoff,
  7236. + int nonblock)
  7237. +{
  7238. + Err("please report me this application\n");
  7239. + BUG();
  7240. + return ftofi(vma->vm_file)->fi_h_vm_ops->populate
  7241. + (vma, addr, len, prot, pgoff, nonblock);
  7242. +}
  7243. +
  7244. +static struct vm_operations_struct aufs_vm_ops = {
  7245. + //.open = aufs_vmaopen,
  7246. + //.close = aufs_vmaclose,
  7247. + .nopage = aufs_nopage,
  7248. + .populate = aufs_populate,
  7249. + //page_mkwrite(struct vm_area_struct *vma, struct page *page)
  7250. +};
  7251. +
  7252. +/* ---------------------------------------------------------------------- */
  7253. +
  7254. +static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
  7255. +{
  7256. + int err, wlock, mmapped;
  7257. + struct dentry *dentry;
  7258. + struct super_block *sb;
  7259. + struct file *h_file;
  7260. + struct vm_operations_struct *vm_ops;
  7261. + unsigned long flags;
  7262. +
  7263. + dentry = file->f_dentry;
  7264. + LKTRTrace("%.*s, %lx, len %lu\n",
  7265. + DLNPair(dentry), vma->vm_start, vma->vm_end - vma->vm_start);
  7266. + DEBUG_ON(!S_ISREG(dentry->d_inode->i_mode));
  7267. + DEBUG_ON(down_write_trylock(&vma->vm_mm->mmap_sem));
  7268. +
  7269. + mmapped = au_is_mmapped(file);
  7270. + wlock = 0;
  7271. + if (file->f_mode & FMODE_WRITE) {
  7272. + flags = VM_SHARED | VM_WRITE;
  7273. + wlock = ((flags & vma->vm_flags) == flags);
  7274. + }
  7275. +
  7276. + sb = dentry->d_sb;
  7277. + si_read_lock(sb);
  7278. + err = au_reval_and_lock_finfo(file, au_reopen_nondir,
  7279. + wlock | !mmapped, /*locked*/0);
  7280. + //err = -1;
  7281. + if (unlikely(err))
  7282. + goto out;
  7283. +
  7284. + if (wlock) {
  7285. + err = au_ready_to_write(file, -1);
  7286. + //err = -1;
  7287. + if (unlikely(err))
  7288. + goto out_unlock;
  7289. + }
  7290. +
  7291. + h_file = au_h_fptr(file);
  7292. + vm_ops = ftofi(file)->fi_h_vm_ops;
  7293. + if (unlikely(!mmapped)) {
  7294. + // nfs uses some locks
  7295. + lockdep_off();
  7296. + err = h_file->f_op->mmap(h_file, vma);
  7297. + lockdep_on();
  7298. + if (unlikely(err))
  7299. + goto out_unlock;
  7300. + vm_ops = vma->vm_ops;
  7301. + DEBUG_ON(!vm_ops);
  7302. + err = do_munmap(current->mm, vma->vm_start,
  7303. + vma->vm_end - vma->vm_start);
  7304. + if (unlikely(err)) {
  7305. + IOErr("failed internal unmapping %.*s, %d\n",
  7306. + DLNPair(h_file->f_dentry), err);
  7307. + err = -EIO;
  7308. + goto out_unlock;
  7309. + }
  7310. + }
  7311. + DEBUG_ON(!vm_ops);
  7312. +
  7313. + err = generic_file_mmap(file, vma);
  7314. + if (!err) {
  7315. + file_accessed(h_file);
  7316. + dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
  7317. + vma->vm_ops = &aufs_vm_ops;
  7318. + if (unlikely(!mmapped))
  7319. + ftofi(file)->fi_h_vm_ops = vm_ops;
  7320. + }
  7321. +
  7322. + out_unlock:
  7323. + if (!wlock && mmapped)
  7324. + fi_read_unlock(file);
  7325. + else
  7326. + fi_write_unlock(file);
  7327. + out:
  7328. + si_read_unlock(sb);
  7329. + TraceErr(err);
  7330. + return err;
  7331. +}
  7332. +
  7333. +// todo: try do_sendfile() in fs/read_write.c
  7334. +static ssize_t aufs_sendfile(struct file *file, loff_t *ppos,
  7335. + size_t count, read_actor_t actor, void *target)
  7336. +{
  7337. + ssize_t err;
  7338. + struct file *h_file;
  7339. + const char c = current->comm[4];
  7340. + /* true if a kernel thread named 'loop[0-9].*' accesses a file */
  7341. + const int loopback = (current->mm == NULL
  7342. + && '0' <= c && c <= '9'
  7343. + && strncmp(current->comm, "loop", 4) == 0);
  7344. + struct dentry *dentry;
  7345. + struct super_block *sb;
  7346. +
  7347. + dentry = file->f_dentry;
  7348. + LKTRTrace("%.*s, pos %Ld, cnt %lu, loopback %d\n",
  7349. + DLNPair(dentry), *ppos, (unsigned long)count, loopback);
  7350. +
  7351. + sb = dentry->d_sb;
  7352. + si_read_lock(sb);
  7353. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7354. + /*locked*/0);
  7355. + if (unlikely(err))
  7356. + goto out;
  7357. +
  7358. + err = -EINVAL;
  7359. + h_file = au_h_fptr(file);
  7360. + if (h_file->f_op && h_file->f_op->sendfile) {
  7361. + if (/* unlikely */(loopback)) {
  7362. + file->f_mapping = h_file->f_mapping;
  7363. + smp_mb(); //??
  7364. + }
  7365. + // nfs uses some locks
  7366. + lockdep_off();
  7367. + err = h_file->f_op->sendfile
  7368. + (h_file, ppos, count, actor, target);
  7369. + lockdep_on();
  7370. + dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
  7371. + }
  7372. + fi_read_unlock(file);
  7373. +
  7374. + out:
  7375. + si_read_unlock(sb);
  7376. + TraceErr(err);
  7377. + return err;
  7378. +}
  7379. +
  7380. +/* ---------------------------------------------------------------------- */
  7381. +
  7382. +/* copied from linux/fs/select.h, must match */
  7383. +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
  7384. +
  7385. +static unsigned int aufs_poll(struct file *file, poll_table *wait)
  7386. +{
  7387. + unsigned int mask;
  7388. + struct file *hidden_file;
  7389. + int err;
  7390. + struct dentry *dentry;
  7391. + struct super_block *sb;
  7392. +
  7393. + dentry = file->f_dentry;
  7394. + LKTRTrace("%.*s, wait %p\n", DLNPair(dentry), wait);
  7395. + DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode));
  7396. +
  7397. + /* We should pretend an error happend. */
  7398. + mask = POLLERR /* | POLLIN | POLLOUT */;
  7399. + sb = dentry->d_sb;
  7400. + si_read_lock(sb);
  7401. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7402. + /*locked*/0);
  7403. + //err = -1;
  7404. + if (unlikely(err))
  7405. + goto out;
  7406. +
  7407. + /* it is not an error of hidden_file has no operation */
  7408. + mask = DEFAULT_POLLMASK;
  7409. + hidden_file = au_h_fptr(file);
  7410. + if (hidden_file->f_op && hidden_file->f_op->poll)
  7411. + mask = hidden_file->f_op->poll(hidden_file, wait);
  7412. + fi_read_unlock(file);
  7413. +
  7414. + out:
  7415. + si_read_unlock(sb);
  7416. + TraceErr((int)mask);
  7417. + return mask;
  7418. +}
  7419. +
  7420. +static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
  7421. + int datasync)
  7422. +{
  7423. + int err, my_lock;
  7424. + struct inode *inode;
  7425. + struct file *hidden_file;
  7426. + struct super_block *sb;
  7427. +
  7428. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
  7429. + inode = dentry->d_inode;
  7430. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
  7431. + IMustLock(inode);
  7432. + my_lock = 0;
  7433. +#else
  7434. + /* before 2.6.17,
  7435. + * msync(2) calls me without locking i_sem/i_mutex, but fsync(2).
  7436. + */
  7437. + my_lock = !i_trylock(inode);
  7438. +#endif
  7439. +
  7440. + sb = dentry->d_sb;
  7441. + si_read_lock(sb);
  7442. + err = 0; //-EBADF; // posix?
  7443. + if (unlikely(!(file->f_mode & FMODE_WRITE)))
  7444. + goto out;
  7445. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
  7446. + /*locked*/1);
  7447. + //err = -1;
  7448. + if (unlikely(err))
  7449. + goto out;
  7450. + err = au_ready_to_write(file, -1);
  7451. + //err = -1;
  7452. + if (unlikely(err))
  7453. + goto out_unlock;
  7454. +
  7455. + err = -EINVAL;
  7456. + hidden_file = au_h_fptr(file);
  7457. + if (hidden_file->f_op && hidden_file->f_op->fsync) {
  7458. + // todo: apparmor thread?
  7459. + //file->f_mapping->host->i_mutex
  7460. + ii_write_lock_child(inode);
  7461. + hi_lock_child(hidden_file->f_dentry->d_inode);
  7462. + err = hidden_file->f_op->fsync
  7463. + (hidden_file, hidden_file->f_dentry, datasync);
  7464. + //err = -1;
  7465. + au_cpup_attr_timesizes(inode);
  7466. + i_unlock(hidden_file->f_dentry->d_inode);
  7467. + ii_write_unlock(inode);
  7468. + }
  7469. +
  7470. + out_unlock:
  7471. + fi_write_unlock(file);
  7472. + out:
  7473. + if (unlikely(my_lock))
  7474. + i_unlock(inode);
  7475. + si_read_unlock(sb);
  7476. + TraceErr(err);
  7477. + return err;
  7478. +}
  7479. +
  7480. +static int aufs_fasync(int fd, struct file *file, int flag)
  7481. +{
  7482. + int err;
  7483. + struct file *hidden_file;
  7484. + struct dentry *dentry;
  7485. + struct super_block *sb;
  7486. +
  7487. + dentry = file->f_dentry;
  7488. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), flag);
  7489. +
  7490. + sb = dentry->d_sb;
  7491. + si_read_lock(sb);
  7492. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7493. + /*locked*/0);
  7494. + //err = -1;
  7495. + if (unlikely(err))
  7496. + goto out;
  7497. +
  7498. + hidden_file = au_h_fptr(file);
  7499. + if (hidden_file->f_op && hidden_file->f_op->fasync)
  7500. + err = hidden_file->f_op->fasync(fd, hidden_file, flag);
  7501. + fi_read_unlock(file);
  7502. +
  7503. + out:
  7504. + si_read_unlock(sb);
  7505. + TraceErr(err);
  7506. + return err;
  7507. +}
  7508. +
  7509. +/* ---------------------------------------------------------------------- */
  7510. +
  7511. +#if 0 // comment
  7512. +struct file_operations {
  7513. + struct module *owner;
  7514. + loff_t (*llseek) (struct file *, loff_t, int);
  7515. + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
  7516. + ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
  7517. + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
  7518. + ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
  7519. + int (*readdir) (struct file *, void *, filldir_t);
  7520. + unsigned int (*poll) (struct file *, struct poll_table_struct *);
  7521. + int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
  7522. + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
  7523. + long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
  7524. + int (*mmap) (struct file *, struct vm_area_struct *);
  7525. + int (*open) (struct inode *, struct file *);
  7526. + int (*flush) (struct file *);
  7527. + int (*release) (struct inode *, struct file *);
  7528. + int (*fsync) (struct file *, struct dentry *, int datasync);
  7529. + int (*aio_fsync) (struct kiocb *, int datasync);
  7530. + int (*fasync) (int, struct file *, int);
  7531. + int (*lock) (struct file *, int, struct file_lock *);
  7532. + ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
  7533. + ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
  7534. + ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
  7535. + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
  7536. + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
  7537. + int (*check_flags)(int);
  7538. + int (*dir_notify)(struct file *file, unsigned long arg);
  7539. + int (*flock) (struct file *, int, struct file_lock *);
  7540. +};
  7541. +#endif
  7542. +
  7543. +struct file_operations aufs_file_fop = {
  7544. + .read = aufs_read,
  7545. + .write = aufs_write,
  7546. + .poll = aufs_poll,
  7547. + .mmap = aufs_mmap,
  7548. + .open = aufs_open_nondir,
  7549. + .flush = aufs_flush,
  7550. + .release = aufs_release_nondir,
  7551. + .fsync = aufs_fsync_nondir,
  7552. + .fasync = aufs_fasync,
  7553. + .sendfile = aufs_sendfile,
  7554. +};
  7555. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/file.c linux-2.6.22.1/fs/aufs/file.c
  7556. --- linux-2.6.22.1.oorig/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
  7557. +++ linux-2.6.22.1/fs/aufs/file.c 2007-07-24 14:17:46.000000000 +0200
  7558. @@ -0,0 +1,832 @@
  7559. +/*
  7560. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  7561. + *
  7562. + * This program, aufs is free software; you can redistribute it and/or modify
  7563. + * it under the terms of the GNU General Public License as published by
  7564. + * the Free Software Foundation; either version 2 of the License, or
  7565. + * (at your option) any later version.
  7566. + *
  7567. + * This program is distributed in the hope that it will be useful,
  7568. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7569. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  7570. + * GNU General Public License for more details.
  7571. + *
  7572. + * You should have received a copy of the GNU General Public License
  7573. + * along with this program; if not, write to the Free Software
  7574. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  7575. + */
  7576. +
  7577. +/* $Id: file.c,v 1.42 2007/05/14 03:39:09 sfjro Exp $ */
  7578. +
  7579. +//#include <linux/fsnotify.h>
  7580. +#include <linux/pagemap.h>
  7581. +//#include <linux/poll.h>
  7582. +//#include <linux/security.h>
  7583. +#include "aufs.h"
  7584. +
  7585. +/* drop flags for writing */
  7586. +unsigned int au_file_roflags(unsigned int flags)
  7587. +{
  7588. + flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
  7589. + flags |= O_RDONLY | O_NOATIME;
  7590. + return flags;
  7591. +}
  7592. +
  7593. +/* common functions to regular file and dir */
  7594. +struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags)
  7595. +{
  7596. + struct dentry *hidden_dentry;
  7597. + struct inode *hidden_inode;
  7598. + struct super_block *sb;
  7599. + struct vfsmount *hidden_mnt;
  7600. + struct file *hidden_file;
  7601. + struct aufs_branch *br;
  7602. + loff_t old_size;
  7603. + int udba;
  7604. +
  7605. + LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags);
  7606. + DEBUG_ON(!dentry);
  7607. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  7608. + DEBUG_ON(!hidden_dentry);
  7609. + hidden_inode = hidden_dentry->d_inode;
  7610. + DEBUG_ON(!hidden_inode);
  7611. +
  7612. + sb = dentry->d_sb;
  7613. + udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
  7614. + if (unlikely(udba)) {
  7615. + // test here?
  7616. + }
  7617. +
  7618. + br = stobr(sb, bindex);
  7619. + br_get(br);
  7620. + /* drop flags for writing */
  7621. + if (test_ro(sb, bindex, dentry->d_inode))
  7622. + flags = au_file_roflags(flags);
  7623. + flags &= ~O_CREAT;
  7624. + spin_lock(&hidden_inode->i_lock);
  7625. + old_size = i_size_read(hidden_inode);
  7626. + spin_unlock(&hidden_inode->i_lock);
  7627. +
  7628. + //DbgSleep(3);
  7629. +
  7630. + dget(hidden_dentry);
  7631. + hidden_mnt = mntget(br->br_mnt);
  7632. + hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags);
  7633. + //if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);}
  7634. +
  7635. + if (!IS_ERR(hidden_file)) {
  7636. +#if 0 // remove this
  7637. + if (/* old_size && */ (flags & O_TRUNC)) {
  7638. + au_direval_dec(dentry);
  7639. + if (!IS_ROOT(dentry))
  7640. + au_direval_dec(dentry->d_parent);
  7641. + }
  7642. +#endif
  7643. + return hidden_file;
  7644. + }
  7645. +
  7646. + br_put(br);
  7647. + TraceErrPtr(hidden_file);
  7648. + return hidden_file;
  7649. +}
  7650. +
  7651. +static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
  7652. +{
  7653. + int err;
  7654. + struct dentry *parent, *h_parent, *h_dentry;
  7655. + aufs_bindex_t bcpup;
  7656. + struct inode *h_dir, *h_inode, *dir;
  7657. +
  7658. + LKTRTrace("%.*s\n", DLNPair(dentry));
  7659. + DEBUG_ON(IS_ROOT(dentry));
  7660. + DiMustWriteLock(dentry);
  7661. +
  7662. + parent = dentry->d_parent; // dget_parent()
  7663. + di_write_lock_parent(parent);
  7664. + bcpup = err = find_rw_parent_br(dentry, bstart);
  7665. + //bcpup = err = find_rw_br(sb, bstart);
  7666. + if (unlikely(err < 0)) {
  7667. + err = 0; // stop copyup, it is not an error
  7668. + goto out;
  7669. + }
  7670. + err = 0;
  7671. +
  7672. + h_parent = au_h_dptr_i(parent, bcpup);
  7673. + if (!h_parent) {
  7674. + err = cpup_dirs(dentry, bcpup, NULL);
  7675. + if (unlikely(err))
  7676. + goto out;
  7677. + h_parent = au_h_dptr_i(parent, bcpup);
  7678. + }
  7679. +
  7680. + h_dir = h_parent->d_inode;
  7681. + h_dentry = au_h_dptr_i(dentry, bstart);
  7682. + h_inode = h_dentry->d_inode;
  7683. + dir = parent->d_inode;
  7684. + hdir_lock(h_dir, dir, bcpup);
  7685. + hi_lock_child(h_inode);
  7686. + DEBUG_ON(au_h_dptr_i(dentry, bcpup));
  7687. + err = sio_cpup_simple(dentry, bcpup, -1,
  7688. + au_flags_cpup(CPUP_DTIME, parent));
  7689. + TraceErr(err);
  7690. + i_unlock(h_inode);
  7691. + hdir_unlock(h_dir, dir, bcpup);
  7692. +
  7693. + out:
  7694. + di_write_unlock(parent);
  7695. + TraceErr(err);
  7696. + return err;
  7697. +}
  7698. +
  7699. +int au_do_open(struct inode *inode, struct file *file,
  7700. + int (*open)(struct file *file, int flags))
  7701. +{
  7702. + int err, coo;
  7703. + struct dentry *dentry;
  7704. + struct super_block *sb;
  7705. + aufs_bindex_t bstart;
  7706. + struct inode *h_dir, *dir;
  7707. +
  7708. + dentry = file->f_dentry;
  7709. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
  7710. +
  7711. + sb = dentry->d_sb;
  7712. + si_read_lock(sb);
  7713. + coo = 0;
  7714. +#if 0
  7715. + switch (au_flag_test_coo(sb)) {
  7716. + case AuFlag_COO_LEAF:
  7717. + coo = !S_ISDIR(inode->i_mode);
  7718. + break;
  7719. + case AuFlag_COO_ALL:
  7720. + coo = 1;
  7721. + break;
  7722. + }
  7723. +#endif
  7724. + err = au_init_finfo(file);
  7725. + //if (LktrCond) {fi_write_unlock(file); fin_finfo(file); err = -1;}
  7726. + if (unlikely(err))
  7727. + goto out;
  7728. +
  7729. + if (!coo) {
  7730. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  7731. + bstart = dbstart(dentry);
  7732. + } else {
  7733. + di_write_lock_child(dentry);
  7734. + bstart = dbstart(dentry);
  7735. + if (test_ro(sb, bstart, dentry->d_inode)) {
  7736. + err = do_coo(dentry, bstart);
  7737. + if (err) {
  7738. + di_write_unlock(dentry);
  7739. + goto out_finfo;
  7740. + }
  7741. + bstart = dbstart(dentry);
  7742. + }
  7743. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  7744. + }
  7745. +
  7746. + // todo: remove this extra locks
  7747. + dir = dentry->d_parent->d_inode;
  7748. + if (!IS_ROOT(dentry))
  7749. + ii_read_lock_parent(dir);
  7750. + h_dir = au_h_iptr_i(dir, bstart);
  7751. + hdir_lock(h_dir, dir, bstart);
  7752. + err = open(file, file->f_flags);
  7753. + //if (LktrCond) err = -1;
  7754. + hdir_unlock(h_dir, dir, bstart);
  7755. + if (!IS_ROOT(dentry))
  7756. + ii_read_unlock(dir);
  7757. + di_read_unlock(dentry, AUFS_I_RLOCK);
  7758. +
  7759. + out_finfo:
  7760. + fi_write_unlock(file);
  7761. + if (unlikely(err))
  7762. + au_fin_finfo(file);
  7763. + //DbgFile(file);
  7764. + out:
  7765. + si_read_unlock(sb);
  7766. + TraceErr(err);
  7767. + return err;
  7768. +}
  7769. +
  7770. +int au_reopen_nondir(struct file *file)
  7771. +{
  7772. + int err;
  7773. + struct dentry *dentry;
  7774. + aufs_bindex_t bstart, bindex, bend;
  7775. + struct file *hidden_file, *h_file_tmp;
  7776. +
  7777. + dentry = file->f_dentry;
  7778. + LKTRTrace("%.*s\n", DLNPair(dentry));
  7779. + DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
  7780. + || !au_h_dptr(dentry)->d_inode);
  7781. + bstart = dbstart(dentry);
  7782. +
  7783. + h_file_tmp = NULL;
  7784. + if (fbstart(file) == bstart) {
  7785. + hidden_file = au_h_fptr(file);
  7786. + if (file->f_mode == hidden_file->f_mode)
  7787. + return 0; /* success */
  7788. + h_file_tmp = hidden_file;
  7789. + get_file(h_file_tmp);
  7790. + set_h_fptr(file, bstart, NULL);
  7791. + }
  7792. + DEBUG_ON(fbstart(file) < bstart
  7793. + || ftofi(file)->fi_hfile[0 + bstart].hf_file);
  7794. +
  7795. + hidden_file = hidden_open(dentry, bstart, file->f_flags & ~O_TRUNC);
  7796. + //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bstart));
  7797. + //hidden_file = ERR_PTR(-1);}
  7798. + err = PTR_ERR(hidden_file);
  7799. + if (IS_ERR(hidden_file))
  7800. + goto out; // close all?
  7801. + err = 0;
  7802. + //cpup_file_flags(hidden_file, file);
  7803. + set_fbstart(file, bstart);
  7804. + set_h_fptr(file, bstart, hidden_file);
  7805. + memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(file->f_ra)); //??
  7806. +
  7807. + /* close lower files */
  7808. + bend = fbend(file);
  7809. + for (bindex = bstart + 1; bindex <= bend; bindex++)
  7810. + set_h_fptr(file, bindex, NULL);
  7811. + set_fbend(file, bstart);
  7812. +
  7813. + out:
  7814. + if (h_file_tmp)
  7815. + fput(h_file_tmp);
  7816. + TraceErr(err);
  7817. + return err;
  7818. +}
  7819. +
  7820. +/*
  7821. + * copyup the deleted file for writing.
  7822. + */
  7823. +static int cpup_wh_file(struct file *file, aufs_bindex_t bdst, loff_t len)
  7824. +{
  7825. + int err;
  7826. + struct dentry *dentry, *parent, *hidden_parent, *tmp_dentry;
  7827. + struct dentry *hidden_dentry_bstart, *hidden_dentry_bdst;
  7828. + struct inode *hidden_dir;
  7829. + aufs_bindex_t bstart;
  7830. + struct aufs_dinfo *dinfo;
  7831. + struct dtime dt;
  7832. + struct lkup_args lkup;
  7833. + struct super_block *sb;
  7834. +
  7835. + dentry = file->f_dentry;
  7836. + LKTRTrace("%.*s, bdst %d, len %Lu\n", DLNPair(dentry), bdst, len);
  7837. + DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
  7838. + || !(file->f_mode & FMODE_WRITE));
  7839. + DiMustWriteLock(dentry);
  7840. + parent = dentry->d_parent;
  7841. + IiMustAnyLock(parent->d_inode);
  7842. + hidden_parent = au_h_dptr_i(parent, bdst);
  7843. + DEBUG_ON(!hidden_parent);
  7844. + hidden_dir = hidden_parent->d_inode;
  7845. + DEBUG_ON(!hidden_dir);
  7846. + IMustLock(hidden_dir);
  7847. +
  7848. + sb = parent->d_sb;
  7849. + lkup.nfsmnt = au_nfsmnt(sb, bdst);
  7850. + lkup.dlgt = need_dlgt(sb);
  7851. + tmp_dentry = lkup_whtmp(hidden_parent, &dentry->d_name, &lkup);
  7852. + //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
  7853. + err = PTR_ERR(tmp_dentry);
  7854. + if (IS_ERR(tmp_dentry))
  7855. + goto out;
  7856. +
  7857. + dtime_store(&dt, parent, hidden_parent);
  7858. + dinfo = dtodi(dentry);
  7859. + bstart = dinfo->di_bstart;
  7860. + hidden_dentry_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
  7861. + hidden_dentry_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
  7862. + dinfo->di_bstart = bdst;
  7863. + dinfo->di_hdentry[0 + bdst].hd_dentry = tmp_dentry;
  7864. + dinfo->di_hdentry[0 + bstart].hd_dentry = au_h_fptr(file)->f_dentry;
  7865. + err = cpup_single(dentry, bdst, bstart, len,
  7866. + au_flags_cpup(!CPUP_DTIME, parent));
  7867. + //if (LktrCond) err = -1;
  7868. + if (!err)
  7869. + err = au_reopen_nondir(file);
  7870. + //err = -1;
  7871. + dinfo->di_hdentry[0 + bstart].hd_dentry = hidden_dentry_bstart;
  7872. + dinfo->di_hdentry[0 + bdst].hd_dentry = hidden_dentry_bdst;
  7873. + dinfo->di_bstart = bstart;
  7874. + if (unlikely(err))
  7875. + goto out_tmp;
  7876. +
  7877. + DEBUG_ON(!d_unhashed(dentry));
  7878. + err = vfsub_unlink(hidden_dir, tmp_dentry, lkup.dlgt);
  7879. + //if (LktrCond) err = -1;
  7880. + if (unlikely(err)) {
  7881. + IOErr("failed remove copied-up tmp file %.*s(%d)\n",
  7882. + DLNPair(tmp_dentry), err);
  7883. + err = -EIO;
  7884. + }
  7885. + dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
  7886. +
  7887. + out_tmp:
  7888. + dput(tmp_dentry);
  7889. + out:
  7890. + TraceErr(err);
  7891. + return err;
  7892. +}
  7893. +
  7894. +struct cpup_wh_file_args {
  7895. + int *errp;
  7896. + struct file *file;
  7897. + aufs_bindex_t bdst;
  7898. + loff_t len;
  7899. +};
  7900. +
  7901. +static void call_cpup_wh_file(void *args)
  7902. +{
  7903. + struct cpup_wh_file_args *a = args;
  7904. + *a->errp = cpup_wh_file(a->file, a->bdst, a->len);
  7905. +}
  7906. +
  7907. +/*
  7908. + * prepare the @file for writing.
  7909. + */
  7910. +int au_ready_to_write(struct file *file, loff_t len)
  7911. +{
  7912. + int err;
  7913. + struct dentry *dentry, *parent, *hidden_dentry, *hidden_parent;
  7914. + struct inode *hidden_inode, *hidden_dir, *inode, *dir;
  7915. + struct super_block *sb;
  7916. + aufs_bindex_t bstart, bcpup;
  7917. +
  7918. + dentry = file->f_dentry;
  7919. + LKTRTrace("%.*s, len %Ld\n", DLNPair(dentry), len);
  7920. + FiMustWriteLock(file);
  7921. +
  7922. + sb = dentry->d_sb;
  7923. + bstart = fbstart(file);
  7924. + DEBUG_ON(ftobr(file, bstart) != stobr(sb, bstart));
  7925. +
  7926. + inode = dentry->d_inode;
  7927. + ii_read_lock_child(inode);
  7928. + LKTRTrace("rdonly %d, bstart %d\n", test_ro(sb, bstart, inode), bstart);
  7929. + err = test_ro(sb, bstart, inode);
  7930. + ii_read_unlock(inode);
  7931. + if (!err && (au_h_fptr(file)->f_mode & FMODE_WRITE))
  7932. + return 0;
  7933. +
  7934. + /* need to cpup */
  7935. + parent = dentry->d_parent; // dget_parent()
  7936. + di_write_lock_child(dentry);
  7937. + di_write_lock_parent(parent);
  7938. + bcpup = err = find_rw_parent_br(dentry, bstart);
  7939. + //bcpup = err = find_rw_br(sb, bstart);
  7940. + if (unlikely(err < 0))
  7941. + goto out_unlock;
  7942. + err = 0;
  7943. +
  7944. + hidden_parent = au_h_dptr_i(parent, bcpup);
  7945. + if (!hidden_parent) {
  7946. + err = cpup_dirs(dentry, bcpup, NULL);
  7947. + //if (LktrCond) err = -1;
  7948. + if (unlikely(err))
  7949. + goto out_unlock;
  7950. + hidden_parent = au_h_dptr_i(parent, bcpup);
  7951. + }
  7952. +
  7953. + hidden_dir = hidden_parent->d_inode;
  7954. + hidden_dentry = au_h_fptr(file)->f_dentry;
  7955. + hidden_inode = hidden_dentry->d_inode;
  7956. + dir = parent->d_inode;
  7957. + hdir_lock(hidden_dir, dir, bcpup);
  7958. + hi_lock_child(hidden_inode);
  7959. + if (d_unhashed(dentry) || d_unhashed(hidden_dentry)
  7960. + /* || !hidden_inode->i_nlink */) {
  7961. + if (!au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE,
  7962. + need_dlgt(sb)))
  7963. + err = cpup_wh_file(file, bcpup, len);
  7964. + else {
  7965. + struct cpup_wh_file_args args = {
  7966. + .errp = &err,
  7967. + .file = file,
  7968. + .bdst = bcpup,
  7969. + .len = len
  7970. + };
  7971. + au_wkq_wait(call_cpup_wh_file, &args, /*dlgt*/0);
  7972. + }
  7973. + //if (LktrCond) err = -1;
  7974. + TraceErr(err);
  7975. + } else {
  7976. + if (!au_h_dptr_i(dentry, bcpup))
  7977. + err = sio_cpup_simple(dentry, bcpup, len,
  7978. + au_flags_cpup(CPUP_DTIME,
  7979. + parent));
  7980. + //if (LktrCond) err = -1;
  7981. + TraceErr(err);
  7982. + if (!err)
  7983. + err = au_reopen_nondir(file);
  7984. + //if (LktrCond) err = -1;
  7985. + TraceErr(err);
  7986. + }
  7987. + i_unlock(hidden_inode);
  7988. + hdir_unlock(hidden_dir, dir, bcpup);
  7989. +
  7990. + out_unlock:
  7991. + di_write_unlock(parent);
  7992. + di_write_unlock(dentry);
  7993. +// out:
  7994. + TraceErr(err);
  7995. + return err;
  7996. +
  7997. +}
  7998. +
  7999. +/* ---------------------------------------------------------------------- */
  8000. +
  8001. +/*
  8002. + * after branch manipulating, refresh the file.
  8003. + */
  8004. +static int refresh_file(struct file *file, int (*reopen)(struct file *file))
  8005. +{
  8006. + int err, new_sz;
  8007. + struct dentry *dentry;
  8008. + aufs_bindex_t bend, bindex, bstart, brid;
  8009. + struct aufs_hfile *p;
  8010. + struct aufs_finfo *finfo;
  8011. + struct super_block *sb;
  8012. + struct inode *inode;
  8013. + struct file *hidden_file;
  8014. +
  8015. + dentry = file->f_dentry;
  8016. + LKTRTrace("%.*s\n", DLNPair(dentry));
  8017. + FiMustWriteLock(file);
  8018. + DiMustReadLock(dentry);
  8019. + inode = dentry->d_inode;
  8020. + IiMustReadLock(inode);
  8021. + //au_debug_on();
  8022. + //DbgDentry(dentry);
  8023. + //DbgFile(file);
  8024. + //au_debug_off();
  8025. +
  8026. + err = -ENOMEM;
  8027. + sb = dentry->d_sb;
  8028. + finfo = ftofi(file);
  8029. + bstart = finfo->fi_bstart;
  8030. + bend = finfo->fi_bstart;
  8031. + new_sz = sizeof(*finfo->fi_hfile) * (sbend(sb) + 1);
  8032. + p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1),
  8033. + new_sz, GFP_KERNEL);
  8034. + //p = NULL;
  8035. + if (unlikely(!p))
  8036. + goto out;
  8037. + finfo->fi_hfile = p;
  8038. + hidden_file = p[0 + bstart].hf_file;
  8039. +
  8040. + p = finfo->fi_hfile + finfo->fi_bstart;
  8041. + brid = p->hf_br->br_id;
  8042. + bend = finfo->fi_bend;
  8043. + for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
  8044. + struct aufs_hfile tmp, *q;
  8045. + aufs_bindex_t new_bindex;
  8046. +
  8047. + if (!p->hf_file)
  8048. + continue;
  8049. + new_bindex = find_bindex(sb, p->hf_br);
  8050. + if (new_bindex == bindex)
  8051. + continue;
  8052. + if (new_bindex < 0) { // test here
  8053. + set_h_fptr(file, bindex, NULL);
  8054. + continue;
  8055. + }
  8056. +
  8057. + /* swap two hidden inode, and loop again */
  8058. + q = finfo->fi_hfile + new_bindex;
  8059. + tmp = *q;
  8060. + *q = *p;
  8061. + *p = tmp;
  8062. + if (tmp.hf_file) {
  8063. + bindex--;
  8064. + p--;
  8065. + }
  8066. + }
  8067. + {
  8068. + aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend;
  8069. + finfo->fi_bstart = 0;
  8070. + finfo->fi_bend = sbend(sb);
  8071. + //au_debug_on();
  8072. + //DbgFile(file);
  8073. + //au_debug_off();
  8074. + finfo->fi_bstart = s;
  8075. + finfo->fi_bend = e;
  8076. + }
  8077. +
  8078. + p = finfo->fi_hfile;
  8079. + if (!au_is_mmapped(file) && !d_unhashed(dentry)) {
  8080. + bend = sbend(sb);
  8081. + for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
  8082. + finfo->fi_bstart++, p++)
  8083. + if (p->hf_file) {
  8084. + if (p->hf_file->f_dentry
  8085. + && p->hf_file->f_dentry->d_inode)
  8086. + break;
  8087. + else
  8088. + au_hfput(p);
  8089. + }
  8090. + } else {
  8091. + bend = find_brindex(sb, brid);
  8092. + //LKTRTrace("%d\n", bend);
  8093. + for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
  8094. + finfo->fi_bstart++, p++)
  8095. + if (p->hf_file)
  8096. + au_hfput(p);
  8097. + //LKTRTrace("%d\n", finfo->fi_bstart);
  8098. + bend = sbend(sb);
  8099. + }
  8100. +
  8101. + p = finfo->fi_hfile + bend;
  8102. + for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
  8103. + finfo->fi_bend--, p--)
  8104. + if (p->hf_file) {
  8105. + if (p->hf_file->f_dentry
  8106. + && p->hf_file->f_dentry->d_inode)
  8107. + break;
  8108. + else
  8109. + au_hfput(p);
  8110. + }
  8111. + //Dbg("%d, %d\n", finfo->fi_bstart, finfo->fi_bend);
  8112. + DEBUG_ON(finfo->fi_bend < finfo->fi_bstart);
  8113. + //DbgFile(file);
  8114. + //DbgDentry(file->f_dentry);
  8115. +
  8116. + err = 0;
  8117. +#if 0 // todo:
  8118. + if (!au_h_dptr(dentry)->d_inode) {
  8119. + au_update_figen(file);
  8120. + goto out; /* success */
  8121. + }
  8122. +#endif
  8123. +
  8124. + if (unlikely(au_is_mmapped(file) || d_unhashed(dentry)))
  8125. + goto out_update; /* success */
  8126. +
  8127. + again:
  8128. + bstart = ibstart(inode);
  8129. + if (bstart < finfo->fi_bstart
  8130. + && au_flag_test(sb, AuFlag_PLINK)
  8131. + && au_is_plinked(sb, inode)) {
  8132. + struct dentry *parent = dentry->d_parent; // dget_parent()
  8133. + struct inode *dir = parent->d_inode, *h_dir;
  8134. +
  8135. + if (test_ro(sb, bstart, inode)) {
  8136. + di_read_lock_parent(parent, !AUFS_I_RLOCK);
  8137. + bstart = err = find_rw_parent_br(dentry, bstart);
  8138. + //bstart = err = find_rw_br(sb, bstart);
  8139. + di_read_unlock(parent, !AUFS_I_RLOCK);
  8140. + //todo: err = -1;
  8141. + if (unlikely(err < 0))
  8142. + goto out;
  8143. + }
  8144. + di_read_unlock(dentry, AUFS_I_RLOCK);
  8145. + di_write_lock_child(dentry);
  8146. + if (bstart != ibstart(inode)) { // todo
  8147. + /* someone changed our inode while we were sleeping */
  8148. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  8149. + goto again;
  8150. + }
  8151. +
  8152. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  8153. + err = test_and_cpup_dirs(dentry, bstart, NULL);
  8154. +
  8155. + // always superio.
  8156. +#if 1
  8157. + h_dir = au_h_dptr_i(parent, bstart)->d_inode;
  8158. + hdir_lock(h_dir, dir, bstart);
  8159. + err = sio_cpup_simple(dentry, bstart, -1,
  8160. + au_flags_cpup(CPUP_DTIME, parent));
  8161. + hdir_unlock(h_dir, dir, bstart);
  8162. + di_read_unlock(parent, AUFS_I_RLOCK);
  8163. +#else
  8164. + if (!is_au_wkq(current)) {
  8165. + struct cpup_pseudo_link_args args = {
  8166. + .errp = &err,
  8167. + .dentry = dentry,
  8168. + .bdst = bstart,
  8169. + .do_lock = 1
  8170. + };
  8171. + au_wkq_wait(call_cpup_pseudo_link, &args);
  8172. + } else
  8173. + err = cpup_pseudo_link(dentry, bstart, /*do_lock*/1);
  8174. +#endif
  8175. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  8176. + if (unlikely(err))
  8177. + goto out;
  8178. + }
  8179. +
  8180. + err = reopen(file);
  8181. + //err = -1;
  8182. + out_update:
  8183. + if (!err) {
  8184. + au_update_figen(file);
  8185. + //DbgFile(file);
  8186. + return 0; /* success */
  8187. + }
  8188. +
  8189. + /* error, close all hidden files */
  8190. + bend = fbend(file);
  8191. + for (bindex = fbstart(file); bindex <= bend; bindex++)
  8192. + set_h_fptr(file, bindex, NULL);
  8193. +
  8194. + out:
  8195. + TraceErr(err);
  8196. + return err;
  8197. +}
  8198. +
  8199. +/* common function to regular file and dir */
  8200. +int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
  8201. + int wlock, int locked)
  8202. +{
  8203. + int err, sgen, fgen, pseudo_link;
  8204. + struct dentry *dentry;
  8205. + struct super_block *sb;
  8206. + aufs_bindex_t bstart;
  8207. +
  8208. + dentry = file->f_dentry;
  8209. + LKTRTrace("%.*s, w %d, l %d\n", DLNPair(dentry), wlock, locked);
  8210. + sb = dentry->d_sb;
  8211. + SiMustAnyLock(sb);
  8212. +
  8213. + err = 0;
  8214. + sgen = au_sigen(sb);
  8215. + fi_write_lock(file);
  8216. + fgen = au_figen(file);
  8217. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  8218. + bstart = dbstart(dentry);
  8219. + pseudo_link = (bstart != ibstart(dentry->d_inode));
  8220. + di_read_unlock(dentry, AUFS_I_RLOCK);
  8221. + if (sgen == fgen && !pseudo_link && fbstart(file) == bstart) {
  8222. + if (!wlock)
  8223. + fi_downgrade_lock(file);
  8224. + return 0; /* success */
  8225. + }
  8226. +
  8227. + LKTRTrace("sgen %d, fgen %d\n", sgen, fgen);
  8228. + if (sgen != au_digen(dentry)) {
  8229. + /*
  8230. + * d_path() and path_lookup() is a simple and good approach
  8231. + * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a
  8232. + * deadlock. removed the code.
  8233. + */
  8234. + di_write_lock_child(dentry);
  8235. + err = au_reval_dpath(dentry, sgen);
  8236. + //if (LktrCond) err = -1;
  8237. + di_write_unlock(dentry);
  8238. + if (unlikely(err < 0))
  8239. + goto out;
  8240. + DEBUG_ON(au_digen(dentry) != sgen);
  8241. + }
  8242. +
  8243. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  8244. + err = refresh_file(file, reopen);
  8245. + //if (LktrCond) err = -1;
  8246. + di_read_unlock(dentry, AUFS_I_RLOCK);
  8247. + if (!err) {
  8248. + if (!wlock)
  8249. + fi_downgrade_lock(file);
  8250. + } else
  8251. + fi_write_unlock(file);
  8252. +
  8253. + out:
  8254. + TraceErr(err);
  8255. + return err;
  8256. +}
  8257. +
  8258. +/* ---------------------------------------------------------------------- */
  8259. +
  8260. +// cf. aufs_nopage()
  8261. +// for madvise(2)
  8262. +static int aufs_readpage(struct file *file, struct page *page)
  8263. +{
  8264. + TraceEnter();
  8265. + unlock_page(page);
  8266. + return 0;
  8267. +}
  8268. +
  8269. +// they will never be called.
  8270. +#ifdef CONFIG_AUFS_DEBUG
  8271. +static int aufs_prepare_write(struct file *file, struct page *page,
  8272. + unsigned from, unsigned to)
  8273. +{BUG();return 0;}
  8274. +static int aufs_commit_write(struct file *file, struct page *page,
  8275. + unsigned from, unsigned to)
  8276. +{BUG();return 0;}
  8277. +static int aufs_writepage(struct page *page, struct writeback_control *wbc)
  8278. +{BUG();return 0;}
  8279. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
  8280. +static void aufs_sync_page(struct page *page)
  8281. +{BUG();}
  8282. +#else
  8283. +static int aufs_sync_page(struct page *page)
  8284. +{BUG(); return 0;}
  8285. +#endif
  8286. +
  8287. +#if 0 // comment
  8288. +static int aufs_writepages(struct address_space *mapping,
  8289. + struct writeback_control *wbc)
  8290. +{BUG();return 0;}
  8291. +static int aufs_readpages(struct file *filp, struct address_space *mapping,
  8292. + struct list_head *pages, unsigned nr_pages)
  8293. +{BUG();return 0;}
  8294. +static sector_t aufs_bmap(struct address_space *mapping, sector_t block)
  8295. +{BUG();return 0;}
  8296. +#endif
  8297. +
  8298. +static int aufs_set_page_dirty(struct page *page)
  8299. +{BUG();return 0;}
  8300. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
  8301. +static void aufs_invalidatepage (struct page *page, unsigned long offset)
  8302. +{BUG();}
  8303. +#else
  8304. +static int aufs_invalidatepage (struct page *page, unsigned long offset)
  8305. +{BUG(); return 0;}
  8306. +#endif
  8307. +static int aufs_releasepage (struct page *page, gfp_t gfp)
  8308. +{BUG();return 0;}
  8309. +static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
  8310. + const struct iovec *iov, loff_t offset,
  8311. + unsigned long nr_segs)
  8312. +{BUG();return 0;}
  8313. +static struct page* aufs_get_xip_page(struct address_space *mapping,
  8314. + sector_t offset, int create)
  8315. +{BUG();return NULL;}
  8316. +//static int aufs_migratepage (struct page *newpage, struct page *page)
  8317. +//{BUG();return 0;}
  8318. +#endif
  8319. +
  8320. +#if 0 // comment
  8321. +struct address_space {
  8322. + struct inode *host; /* owner: inode, block_device */
  8323. + struct radix_tree_root page_tree; /* radix tree of all pages */
  8324. + rwlock_t tree_lock; /* and rwlock protecting it */
  8325. + unsigned int i_mmap_writable;/* count VM_SHARED mappings */
  8326. + struct prio_tree_root i_mmap; /* tree of private and shared mappings */
  8327. + struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
  8328. + spinlock_t i_mmap_lock; /* protect tree, count, list */
  8329. + unsigned int truncate_count; /* Cover race condition with truncate */
  8330. + unsigned long nrpages; /* number of total pages */
  8331. + pgoff_t writeback_index;/* writeback starts here */
  8332. + struct address_space_operations *a_ops; /* methods */
  8333. + unsigned long flags; /* error bits/gfp mask */
  8334. + struct backing_dev_info *backing_dev_info; /* device readahead, etc */
  8335. + spinlock_t private_lock; /* for use by the address_space */
  8336. + struct list_head private_list; /* ditto */
  8337. + struct address_space *assoc_mapping; /* ditto */
  8338. +} __attribute__((aligned(sizeof(long))));
  8339. +
  8340. +struct address_space_operations {
  8341. + int (*writepage)(struct page *page, struct writeback_control *wbc);
  8342. + int (*readpage)(struct file *, struct page *);
  8343. + void (*sync_page)(struct page *);
  8344. +
  8345. + /* Write back some dirty pages from this mapping. */
  8346. + int (*writepages)(struct address_space *, struct writeback_control *);
  8347. +
  8348. + /* Set a page dirty. Return true if this dirtied it */
  8349. + int (*set_page_dirty)(struct page *page);
  8350. +
  8351. + int (*readpages)(struct file *filp, struct address_space *mapping,
  8352. + struct list_head *pages, unsigned nr_pages);
  8353. +
  8354. + /*
  8355. + * ext3 requires that a successful prepare_write() call be followed
  8356. + * by a commit_write() call - they must be balanced
  8357. + */
  8358. + int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
  8359. + int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
  8360. + /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
  8361. + sector_t (*bmap)(struct address_space *, sector_t);
  8362. + void (*invalidatepage) (struct page *, unsigned long);
  8363. + int (*releasepage) (struct page *, gfp_t);
  8364. + ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
  8365. + loff_t offset, unsigned long nr_segs);
  8366. + struct page* (*get_xip_page)(struct address_space *, sector_t,
  8367. + int);
  8368. + /* migrate the contents of a page to the specified target */
  8369. + int (*migratepage) (struct page *, struct page *);
  8370. +};
  8371. +#endif
  8372. +
  8373. +struct address_space_operations aufs_aop = {
  8374. + .readpage = aufs_readpage,
  8375. +#ifdef CONFIG_AUFS_DEBUG
  8376. + .writepage = aufs_writepage,
  8377. + .sync_page = aufs_sync_page,
  8378. + //.writepages = aufs_writepages,
  8379. + .set_page_dirty = aufs_set_page_dirty,
  8380. + //.readpages = aufs_readpages,
  8381. + .prepare_write = aufs_prepare_write,
  8382. + .commit_write = aufs_commit_write,
  8383. + //.bmap = aufs_bmap,
  8384. + .invalidatepage = aufs_invalidatepage,
  8385. + .releasepage = aufs_releasepage,
  8386. + .direct_IO = aufs_direct_IO,
  8387. + .get_xip_page = aufs_get_xip_page,
  8388. + //.migratepage = aufs_migratepage
  8389. +#endif
  8390. +};
  8391. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/file.h linux-2.6.22.1/fs/aufs/file.h
  8392. --- linux-2.6.22.1.oorig/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
  8393. +++ linux-2.6.22.1/fs/aufs/file.h 2007-07-24 14:17:46.000000000 +0200
  8394. @@ -0,0 +1,140 @@
  8395. +/*
  8396. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  8397. + *
  8398. + * This program, aufs is free software; you can redistribute it and/or modify
  8399. + * it under the terms of the GNU General Public License as published by
  8400. + * the Free Software Foundation; either version 2 of the License, or
  8401. + * (at your option) any later version.
  8402. + *
  8403. + * This program is distributed in the hope that it will be useful,
  8404. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8405. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8406. + * GNU General Public License for more details.
  8407. + *
  8408. + * You should have received a copy of the GNU General Public License
  8409. + * along with this program; if not, write to the Free Software
  8410. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8411. + */
  8412. +
  8413. +/* $Id: file.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
  8414. +
  8415. +#ifndef __AUFS_FILE_H__
  8416. +#define __AUFS_FILE_H__
  8417. +
  8418. +#ifdef __KERNEL__
  8419. +
  8420. +#include <linux/file.h>
  8421. +#include <linux/fs.h>
  8422. +#include <linux/version.h>
  8423. +#include <linux/aufs_type.h>
  8424. +#include "misc.h"
  8425. +
  8426. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  8427. +// SEEK_xxx are defined in linux/fs.h
  8428. +#else
  8429. +enum {SEEK_SET, SEEK_CUR, SEEK_END};
  8430. +#endif
  8431. +
  8432. +/* ---------------------------------------------------------------------- */
  8433. +
  8434. +struct aufs_branch;
  8435. +struct aufs_hfile {
  8436. + struct file *hf_file;
  8437. + struct aufs_branch *hf_br;
  8438. +};
  8439. +
  8440. +struct aufs_vdir;
  8441. +struct aufs_finfo {
  8442. + atomic_t fi_generation;
  8443. +
  8444. + struct aufs_rwsem fi_rwsem;
  8445. + struct aufs_hfile *fi_hfile;
  8446. + aufs_bindex_t fi_bstart, fi_bend;
  8447. +
  8448. + union {
  8449. + struct vm_operations_struct *fi_h_vm_ops;
  8450. + struct aufs_vdir *fi_vdir_cache;
  8451. + };
  8452. +};
  8453. +
  8454. +/* ---------------------------------------------------------------------- */
  8455. +
  8456. +/* file.c */
  8457. +extern struct address_space_operations aufs_aop;
  8458. +unsigned int au_file_roflags(unsigned int flags);
  8459. +struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex,
  8460. + int flags);
  8461. +int au_do_open(struct inode *inode, struct file *file,
  8462. + int (*open)(struct file *file, int flags));
  8463. +int au_reopen_nondir(struct file *file);
  8464. +int au_ready_to_write(struct file *file, loff_t len);
  8465. +int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
  8466. + int wlock, int locked);
  8467. +
  8468. +/* f_op.c */
  8469. +extern struct file_operations aufs_file_fop;
  8470. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  8471. +int aufs_flush(struct file *file, fl_owner_t id);
  8472. +#else
  8473. +int aufs_flush(struct file *file);
  8474. +#endif
  8475. +
  8476. +/* finfo.c */
  8477. +struct aufs_finfo *ftofi(struct file *file);
  8478. +aufs_bindex_t fbstart(struct file *file);
  8479. +aufs_bindex_t fbend(struct file *file);
  8480. +struct aufs_vdir *fvdir_cache(struct file *file);
  8481. +struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex);
  8482. +struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex);
  8483. +struct file *au_h_fptr(struct file *file);
  8484. +
  8485. +void set_fbstart(struct file *file, aufs_bindex_t bindex);
  8486. +void set_fbend(struct file *file, aufs_bindex_t bindex);
  8487. +void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache);
  8488. +void au_hfput(struct aufs_hfile *hf);
  8489. +void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *h_file);
  8490. +void au_update_figen(struct file *file);
  8491. +
  8492. +void au_fin_finfo(struct file *file);
  8493. +int au_init_finfo(struct file *file);
  8494. +
  8495. +/* ---------------------------------------------------------------------- */
  8496. +
  8497. +static inline int au_figen(struct file *f)
  8498. +{
  8499. + return atomic_read(&ftofi(f)->fi_generation);
  8500. +}
  8501. +
  8502. +static inline int au_is_mmapped(struct file *f)
  8503. +{
  8504. + return !!(ftofi(f)->fi_h_vm_ops);
  8505. +}
  8506. +
  8507. +/* ---------------------------------------------------------------------- */
  8508. +
  8509. +/*
  8510. + * fi_read_lock, fi_write_lock,
  8511. + * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
  8512. + */
  8513. +SimpleRwsemFuncs(fi, struct file *f, ftofi(f)->fi_rwsem);
  8514. +
  8515. +/* to debug easier, do not make them inlined functions */
  8516. +#define FiMustReadLock(f) do {\
  8517. + SiMustAnyLock((f)->f_dentry->d_sb); \
  8518. + RwMustReadLock(&ftofi(f)->fi_rwsem); \
  8519. +} while (0)
  8520. +
  8521. +#define FiMustWriteLock(f) do { \
  8522. + SiMustAnyLock((f)->f_dentry->d_sb); \
  8523. + RwMustWriteLock(&ftofi(f)->fi_rwsem); \
  8524. +} while (0)
  8525. +
  8526. +#define FiMustAnyLock(f) do { \
  8527. + SiMustAnyLock((f)->f_dentry->d_sb); \
  8528. + RwMustAnyLock(&ftofi(f)->fi_rwsem); \
  8529. +} while (0)
  8530. +
  8531. +#define FiMustNoWaiters(f) RwMustNoWaiters(&ftofi(f)->fi_rwsem)
  8532. +
  8533. +#endif /* __KERNEL__ */
  8534. +#endif /* __AUFS_FILE_H__ */
  8535. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/finfo.c linux-2.6.22.1/fs/aufs/finfo.c
  8536. --- linux-2.6.22.1.oorig/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
  8537. +++ linux-2.6.22.1/fs/aufs/finfo.c 2007-07-24 14:17:46.000000000 +0200
  8538. @@ -0,0 +1,211 @@
  8539. +/*
  8540. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  8541. + *
  8542. + * This program, aufs is free software; you can redistribute it and/or modify
  8543. + * it under the terms of the GNU General Public License as published by
  8544. + * the Free Software Foundation; either version 2 of the License, or
  8545. + * (at your option) any later version.
  8546. + *
  8547. + * This program is distributed in the hope that it will be useful,
  8548. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8549. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8550. + * GNU General Public License for more details.
  8551. + *
  8552. + * You should have received a copy of the GNU General Public License
  8553. + * along with this program; if not, write to the Free Software
  8554. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8555. + */
  8556. +
  8557. +/* $Id: finfo.c,v 1.23 2007/04/30 05:45:21 sfjro Exp $ */
  8558. +
  8559. +#include "aufs.h"
  8560. +
  8561. +struct aufs_finfo *ftofi(struct file *file)
  8562. +{
  8563. + struct aufs_finfo *finfo = file->private_data;
  8564. + DEBUG_ON(!finfo
  8565. + || !finfo->fi_hfile
  8566. + || (0 < finfo->fi_bend
  8567. + && (/* stosi(file->f_dentry->d_sb)->si_bend
  8568. + < finfo->fi_bend
  8569. + || */ finfo->fi_bend < finfo->fi_bstart)));
  8570. + return finfo;
  8571. +}
  8572. +
  8573. +// hard/soft set
  8574. +aufs_bindex_t fbstart(struct file *file)
  8575. +{
  8576. + FiMustAnyLock(file);
  8577. + return ftofi(file)->fi_bstart;
  8578. +}
  8579. +
  8580. +aufs_bindex_t fbend(struct file *file)
  8581. +{
  8582. + FiMustAnyLock(file);
  8583. + return ftofi(file)->fi_bend;
  8584. +}
  8585. +
  8586. +struct aufs_vdir *fvdir_cache(struct file *file)
  8587. +{
  8588. + FiMustAnyLock(file);
  8589. + return ftofi(file)->fi_vdir_cache;
  8590. +}
  8591. +
  8592. +struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex)
  8593. +{
  8594. + struct aufs_finfo *finfo = ftofi(file);
  8595. + struct aufs_hfile *hf;
  8596. +
  8597. + FiMustAnyLock(file);
  8598. + DEBUG_ON(!finfo
  8599. + || finfo->fi_bstart < 0
  8600. + || bindex < finfo->fi_bstart
  8601. + || finfo->fi_bend < bindex);
  8602. + hf = finfo->fi_hfile + bindex;
  8603. + DEBUG_ON(hf->hf_br && br_count(hf->hf_br) <= 0);
  8604. + return hf->hf_br;
  8605. +}
  8606. +
  8607. +struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex)
  8608. +{
  8609. + struct aufs_finfo *finfo = ftofi(file);
  8610. + struct aufs_hfile *hf;
  8611. +
  8612. + FiMustAnyLock(file);
  8613. + DEBUG_ON(!finfo
  8614. + || finfo->fi_bstart < 0
  8615. + || bindex < finfo->fi_bstart
  8616. + || finfo->fi_bend < bindex);
  8617. + hf = finfo->fi_hfile + bindex;
  8618. + DEBUG_ON(hf->hf_file
  8619. + && file_count(hf->hf_file) <= 0
  8620. + && br_count(hf->hf_br) <= 0);
  8621. + return hf->hf_file;
  8622. +}
  8623. +
  8624. +struct file *au_h_fptr(struct file *file)
  8625. +{
  8626. + return au_h_fptr_i(file, fbstart(file));
  8627. +}
  8628. +
  8629. +void set_fbstart(struct file *file, aufs_bindex_t bindex)
  8630. +{
  8631. + FiMustWriteLock(file);
  8632. + DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex);
  8633. + ftofi(file)->fi_bstart = bindex;
  8634. +}
  8635. +
  8636. +void set_fbend(struct file *file, aufs_bindex_t bindex)
  8637. +{
  8638. + FiMustWriteLock(file);
  8639. + DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex
  8640. + || bindex < fbstart(file));
  8641. + ftofi(file)->fi_bend = bindex;
  8642. +}
  8643. +
  8644. +void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache)
  8645. +{
  8646. + FiMustWriteLock(file);
  8647. + DEBUG_ON(!S_ISDIR(file->f_dentry->d_inode->i_mode)
  8648. + || (ftofi(file)->fi_vdir_cache && vdir_cache));
  8649. + ftofi(file)->fi_vdir_cache = vdir_cache;
  8650. +}
  8651. +
  8652. +void au_hfput(struct aufs_hfile *hf)
  8653. +{
  8654. + fput(hf->hf_file);
  8655. + hf->hf_file = NULL;
  8656. + DEBUG_ON(!hf->hf_br);
  8657. + br_put(hf->hf_br);
  8658. + hf->hf_br = NULL;
  8659. +}
  8660. +
  8661. +void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
  8662. +{
  8663. + struct aufs_finfo *finfo = ftofi(file);
  8664. + struct aufs_hfile *hf;
  8665. +
  8666. + FiMustWriteLock(file);
  8667. + DEBUG_ON(!finfo
  8668. + || finfo->fi_bstart < 0
  8669. + || bindex < finfo->fi_bstart
  8670. + || finfo->fi_bend < bindex);
  8671. + DEBUG_ON(val && file_count(val) <= 0);
  8672. + hf = finfo->fi_hfile + bindex;
  8673. + DEBUG_ON(val && hf->hf_file);
  8674. + if (hf->hf_file)
  8675. + au_hfput(hf);
  8676. + if (val) {
  8677. + hf->hf_file = val;
  8678. + hf->hf_br = stobr(file->f_dentry->d_sb, bindex);
  8679. + }
  8680. +}
  8681. +
  8682. +void au_update_figen(struct file *file)
  8683. +{
  8684. + atomic_set(&ftofi(file)->fi_generation, au_digen(file->f_dentry));
  8685. +}
  8686. +
  8687. +void au_fin_finfo(struct file *file)
  8688. +{
  8689. + struct aufs_finfo *finfo;
  8690. + struct dentry *dentry;
  8691. + aufs_bindex_t bindex, bend;
  8692. +
  8693. + dentry = file->f_dentry;
  8694. + LKTRTrace("%.*s\n", DLNPair(dentry));
  8695. + SiMustAnyLock(dentry->d_sb);
  8696. +
  8697. + fi_write_lock(file);
  8698. + bend = fbend(file);
  8699. + bindex = fbstart(file);
  8700. + if (bindex >= 0)
  8701. + for (; bindex <= bend; bindex++)
  8702. + set_h_fptr(file, bindex, NULL);
  8703. +
  8704. + finfo = ftofi(file);
  8705. +#ifdef CONFIG_AUFS_DEBUG
  8706. + if (finfo->fi_bstart >= 0) {
  8707. + bend = fbend(file);
  8708. + for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
  8709. + struct aufs_hfile *hf;
  8710. + hf = finfo->fi_hfile + bindex;
  8711. + DEBUG_ON(hf->hf_file || hf->hf_br);
  8712. + }
  8713. + }
  8714. +#endif
  8715. +
  8716. + kfree(finfo->fi_hfile);
  8717. + fi_write_unlock(file);
  8718. + cache_free_finfo(finfo);
  8719. + //file->private_data = NULL;
  8720. +}
  8721. +
  8722. +int au_init_finfo(struct file *file)
  8723. +{
  8724. + struct aufs_finfo *finfo;
  8725. + struct dentry *dentry;
  8726. +
  8727. + dentry = file->f_dentry;
  8728. + LKTRTrace("%.*s\n", DLNPair(dentry));
  8729. + DEBUG_ON(!dentry->d_inode);
  8730. +
  8731. + finfo = cache_alloc_finfo();
  8732. + if (finfo) {
  8733. + finfo->fi_hfile = kcalloc(sbend(dentry->d_sb) + 1,
  8734. + sizeof(*finfo->fi_hfile), GFP_KERNEL);
  8735. + if (finfo->fi_hfile) {
  8736. + rw_init_wlock(&finfo->fi_rwsem);
  8737. + finfo->fi_bstart = -1;
  8738. + finfo->fi_bend = -1;
  8739. + atomic_set(&finfo->fi_generation, au_digen(dentry));
  8740. +
  8741. + file->private_data = finfo;
  8742. + return 0; /* success */
  8743. + }
  8744. + cache_free_finfo(finfo);
  8745. + }
  8746. +
  8747. + TraceErr(-ENOMEM);
  8748. + return -ENOMEM;
  8749. +}
  8750. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/hinotify.c linux-2.6.22.1/fs/aufs/hinotify.c
  8751. --- linux-2.6.22.1.oorig/fs/aufs/hinotify.c 1970-01-01 01:00:00.000000000 +0100
  8752. +++ linux-2.6.22.1/fs/aufs/hinotify.c 2007-07-24 14:17:46.000000000 +0200
  8753. @@ -0,0 +1,536 @@
  8754. +/*
  8755. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  8756. + *
  8757. + * This program, aufs is free software; you can redistribute it and/or modify
  8758. + * it under the terms of the GNU General Public License as published by
  8759. + * the Free Software Foundation; either version 2 of the License, or
  8760. + * (at your option) any later version.
  8761. + *
  8762. + * This program is distributed in the hope that it will be useful,
  8763. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8764. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8765. + * GNU General Public License for more details.
  8766. + *
  8767. + * You should have received a copy of the GNU General Public License
  8768. + * along with this program; if not, write to the Free Software
  8769. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8770. + */
  8771. +
  8772. +/* $Id: hinotify.c,v 1.19 2007/05/14 03:39:21 sfjro Exp $ */
  8773. +
  8774. +#include "aufs.h"
  8775. +
  8776. +static struct inotify_handle *in_handle;
  8777. +static const __u32 in_mask = (IN_MOVE | IN_DELETE | IN_CREATE /* | IN_ACCESS */
  8778. + | IN_MODIFY | IN_ATTRIB
  8779. + | IN_DELETE_SELF | IN_MOVE_SELF);
  8780. +
  8781. +int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
  8782. + struct inode *hidden_inode)
  8783. +{
  8784. + int err;
  8785. + struct aufs_hinotify *hin;
  8786. + s32 wd;
  8787. +
  8788. + LKTRTrace("i%lu, hi%lu\n", inode->i_ino, hidden_inode->i_ino);
  8789. +
  8790. + err = -ENOMEM;
  8791. + hin = cache_alloc_hinotify();
  8792. + if (hin) {
  8793. + DEBUG_ON(hinode->hi_notify);
  8794. + hinode->hi_notify = hin;
  8795. + hin->hin_aufs_inode = inode;
  8796. + inotify_init_watch(&hin->hin_watch);
  8797. + wd = inotify_add_watch(in_handle, &hin->hin_watch, hidden_inode,
  8798. + in_mask);
  8799. + if (wd >= 0)
  8800. + return 0; /* success */
  8801. +
  8802. + err = wd;
  8803. + put_inotify_watch(&hin->hin_watch);
  8804. + cache_free_hinotify(hin);
  8805. + hinode->hi_notify = NULL;
  8806. + }
  8807. +
  8808. + TraceErr(err);
  8809. + return err;
  8810. +}
  8811. +
  8812. +void do_free_hinotify(struct aufs_hinode *hinode)
  8813. +{
  8814. + int err;
  8815. + struct aufs_hinotify *hin;
  8816. +
  8817. + TraceEnter();
  8818. +
  8819. + hin = hinode->hi_notify;
  8820. + if (hin) {
  8821. + err = 0;
  8822. + if (atomic_read(&hin->hin_watch.count))
  8823. + err = inotify_rm_watch(in_handle, &hin->hin_watch);
  8824. +
  8825. + if (!err) {
  8826. + cache_free_hinotify(hin);
  8827. + hinode->hi_notify = NULL;
  8828. + } else
  8829. + IOErr1("failed inotify_rm_watch() %d\n", err);
  8830. + }
  8831. +}
  8832. +
  8833. +/* ---------------------------------------------------------------------- */
  8834. +
  8835. +static void ctl_hinotify(struct aufs_hinode *hinode, const __u32 mask)
  8836. +{
  8837. + struct inode *hi;
  8838. + struct inotify_watch *watch;
  8839. +
  8840. + hi = hinode->hi_inode;
  8841. + LKTRTrace("hi%lu, sb %p, 0x%x\n", hi->i_ino, hi->i_sb, mask);
  8842. + if (0 && !strcmp(current->comm, "link"))
  8843. + dump_stack();
  8844. + IMustLock(hi);
  8845. + if (!hinode->hi_notify)
  8846. + return;
  8847. +
  8848. + watch = &hinode->hi_notify->hin_watch;
  8849. +#if 0
  8850. + {
  8851. + u32 wd;
  8852. + wd = inotify_find_update_watch(in_handle, hi, mask);
  8853. + TraceErr(wd);
  8854. + // ignore an err;
  8855. + }
  8856. +#else
  8857. + watch->mask = mask;
  8858. + smp_mb();
  8859. +#endif
  8860. + LKTRTrace("watch %p, mask %u\n", watch, watch->mask);
  8861. +}
  8862. +
  8863. +#define suspend_hinotify(hi) ctl_hinotify(hi, 0)
  8864. +#define resume_hinotify(hi) ctl_hinotify(hi, in_mask)
  8865. +
  8866. +void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
  8867. + unsigned int lsc)
  8868. +{
  8869. + struct aufs_hinode *hinode;
  8870. +
  8871. + LKTRTrace("i%lu, b%d, lsc %d\n", dir->i_ino, bindex, lsc);
  8872. + DEBUG_ON(!S_ISDIR(dir->i_mode));
  8873. + hinode = itoii(dir)->ii_hinode + bindex;
  8874. + DEBUG_ON(h_dir != hinode->hi_inode);
  8875. +
  8876. + hi_lock(h_dir, lsc);
  8877. + if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
  8878. + suspend_hinotify(hinode);
  8879. +}
  8880. +
  8881. +void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
  8882. +{
  8883. + struct aufs_hinode *hinode;
  8884. +
  8885. + LKTRTrace("i%lu, b%d\n", dir->i_ino, bindex);
  8886. + DEBUG_ON(!S_ISDIR(dir->i_mode));
  8887. + hinode = itoii(dir)->ii_hinode + bindex;
  8888. + DEBUG_ON(h_dir != hinode->hi_inode);
  8889. +
  8890. + if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
  8891. + resume_hinotify(hinode);
  8892. + i_unlock(h_dir);
  8893. +}
  8894. +
  8895. +void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
  8896. + aufs_bindex_t bindex, int issamedir)
  8897. +{
  8898. + struct aufs_hinode *hinode;
  8899. +
  8900. + LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
  8901. +
  8902. + vfsub_lock_rename(h_parents[0], h_parents[1]);
  8903. + hinode = itoii(dirs[0])->ii_hinode + bindex;
  8904. + DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
  8905. + suspend_hinotify(hinode);
  8906. + if (issamedir)
  8907. + return;
  8908. + hinode = itoii(dirs[1])->ii_hinode + bindex;
  8909. + DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
  8910. + suspend_hinotify(hinode);
  8911. +}
  8912. +
  8913. +void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
  8914. + aufs_bindex_t bindex, int issamedir)
  8915. +{
  8916. + struct aufs_hinode *hinode;
  8917. +
  8918. + LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
  8919. +
  8920. + hinode = itoii(dirs[0])->ii_hinode + bindex;
  8921. + DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
  8922. + resume_hinotify(hinode);
  8923. + if (!issamedir) {
  8924. + hinode = itoii(dirs[1])->ii_hinode + bindex;
  8925. + DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
  8926. + resume_hinotify(hinode);
  8927. + }
  8928. + vfsub_unlock_rename(h_parents[0], h_parents[1]);
  8929. +}
  8930. +
  8931. +void au_reset_hinotify(struct inode *inode, unsigned int flags)
  8932. +{
  8933. + aufs_bindex_t bindex, bend;
  8934. + struct inode *hi;
  8935. +
  8936. + LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags);
  8937. +
  8938. + bend = ibend(inode);
  8939. + for (bindex = ibstart(inode); bindex <= bend; bindex++) {
  8940. + hi = au_h_iptr_i(inode, bindex);
  8941. + if (hi) {
  8942. + //hi_lock(hi, AUFS_LSC_H_CHILD);
  8943. + igrab(hi);
  8944. + set_h_iptr(inode, bindex, NULL, 0);
  8945. + set_h_iptr(inode, bindex, igrab(hi), flags);
  8946. + iput(hi);
  8947. + //i_unlock(hi);
  8948. + }
  8949. + }
  8950. +}
  8951. +
  8952. +/* ---------------------------------------------------------------------- */
  8953. +
  8954. +#ifdef CONFIG_AUFS_DEBUG
  8955. +static char *in_name(u32 mask)
  8956. +{
  8957. +#define test_ret(flag) if (mask & flag) return #flag;
  8958. + test_ret(IN_ACCESS);
  8959. + test_ret(IN_MODIFY);
  8960. + test_ret(IN_ATTRIB);
  8961. + test_ret(IN_CLOSE_WRITE);
  8962. + test_ret(IN_CLOSE_NOWRITE);
  8963. + test_ret(IN_OPEN);
  8964. + test_ret(IN_MOVED_FROM);
  8965. + test_ret(IN_MOVED_TO);
  8966. + test_ret(IN_CREATE);
  8967. + test_ret(IN_DELETE);
  8968. + test_ret(IN_DELETE_SELF);
  8969. + test_ret(IN_MOVE_SELF);
  8970. + test_ret(IN_UNMOUNT);
  8971. + test_ret(IN_Q_OVERFLOW);
  8972. + test_ret(IN_IGNORED);
  8973. + return "";
  8974. +#undef test_ret
  8975. +}
  8976. +#else
  8977. +#define in_name(m) "??"
  8978. +#endif
  8979. +
  8980. +static int dec_gen_by_name(struct inode *dir, const char *_name, u32 mask)
  8981. +{
  8982. + int err;
  8983. + struct dentry *parent, *child;
  8984. + struct inode *inode;
  8985. + struct qstr *dname;
  8986. + char *name = (void*)_name;
  8987. + unsigned int len;
  8988. +
  8989. + LKTRTrace("i%lu, %s, 0x%x %s\n",
  8990. + dir->i_ino, name, mask, in_name(mask));
  8991. +
  8992. + err = -1;
  8993. + parent = d_find_alias(dir);
  8994. + if (unlikely(!parent))
  8995. + goto out;
  8996. +
  8997. +#if 0
  8998. + if (unlikely(!memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
  8999. + name += AUFS_WH_PFX_LEN;
  9000. +#endif
  9001. + len = strlen(name);
  9002. + spin_lock(&dcache_lock);
  9003. + list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
  9004. + dname = &child->d_name;
  9005. + if (len == dname->len && !memcmp(dname->name, name, len)) {
  9006. + au_digen_dec(child);
  9007. +#if 1
  9008. + //todo: why both are needed
  9009. + if (mask & IN_MOVE) {
  9010. + spin_lock(&child->d_lock);
  9011. + __d_drop(child);
  9012. + spin_unlock(&child->d_lock);
  9013. + }
  9014. +#endif
  9015. +
  9016. + inode = child->d_inode;
  9017. + if (inode)
  9018. + au_iigen_dec(inode);
  9019. + err = !!inode;
  9020. +
  9021. + // todo: the i_nlink of newly created name by link(2)
  9022. + // should be updated
  9023. + // todo: some nfs dentry doesn't notified at deleteing
  9024. + break;
  9025. + }
  9026. + }
  9027. + spin_unlock(&dcache_lock);
  9028. + dput(parent);
  9029. +
  9030. + out:
  9031. + TraceErr(err);
  9032. + return err;
  9033. +}
  9034. +
  9035. +struct postproc_args {
  9036. + struct inode *h_dir, *dir, *h_child_inode;
  9037. + char *h_child_name;
  9038. + u32 mask;
  9039. +};
  9040. +
  9041. +static void dec_gen_by_ino(struct postproc_args *a)
  9042. +{
  9043. + struct super_block *sb;
  9044. + aufs_bindex_t bindex, bend, bfound;
  9045. + struct xino xino;
  9046. + struct inode *cinode;
  9047. +
  9048. + TraceEnter();
  9049. +
  9050. + sb = a->dir->i_sb;
  9051. + DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
  9052. +
  9053. + bfound = -1;
  9054. + bend = ibend(a->dir);
  9055. + for (bindex = ibstart(a->dir); bfound == -1 && bindex <= bend; bindex++)
  9056. + if (au_h_iptr_i(a->dir, bindex) == a->h_dir)
  9057. + bfound = bindex;
  9058. + if (bfound < 0)
  9059. + return;
  9060. +
  9061. + bindex = find_brindex(sb, itoii(a->dir)->ii_hinode[bfound + 0].hi_id);
  9062. + if (bindex < 0)
  9063. + return;
  9064. + if (unlikely(xino_read(sb, bindex, a->h_child_inode->i_ino, &xino)))
  9065. + return;
  9066. + cinode = NULL;
  9067. + if (xino.ino)
  9068. + cinode = ilookup(sb, xino.ino);
  9069. + if (cinode) {
  9070. +#if 1
  9071. + if (1 || a->mask & IN_MOVE) {
  9072. + struct dentry *child;
  9073. + spin_lock(&dcache_lock);
  9074. + list_for_each_entry(child, &cinode->i_dentry, d_alias)
  9075. + au_digen_dec(child);
  9076. + spin_unlock(&dcache_lock);
  9077. + }
  9078. +#endif
  9079. + au_iigen_dec(cinode);
  9080. + iput(cinode);
  9081. + }
  9082. +}
  9083. +
  9084. +static void reset_ino(struct postproc_args *a)
  9085. +{
  9086. + aufs_bindex_t bindex, bend;
  9087. + struct super_block *sb;
  9088. + struct inode *h_dir;
  9089. +
  9090. + sb = a->dir->i_sb;
  9091. + bend = ibend(a->dir);
  9092. + for (bindex = ibstart(a->dir); bindex <= bend; bindex++) {
  9093. + h_dir = au_h_iptr_i(a->dir, bindex);
  9094. + if (h_dir && h_dir != a->h_dir)
  9095. + xino_write0(sb, bindex, h_dir->i_ino);
  9096. + /* ignore this error */
  9097. + }
  9098. +}
  9099. +
  9100. +static void postproc(void *args)
  9101. +{
  9102. + struct postproc_args *a = args;
  9103. + struct super_block *sb;
  9104. + struct aufs_vdir *vdir;
  9105. +
  9106. + //au_debug_on();
  9107. + LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
  9108. + a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
  9109. + a->h_child_inode ? a->h_child_inode->i_ino : 0);
  9110. + DEBUG_ON(!a->dir);
  9111. +#if 0//def ForceInotify
  9112. + Dbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
  9113. + a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
  9114. + a->h_child_inode ? a->h_child_inode->i_ino : 0);
  9115. +#endif
  9116. +
  9117. + i_lock(a->dir);
  9118. + sb = a->dir->i_sb;
  9119. + si_read_lock(sb); // consider write_lock
  9120. + ii_write_lock_parent(a->dir);
  9121. +
  9122. + /* make dir entries obsolete */
  9123. + vdir = ivdir(a->dir);
  9124. + if (vdir)
  9125. + vdir->vd_jiffy = 0;
  9126. + a->dir->i_version++;
  9127. +
  9128. + /*
  9129. + * special handling root directory,
  9130. + * sine d_revalidate may not be called later.
  9131. + * main purpose is maintaining i_nlink.
  9132. + */
  9133. + if (unlikely(a->dir->i_ino == AUFS_ROOT_INO))
  9134. + au_cpup_attr_all(a->dir);
  9135. +
  9136. + if (a->h_child_inode && au_flag_test(sb, AuFlag_XINO))
  9137. + dec_gen_by_ino(a);
  9138. + else if (a->mask & (IN_MOVE_SELF | IN_DELETE_SELF))
  9139. + reset_ino(a);
  9140. +
  9141. + ii_write_unlock(a->dir);
  9142. + si_read_unlock(sb);
  9143. + i_unlock(a->dir);
  9144. +
  9145. + au_mntput(a->dir->i_sb);
  9146. + iput(a->h_child_inode);
  9147. + iput(a->h_dir);
  9148. + iput(a->dir);
  9149. +#if 0
  9150. + if (atomic_dec_and_test(&stosi(sb)->si_hinotify))
  9151. + wake_up_all(&stosi(sb)->si_hinotify_wq);
  9152. +#endif
  9153. + kfree(a);
  9154. + //au_debug_off();
  9155. +}
  9156. +
  9157. +static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask,
  9158. + u32 cookie, const char *h_child_name,
  9159. + struct inode *h_child_inode)
  9160. +{
  9161. + struct aufs_hinotify *hinotify;
  9162. + struct postproc_args *args;
  9163. + int len;
  9164. + char *p;
  9165. + struct inode *dir;
  9166. + //static DECLARE_WAIT_QUEUE_HEAD(wq);
  9167. +
  9168. + //au_debug_on();
  9169. + LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
  9170. + watch->inode->i_ino, wd, mask, in_name(mask), cookie,
  9171. + h_child_name ? h_child_name : "",
  9172. + h_child_inode ? h_child_inode->i_ino : 0);
  9173. + //au_debug_off();
  9174. + //IMustLock(h_dir);
  9175. +#if 0 //defined(ForceInotify) || defined(DbgInotify)
  9176. + Dbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
  9177. + watch->inode->i_ino, wd, mask, in_name(mask), cookie,
  9178. + h_child_name ? h_child_name : "",
  9179. + h_child_inode ? h_child_inode->i_ino : 0);
  9180. +#endif
  9181. + /* if IN_UNMOUNT happens, there must be another bug */
  9182. + if (mask & (IN_IGNORED | IN_UNMOUNT)) {
  9183. + put_inotify_watch(watch);
  9184. + return;
  9185. + }
  9186. +
  9187. + switch (mask & IN_ALL_EVENTS) {
  9188. + case IN_MODIFY:
  9189. + case IN_ATTRIB:
  9190. + if (h_child_name)
  9191. + return;
  9192. + break;
  9193. +
  9194. + case IN_MOVED_FROM:
  9195. + case IN_MOVED_TO:
  9196. + case IN_CREATE:
  9197. + DEBUG_ON(!h_child_name || !h_child_inode);
  9198. + break;
  9199. + case IN_DELETE:
  9200. + /*
  9201. + * aufs never be able to get this child inode.
  9202. + * revalidation should be in d_revalide()
  9203. + * by checking i_nlink, i_generation or d_unhashed().
  9204. + */
  9205. + DEBUG_ON(!h_child_name);
  9206. + break;
  9207. +
  9208. + case IN_DELETE_SELF:
  9209. + case IN_MOVE_SELF:
  9210. + DEBUG_ON(h_child_name || h_child_inode);
  9211. + break;
  9212. +
  9213. + case IN_ACCESS:
  9214. + default:
  9215. + DEBUG_ON(1);
  9216. + }
  9217. +
  9218. +#ifdef DbgInotify
  9219. + WARN_ON(1);
  9220. +#endif
  9221. +
  9222. + /* iput() will be called in postproc() */
  9223. + hinotify = container_of(watch, struct aufs_hinotify, hin_watch);
  9224. + DEBUG_ON(!hinotify || !hinotify->hin_aufs_inode);
  9225. + dir = hinotify->hin_aufs_inode;
  9226. +
  9227. + /* force re-lookup in next d_revalidate() */
  9228. + if (dir->i_ino != AUFS_ROOT_INO)
  9229. + au_iigen_dec(dir);
  9230. + len = 0;
  9231. + if (h_child_name && dec_gen_by_name(dir, h_child_name, mask))
  9232. + len = strlen(h_child_name);
  9233. +
  9234. + //wait_event(wq, (args = kmalloc(sizeof(*args), GFP_KERNEL)));
  9235. + args = kmalloc(sizeof(*args) + len + 1, GFP_KERNEL);
  9236. + if (unlikely(!args)) {
  9237. + Err("no memory\n");
  9238. + return;
  9239. + }
  9240. + args->mask = mask;
  9241. + args->dir = igrab(dir);
  9242. + args->h_dir = igrab(watch->inode);
  9243. + args->h_child_inode = NULL;
  9244. + if (len) {
  9245. + if (h_child_inode)
  9246. + args->h_child_inode = igrab(h_child_inode);
  9247. + p = (void*)args;
  9248. + args->h_child_name = p + sizeof(*args);
  9249. + memcpy(args->h_child_name, h_child_name, len + 1);
  9250. + }
  9251. + //atomic_inc(&stosi(args->dir->i_sb)->si_hinotify);
  9252. + /* prohibit umount */
  9253. + au_mntget(args->dir->i_sb);
  9254. + au_wkq_nowait(postproc, args, /*dlgt*/0);
  9255. +}
  9256. +
  9257. +#if 0
  9258. +void hinotify_flush(struct super_block *sb)
  9259. +{
  9260. + atomic_t *p = &stosi(sb)->si_hinotify;
  9261. + wait_event(stosi(sb)->si_hinotify_wq, !atomic_read(p));
  9262. +}
  9263. +#endif
  9264. +
  9265. +static void aufs_inotify_destroy(struct inotify_watch *watch)
  9266. +{
  9267. + return;
  9268. +}
  9269. +
  9270. +static struct inotify_operations aufs_inotify_ops = {
  9271. + .handle_event = aufs_inotify,
  9272. + .destroy_watch = aufs_inotify_destroy
  9273. +};
  9274. +
  9275. +/* ---------------------------------------------------------------------- */
  9276. +
  9277. +int __init au_inotify_init(void)
  9278. +{
  9279. + in_handle = inotify_init(&aufs_inotify_ops);
  9280. + if (!IS_ERR(in_handle))
  9281. + return 0;
  9282. + TraceErrPtr(in_handle);
  9283. + return PTR_ERR(in_handle);
  9284. +}
  9285. +
  9286. +void au_inotify_fin(void)
  9287. +{
  9288. + inotify_destroy(in_handle);
  9289. +}
  9290. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op.c linux-2.6.22.1/fs/aufs/i_op.c
  9291. --- linux-2.6.22.1.oorig/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
  9292. +++ linux-2.6.22.1/fs/aufs/i_op.c 2007-07-24 14:17:46.000000000 +0200
  9293. @@ -0,0 +1,641 @@
  9294. +/*
  9295. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  9296. + *
  9297. + * This program, aufs is free software; you can redistribute it and/or modify
  9298. + * it under the terms of the GNU General Public License as published by
  9299. + * the Free Software Foundation; either version 2 of the License, or
  9300. + * (at your option) any later version.
  9301. + *
  9302. + * This program is distributed in the hope that it will be useful,
  9303. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9304. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9305. + * GNU General Public License for more details.
  9306. + *
  9307. + * You should have received a copy of the GNU General Public License
  9308. + * along with this program; if not, write to the Free Software
  9309. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  9310. + */
  9311. +
  9312. +/* $Id: i_op.c,v 1.30 2007/04/23 00:55:05 sfjro Exp $ */
  9313. +
  9314. +//#include <linux/fs.h>
  9315. +//#include <linux/namei.h>
  9316. +#include <linux/security.h>
  9317. +#include <asm/uaccess.h>
  9318. +#include "aufs.h"
  9319. +
  9320. +#ifdef CONFIG_AUFS_DLGT
  9321. +struct security_inode_permission_args {
  9322. + int *errp;
  9323. + struct inode *h_inode;
  9324. + int mask;
  9325. + struct nameidata *fake_nd;
  9326. +};
  9327. +
  9328. +static void call_security_inode_permission(void *args)
  9329. +{
  9330. + struct security_inode_permission_args *a = args;
  9331. + LKTRTrace("fsuid %d\n", current->fsuid);
  9332. + *a->errp = security_inode_permission(a->h_inode, a->mask, a->fake_nd);
  9333. +}
  9334. +#endif
  9335. +
  9336. +static int hidden_permission(struct inode *hidden_inode, int mask,
  9337. + struct nameidata *fake_nd, int brperm, int dlgt)
  9338. +{
  9339. + int err, submask;
  9340. + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
  9341. +
  9342. + LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
  9343. + hidden_inode->i_ino, mask, brperm);
  9344. +
  9345. + err = -EACCES;
  9346. + if (unlikely(write_mask && IS_IMMUTABLE(hidden_inode)))
  9347. + goto out;
  9348. +
  9349. + /* skip hidden fs test in the case of write to ro branch */
  9350. + submask = mask & ~MAY_APPEND;
  9351. + if (unlikely((write_mask && !br_writable(brperm))
  9352. + || !hidden_inode->i_op
  9353. + || !hidden_inode->i_op->permission)) {
  9354. + //LKTRLabel(generic_permission);
  9355. + err = generic_permission(hidden_inode, submask, NULL);
  9356. + } else {
  9357. + //LKTRLabel(h_inode->permission);
  9358. + err = hidden_inode->i_op->permission(hidden_inode, submask,
  9359. + fake_nd);
  9360. + TraceErr(err);
  9361. + }
  9362. +
  9363. +#if 1
  9364. + if (!err) {
  9365. +#ifndef CONFIG_AUFS_DLGT
  9366. + err = security_inode_permission(hidden_inode, mask, fake_nd);
  9367. +#else
  9368. + if (!dlgt)
  9369. + err = security_inode_permission(hidden_inode, mask,
  9370. + fake_nd);
  9371. + else {
  9372. + struct security_inode_permission_args args = {
  9373. + .errp = &err,
  9374. + .h_inode = hidden_inode,
  9375. + .mask = mask,
  9376. + .fake_nd = fake_nd
  9377. + };
  9378. + au_wkq_wait(call_security_inode_permission, &args,
  9379. + /*dlgt*/1);
  9380. + }
  9381. +#endif
  9382. + }
  9383. +#endif
  9384. +
  9385. + out:
  9386. + TraceErr(err);
  9387. + return err;
  9388. +}
  9389. +
  9390. +static int silly_lock(struct inode *inode, struct nameidata *nd)
  9391. +{
  9392. + int locked = 0;
  9393. + struct super_block *sb = inode->i_sb;
  9394. +
  9395. + LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
  9396. +
  9397. +#ifdef CONFIG_AUFS_FAKE_DM
  9398. + si_read_lock(sb);
  9399. + ii_read_lock_child(inode);
  9400. +#else
  9401. + if (!nd || !nd->dentry) {
  9402. + si_read_lock(sb);
  9403. + ii_read_lock_child(inode);
  9404. + } else if (nd->dentry->d_inode != inode) {
  9405. + locked = 1;
  9406. + /* lock child first, then parent */
  9407. + si_read_lock(sb);
  9408. + ii_read_lock_child(inode);
  9409. + di_read_lock_parent(nd->dentry, 0);
  9410. + } else {
  9411. + locked = 2;
  9412. + aufs_read_lock(nd->dentry, AUFS_I_RLOCK);
  9413. + }
  9414. +#endif
  9415. + return locked;
  9416. +}
  9417. +
  9418. +static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd)
  9419. +{
  9420. + struct super_block *sb = inode->i_sb;
  9421. +
  9422. + LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd);
  9423. +
  9424. +#ifdef CONFIG_AUFS_FAKE_DM
  9425. + ii_read_unlock(inode);
  9426. + si_read_unlock(sb);
  9427. +#else
  9428. + switch (locked) {
  9429. + case 0:
  9430. + ii_read_unlock(inode);
  9431. + si_read_unlock(sb);
  9432. + break;
  9433. + case 1:
  9434. + di_read_unlock(nd->dentry, 0);
  9435. + ii_read_unlock(inode);
  9436. + si_read_unlock(sb);
  9437. + break;
  9438. + case 2:
  9439. + aufs_read_unlock(nd->dentry, AUFS_I_RLOCK);
  9440. + break;
  9441. + default:
  9442. + BUG();
  9443. + }
  9444. +#endif
  9445. +}
  9446. +
  9447. +static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
  9448. +{
  9449. + int err, locked, dlgt;
  9450. + aufs_bindex_t bindex, bend;
  9451. + struct inode *hidden_inode;
  9452. + struct super_block *sb;
  9453. + struct nameidata fake_nd, *p;
  9454. + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
  9455. + const int nondir = !S_ISDIR(inode->i_mode);
  9456. +
  9457. + LKTRTrace("ino %lu, mask 0x%x, nondir %d, write_mask %d, "
  9458. + "nd %p{%p, %p}\n",
  9459. + inode->i_ino, mask, nondir, write_mask,
  9460. + nd, nd ? nd->dentry : NULL, nd ? nd->mnt : NULL);
  9461. +
  9462. + sb = inode->i_sb;
  9463. + locked = silly_lock(inode, nd);
  9464. + dlgt = need_dlgt(sb);
  9465. +
  9466. + if (nd)
  9467. + fake_nd = *nd;
  9468. + if (/* unlikely */(nondir || write_mask)) {
  9469. + hidden_inode = au_h_iptr(inode);
  9470. + DEBUG_ON(!hidden_inode
  9471. + || ((hidden_inode->i_mode & S_IFMT)
  9472. + != (inode->i_mode & S_IFMT)));
  9473. + err = 0;
  9474. + bindex = ibstart(inode);
  9475. + p = fake_dm(&fake_nd, nd, sb, bindex);
  9476. + /* actual test will be delegated to LSM */
  9477. + if (IS_ERR(p))
  9478. + DEBUG_ON(PTR_ERR(p) != -ENOENT);
  9479. + else {
  9480. + err = hidden_permission(hidden_inode, mask, p,
  9481. + sbr_perm(sb, bindex), dlgt);
  9482. + fake_dm_release(p);
  9483. + }
  9484. + if (write_mask && !err) {
  9485. + err = find_rw_br(sb, bindex);
  9486. + if (err >= 0)
  9487. + err = 0;
  9488. + }
  9489. + goto out;
  9490. + }
  9491. +
  9492. + /* non-write to dir */
  9493. + err = 0;
  9494. + bend = ibend(inode);
  9495. + for (bindex = ibstart(inode); !err && bindex <= bend; bindex++) {
  9496. + hidden_inode = au_h_iptr_i(inode, bindex);
  9497. + if (!hidden_inode)
  9498. + continue;
  9499. + DEBUG_ON(!S_ISDIR(hidden_inode->i_mode));
  9500. +
  9501. + p = fake_dm(&fake_nd, nd, sb, bindex);
  9502. + /* actual test will be delegated to LSM */
  9503. + if (IS_ERR(p))
  9504. + DEBUG_ON(PTR_ERR(p) != -ENOENT);
  9505. + else {
  9506. + err = hidden_permission(hidden_inode, mask, p,
  9507. + sbr_perm(sb, bindex), dlgt);
  9508. + fake_dm_release(p);
  9509. + }
  9510. + }
  9511. +
  9512. + out:
  9513. + silly_unlock(locked, inode, nd);
  9514. + TraceErr(err);
  9515. + return err;
  9516. +}
  9517. +
  9518. +/* ---------------------------------------------------------------------- */
  9519. +
  9520. +static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
  9521. + struct nameidata *nd)
  9522. +{
  9523. + struct dentry *ret, *parent;
  9524. + int err, npositive;
  9525. + struct inode *inode;
  9526. +
  9527. + LKTRTrace("dir %lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  9528. + DEBUG_ON(IS_ROOT(dentry));
  9529. + IMustLock(dir);
  9530. +
  9531. + parent = dentry->d_parent; // dget_parent()
  9532. + aufs_read_lock(parent, !AUFS_I_RLOCK);
  9533. + err = au_alloc_dinfo(dentry);
  9534. + //if (LktrCond) err = -1;
  9535. + ret = ERR_PTR(err);
  9536. + if (unlikely(err))
  9537. + goto out;
  9538. +
  9539. + err = npositive = lkup_dentry(dentry, dbstart(parent), /*type*/0);
  9540. + //err = -1;
  9541. + ret = ERR_PTR(err);
  9542. + if (unlikely(err < 0))
  9543. + goto out_unlock;
  9544. + inode = NULL;
  9545. + if (npositive) {
  9546. + inode = au_new_inode(dentry);
  9547. + ret = (void*)inode;
  9548. + }
  9549. + if (!IS_ERR(inode)) {
  9550. +#if 1
  9551. + /* d_splice_alias() also supports d_add() */
  9552. + ret = d_splice_alias(inode, dentry);
  9553. + if (unlikely(IS_ERR(ret) && inode))
  9554. + ii_write_unlock(inode);
  9555. +#else
  9556. + d_add(dentry, inode);
  9557. +#endif
  9558. + }
  9559. +
  9560. + out_unlock:
  9561. + di_write_unlock(dentry);
  9562. + out:
  9563. + aufs_read_unlock(parent, !AUFS_I_RLOCK);
  9564. + TraceErrPtr(ret);
  9565. + return ret;
  9566. +}
  9567. +
  9568. +/* ---------------------------------------------------------------------- */
  9569. +
  9570. +/*
  9571. + * decide the branch and the parent dir where we will create a new entry.
  9572. + * returns new bindex or an error.
  9573. + * copyup the parent dir if needed.
  9574. + */
  9575. +int wr_dir(struct dentry *dentry, int add_entry, struct dentry *src_dentry,
  9576. + aufs_bindex_t force_btgt, int do_lock_srcdir)
  9577. +{
  9578. + int err;
  9579. + aufs_bindex_t bcpup, bstart, src_bstart;
  9580. + struct dentry *hidden_parent;
  9581. + struct super_block *sb;
  9582. + struct dentry *parent, *src_parent = NULL;
  9583. + struct inode *dir, *src_dir = NULL;
  9584. +
  9585. + LKTRTrace("%.*s, add %d, src %p, force %d, lock_srcdir %d\n",
  9586. + DLNPair(dentry), add_entry, src_dentry, force_btgt,
  9587. + do_lock_srcdir);
  9588. +
  9589. + sb = dentry->d_sb;
  9590. + parent = dentry->d_parent; // dget_parent()
  9591. + bcpup = bstart = dbstart(dentry);
  9592. + if (force_btgt < 0) {
  9593. + if (src_dentry) {
  9594. + src_bstart = dbstart(src_dentry);
  9595. + if (src_bstart < bstart)
  9596. + bcpup = src_bstart;
  9597. + }
  9598. + if (test_ro(sb, bcpup, dentry->d_inode)) {
  9599. + if (!add_entry)
  9600. + di_read_lock_parent(parent, !AUFS_I_RLOCK);
  9601. + bcpup = err = find_rw_parent_br(dentry, bcpup);
  9602. + //bcpup = err = find_rw_br(sb, bcpup);
  9603. + if (!add_entry)
  9604. + di_read_unlock(parent, !AUFS_I_RLOCK);
  9605. + //err = -1;
  9606. + if (unlikely(err < 0))
  9607. + goto out;
  9608. + }
  9609. + } else {
  9610. + DEBUG_ON(bstart <= force_btgt
  9611. + || test_ro(sb, force_btgt, dentry->d_inode));
  9612. + bcpup = force_btgt;
  9613. + }
  9614. + LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
  9615. +
  9616. + err = bcpup;
  9617. + if (bcpup == bstart)
  9618. + goto out; /* success */
  9619. +
  9620. + /* copyup the new parent into the branch we process */
  9621. + hidden_parent = au_h_dptr(dentry)->d_parent; // dget_parent()
  9622. + if (src_dentry) {
  9623. + src_parent = src_dentry->d_parent; // dget_parent()
  9624. + src_dir = src_parent->d_inode;
  9625. + if (do_lock_srcdir)
  9626. + di_write_lock_parent2(src_parent);
  9627. + }
  9628. +
  9629. + dir = parent->d_inode;
  9630. + if (add_entry) {
  9631. + au_update_dbstart(dentry);
  9632. + IMustLock(dir);
  9633. + DiMustWriteLock(parent);
  9634. + IiMustWriteLock(dir);
  9635. + } else
  9636. + di_write_lock_parent(parent);
  9637. +
  9638. + err = 0;
  9639. + if (!au_h_dptr_i(parent, bcpup))
  9640. + err = cpup_dirs(dentry, bcpup, src_parent);
  9641. + //err = -1;
  9642. + if (!err && add_entry) {
  9643. + hidden_parent = au_h_dptr_i(parent, bcpup);
  9644. + DEBUG_ON(!hidden_parent || !hidden_parent->d_inode);
  9645. + hi_lock_parent(hidden_parent->d_inode);
  9646. + err = lkup_neg(dentry, bcpup);
  9647. + //err = -1;
  9648. + i_unlock(hidden_parent->d_inode);
  9649. + }
  9650. +
  9651. + if (!add_entry)
  9652. + di_write_unlock(parent);
  9653. + if (do_lock_srcdir)
  9654. + di_write_unlock(src_parent);
  9655. + if (!err)
  9656. + err = bcpup; /* success */
  9657. + //err = -EPERM;
  9658. + out:
  9659. + TraceErr(err);
  9660. + return err;
  9661. +}
  9662. +
  9663. +/* ---------------------------------------------------------------------- */
  9664. +
  9665. +static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
  9666. +{
  9667. + int err, isdir;
  9668. + aufs_bindex_t bstart, bcpup;
  9669. + struct inode *hidden_inode, *inode, *dir, *h_dir, *gh_dir, *gdir;
  9670. + struct dentry *hidden_dentry, *parent;
  9671. + unsigned int udba;
  9672. +
  9673. + LKTRTrace("%.*s, ia_valid 0x%x\n", DLNPair(dentry), ia->ia_valid);
  9674. + inode = dentry->d_inode;
  9675. + IMustLock(inode);
  9676. +
  9677. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  9678. + bstart = dbstart(dentry);
  9679. + bcpup = err = wr_dir(dentry, /*add*/0, /*src_dentry*/NULL,
  9680. + /*force_btgt*/-1, /*do_lock_srcdir*/0);
  9681. + //err = -1;
  9682. + if (unlikely(err < 0))
  9683. + goto out;
  9684. +
  9685. + /* crazy udba locks */
  9686. + udba = au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY);
  9687. + parent = NULL;
  9688. + gdir = gh_dir = dir = h_dir = NULL;
  9689. + if ((udba || bstart != bcpup) && !IS_ROOT(dentry)) {
  9690. + parent = dentry->d_parent; // dget_parent()
  9691. + dir = parent->d_inode;
  9692. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  9693. + h_dir = au_h_iptr_i(dir, bcpup);
  9694. + }
  9695. + if (parent) {
  9696. + if (unlikely(udba && !IS_ROOT(parent))) {
  9697. + gdir = parent->d_parent->d_inode; // dget_parent()
  9698. + ii_read_lock_parent2(gdir);
  9699. + gh_dir = au_h_iptr_i(gdir, bcpup);
  9700. + hgdir_lock(gh_dir, gdir, bcpup);
  9701. + }
  9702. + hdir_lock(h_dir, dir, bcpup);
  9703. + }
  9704. +
  9705. + isdir = S_ISDIR(inode->i_mode);
  9706. + hidden_dentry = au_h_dptr(dentry);
  9707. + hidden_inode = hidden_dentry->d_inode;
  9708. + DEBUG_ON(!hidden_inode);
  9709. +
  9710. +#define HiLock(bindex) do {\
  9711. + if (!isdir) \
  9712. + hi_lock_child(hidden_inode); \
  9713. + else \
  9714. + hdir2_lock(hidden_inode, inode, bindex); \
  9715. + } while (0)
  9716. +#define HiUnlock(bindex) do {\
  9717. + if (!isdir) \
  9718. + i_unlock(hidden_inode); \
  9719. + else \
  9720. + hdir_unlock(hidden_inode, inode, bindex); \
  9721. + } while (0)
  9722. +
  9723. + if (bstart != bcpup) {
  9724. + loff_t size = -1;
  9725. +
  9726. + if ((ia->ia_valid & ATTR_SIZE)
  9727. + && ia->ia_size < i_size_read(inode)) {
  9728. + size = ia->ia_size;
  9729. + ia->ia_valid &= ~ATTR_SIZE;
  9730. + }
  9731. + HiLock(bstart);
  9732. + err = sio_cpup_simple(dentry, bcpup, size,
  9733. + au_flags_cpup(CPUP_DTIME, parent));
  9734. + //err = -1;
  9735. + HiUnlock(bstart);
  9736. + if (unlikely(err || !ia->ia_valid))
  9737. + goto out_unlock;
  9738. +
  9739. + hidden_dentry = au_h_dptr(dentry);
  9740. + hidden_inode = hidden_dentry->d_inode;
  9741. + DEBUG_ON(!hidden_inode);
  9742. + }
  9743. +
  9744. + HiLock(bcpup);
  9745. + err = vfsub_notify_change(hidden_dentry, ia, need_dlgt(dentry->d_sb));
  9746. + //err = -1;
  9747. + if (!err)
  9748. + au_cpup_attr_changable(inode);
  9749. + HiUnlock(bcpup);
  9750. +#undef HiLock
  9751. +#undef HiUnlock
  9752. +
  9753. + out_unlock:
  9754. + if (parent) {
  9755. + hdir_unlock(h_dir, dir, bcpup);
  9756. + di_read_unlock(parent, AUFS_I_RLOCK);
  9757. + }
  9758. + if (unlikely(gdir)) {
  9759. + hdir_unlock(gh_dir, gdir, bcpup);
  9760. + ii_read_unlock(gdir);
  9761. + }
  9762. + out:
  9763. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  9764. + TraceErr(err);
  9765. + return err;
  9766. +}
  9767. +
  9768. +/* ---------------------------------------------------------------------- */
  9769. +
  9770. +static int hidden_readlink(struct dentry *dentry, int bindex,
  9771. + char __user * buf, int bufsiz)
  9772. +{
  9773. + struct super_block *sb;
  9774. + struct dentry *hidden_dentry;
  9775. +
  9776. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  9777. + if (unlikely(!hidden_dentry->d_inode->i_op
  9778. + || !hidden_dentry->d_inode->i_op->readlink))
  9779. + return -EINVAL;
  9780. +
  9781. + sb = dentry->d_sb;
  9782. + if (!test_ro(sb, bindex, dentry->d_inode)) {
  9783. + touch_atime(sbr_mnt(sb, bindex), hidden_dentry);
  9784. + dentry->d_inode->i_atime = hidden_dentry->d_inode->i_atime;
  9785. + }
  9786. + return hidden_dentry->d_inode->i_op->readlink
  9787. + (hidden_dentry, buf, bufsiz);
  9788. +}
  9789. +
  9790. +static int aufs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
  9791. +{
  9792. + int err;
  9793. +
  9794. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), bufsiz);
  9795. +
  9796. + aufs_read_lock(dentry, AUFS_I_RLOCK);
  9797. + err = hidden_readlink(dentry, dbstart(dentry), buf, bufsiz);
  9798. + //err = -1;
  9799. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  9800. + TraceErr(err);
  9801. + return err;
  9802. +}
  9803. +
  9804. +static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
  9805. +{
  9806. + int err;
  9807. + char *buf;
  9808. + mm_segment_t old_fs;
  9809. +
  9810. + LKTRTrace("%.*s, nd %.*s\n", DLNPair(dentry), DLNPair(nd->dentry));
  9811. +
  9812. + err = -ENOMEM;
  9813. + buf = __getname();
  9814. + //buf = NULL;
  9815. + if (unlikely(!buf))
  9816. + goto out;
  9817. +
  9818. + aufs_read_lock(dentry, AUFS_I_RLOCK);
  9819. + old_fs = get_fs();
  9820. + set_fs(KERNEL_DS);
  9821. + err = hidden_readlink(dentry, dbstart(dentry), (char __user *)buf,
  9822. + PATH_MAX);
  9823. + //err = -1;
  9824. + set_fs(old_fs);
  9825. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  9826. +
  9827. + if (err >= 0) {
  9828. + buf[err] = 0;
  9829. + /* will be freed by put_link */
  9830. + nd_set_link(nd, buf);
  9831. + return NULL; /* success */
  9832. + }
  9833. + __putname(buf);
  9834. +
  9835. + out:
  9836. + path_release(nd);
  9837. + TraceErr(err);
  9838. + return ERR_PTR(err);
  9839. +}
  9840. +
  9841. +static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
  9842. + void *cookie)
  9843. +{
  9844. + LKTRTrace("%.*s\n", DLNPair(dentry));
  9845. + __putname(nd_get_link(nd));
  9846. +}
  9847. +
  9848. +/* ---------------------------------------------------------------------- */
  9849. +#if 0 // comment
  9850. +struct inode_operations {
  9851. + int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
  9852. + struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
  9853. + int (*link) (struct dentry *,struct inode *,struct dentry *);
  9854. + int (*unlink) (struct inode *,struct dentry *);
  9855. + int (*symlink) (struct inode *,struct dentry *,const char *);
  9856. + int (*mkdir) (struct inode *,struct dentry *,int);
  9857. + int (*rmdir) (struct inode *,struct dentry *);
  9858. + int (*mknod) (struct inode *,struct dentry *,int,dev_t);
  9859. + int (*rename) (struct inode *, struct dentry *,
  9860. + struct inode *, struct dentry *);
  9861. + int (*readlink) (struct dentry *, char __user *,int);
  9862. + void * (*follow_link) (struct dentry *, struct nameidata *);
  9863. + void (*put_link) (struct dentry *, struct nameidata *, void *);
  9864. + void (*truncate) (struct inode *);
  9865. + int (*permission) (struct inode *, int, struct nameidata *);
  9866. + int (*setattr) (struct dentry *, struct iattr *);
  9867. + int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
  9868. + int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
  9869. + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
  9870. + ssize_t (*listxattr) (struct dentry *, char *, size_t);
  9871. + int (*removexattr) (struct dentry *, const char *);
  9872. + void (*truncate_range)(struct inode *, loff_t, loff_t);
  9873. +};
  9874. +#endif
  9875. +
  9876. +struct inode_operations aufs_symlink_iop = {
  9877. + .permission = aufs_permission,
  9878. + .setattr = aufs_setattr,
  9879. +
  9880. + .readlink = aufs_readlink,
  9881. + .follow_link = aufs_follow_link,
  9882. + .put_link = aufs_put_link
  9883. +};
  9884. +
  9885. +//i_op_add.c
  9886. +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
  9887. +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
  9888. +int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
  9889. + struct nameidata *nd);
  9890. +int aufs_link(struct dentry *src_dentry, struct inode *dir,
  9891. + struct dentry *dentry);
  9892. +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
  9893. +
  9894. +//i_op_del.c
  9895. +int aufs_unlink(struct inode *dir, struct dentry *dentry);
  9896. +int aufs_rmdir(struct inode *dir, struct dentry *dentry);
  9897. +
  9898. +// i_op_ren.c
  9899. +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
  9900. + struct inode *dir, struct dentry *dentry);
  9901. +
  9902. +struct inode_operations aufs_dir_iop = {
  9903. + .create = aufs_create,
  9904. + .lookup = aufs_lookup,
  9905. + .link = aufs_link,
  9906. + .unlink = aufs_unlink,
  9907. + .symlink = aufs_symlink,
  9908. + .mkdir = aufs_mkdir,
  9909. + .rmdir = aufs_rmdir,
  9910. + .mknod = aufs_mknod,
  9911. + .rename = aufs_rename,
  9912. +
  9913. + .permission = aufs_permission,
  9914. + .setattr = aufs_setattr,
  9915. +
  9916. +#if 0 // xattr
  9917. + .setxattr = aufs_setxattr,
  9918. + .getxattr = aufs_getxattr,
  9919. + .listxattr = aufs_listxattr,
  9920. + .removexattr = aufs_removexattr
  9921. +#endif
  9922. +};
  9923. +
  9924. +struct inode_operations aufs_iop = {
  9925. + .permission = aufs_permission,
  9926. + .setattr = aufs_setattr,
  9927. +
  9928. +#if 0 // xattr
  9929. + .setxattr = aufs_setxattr,
  9930. + .getxattr = aufs_getxattr,
  9931. + .listxattr = aufs_listxattr,
  9932. + .removexattr = aufs_removexattr
  9933. +#endif
  9934. +};
  9935. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op_add.c linux-2.6.22.1/fs/aufs/i_op_add.c
  9936. --- linux-2.6.22.1.oorig/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
  9937. +++ linux-2.6.22.1/fs/aufs/i_op_add.c 2007-07-24 14:17:46.000000000 +0200
  9938. @@ -0,0 +1,621 @@
  9939. +/*
  9940. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  9941. + *
  9942. + * This program, aufs is free software; you can redistribute it and/or modify
  9943. + * it under the terms of the GNU General Public License as published by
  9944. + * the Free Software Foundation; either version 2 of the License, or
  9945. + * (at your option) any later version.
  9946. + *
  9947. + * This program is distributed in the hope that it will be useful,
  9948. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9949. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9950. + * GNU General Public License for more details.
  9951. + *
  9952. + * You should have received a copy of the GNU General Public License
  9953. + * along with this program; if not, write to the Free Software
  9954. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  9955. + */
  9956. +
  9957. +/* $Id: i_op_add.c,v 1.37 2007/05/07 03:46:08 sfjro Exp $ */
  9958. +
  9959. +//#include <linux/fs.h>
  9960. +//#include <linux/namei.h>
  9961. +#include "aufs.h"
  9962. +
  9963. +/*
  9964. + * final procedure of adding a new entry, except link(2).
  9965. + * remove whiteout, instantiate, copyup the parent dir's times and size
  9966. + * and update version.
  9967. + * if it failed, re-create the removed whiteout.
  9968. + */
  9969. +static int epilog(struct dentry *wh_dentry, struct dentry *dentry)
  9970. +{
  9971. + int err, rerr;
  9972. + aufs_bindex_t bwh;
  9973. + struct inode *inode, *dir;
  9974. + struct dentry *wh;
  9975. + struct lkup_args lkup;
  9976. +
  9977. + LKTRTrace("wh %p, %.*s\n", wh_dentry, DLNPair(dentry));
  9978. +
  9979. + lkup.dlgt = need_dlgt(dentry->d_sb);
  9980. + bwh = -1;
  9981. + if (wh_dentry) {
  9982. + bwh = dbwh(dentry);
  9983. + err = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode,
  9984. + wh_dentry, dentry, lkup.dlgt);
  9985. + //err = -1;
  9986. + if (unlikely(err))
  9987. + goto out;
  9988. + }
  9989. +
  9990. + inode = au_new_inode(dentry);
  9991. + //inode = ERR_PTR(-1);
  9992. + if (!IS_ERR(inode)) {
  9993. + d_instantiate(dentry, inode);
  9994. + dir = dentry->d_parent->d_inode;
  9995. + /* or always cpup dir mtime? */
  9996. + if (ibstart(dir) == dbstart(dentry))
  9997. + au_cpup_attr_timesizes(dir);
  9998. + dir->i_version++;
  9999. + return 0; /* success */
  10000. + }
  10001. +
  10002. + err = PTR_ERR(inode);
  10003. + if (!wh_dentry)
  10004. + goto out;
  10005. +
  10006. + /* revert */
  10007. + lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bwh);
  10008. + wh = simple_create_wh(dentry, bwh, wh_dentry->d_parent, &lkup);
  10009. + //wh = ERR_PTR(-1);
  10010. + rerr = PTR_ERR(wh);
  10011. + if (!IS_ERR(wh)) {
  10012. + dput(wh);
  10013. + goto out;
  10014. + }
  10015. + IOErr("%.*s reverting whiteout failed(%d, %d)\n",
  10016. + DLNPair(dentry), err, rerr);
  10017. + err = -EIO;
  10018. +
  10019. + out:
  10020. + TraceErr(err);
  10021. + return err;
  10022. +}
  10023. +
  10024. +/*
  10025. + * initial procedure of adding a new entry.
  10026. + * prepare writable branch and the parent dir, lock it,
  10027. + * lookup whiteout for the new entry.
  10028. + */
  10029. +static struct dentry *
  10030. +lock_hdir_lkup_wh(struct dentry *dentry, struct dtime *dt,
  10031. + struct dentry *src_dentry, int do_lock_srcdir)
  10032. +{
  10033. + struct dentry *wh_dentry, *parent, *hidden_parent;
  10034. + int err;
  10035. + aufs_bindex_t bstart, bcpup;
  10036. + struct inode *dir, *h_dir;
  10037. + struct lkup_args lkup;
  10038. +
  10039. + LKTRTrace("%.*s, src %p\n", DLNPair(dentry), src_dentry);
  10040. +
  10041. + parent = dentry->d_parent;
  10042. + bstart = dbstart(dentry);
  10043. + bcpup = err = wr_dir(dentry, 1, src_dentry, -1, do_lock_srcdir);
  10044. + //err = -1;
  10045. + wh_dentry = ERR_PTR(err);
  10046. + if (unlikely(err < 0))
  10047. + goto out;
  10048. +
  10049. + dir = parent->d_inode;
  10050. + hidden_parent = au_h_dptr_i(parent, bcpup);
  10051. + h_dir = hidden_parent->d_inode;
  10052. + hdir_lock(h_dir, dir, bcpup);
  10053. + if (dt)
  10054. + dtime_store(dt, parent, hidden_parent);
  10055. + if (/* bcpup != bstart || */ bcpup != dbwh(dentry))
  10056. + return NULL; /* success */
  10057. +
  10058. + lkup.nfsmnt = au_nfsmnt(parent->d_sb, bcpup);
  10059. + lkup.dlgt = need_dlgt(parent->d_sb);
  10060. + wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, &lkup);
  10061. + //wh_dentry = ERR_PTR(-1);
  10062. + if (IS_ERR(wh_dentry))
  10063. + hdir_unlock(h_dir, dir, bcpup);
  10064. +
  10065. + out:
  10066. + TraceErrPtr(wh_dentry);
  10067. + return wh_dentry;
  10068. +}
  10069. +
  10070. +/* ---------------------------------------------------------------------- */
  10071. +
  10072. +enum {Mknod, Symlink, Creat};
  10073. +struct simple_arg {
  10074. + int type;
  10075. + union {
  10076. + struct {
  10077. + int mode;
  10078. + struct nameidata *nd;
  10079. + } c;
  10080. + struct {
  10081. + const char *symname;
  10082. + } s;
  10083. + struct {
  10084. + int mode;
  10085. + dev_t dev;
  10086. + } m;
  10087. + } u;
  10088. +};
  10089. +
  10090. +static int add_simple(struct inode *dir, struct dentry *dentry,
  10091. + struct simple_arg *arg)
  10092. +{
  10093. + int err, dlgt;
  10094. + struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent;
  10095. + struct inode *hidden_dir;
  10096. + struct dtime dt;
  10097. +
  10098. + LKTRTrace("type %d, %.*s\n", arg->type, DLNPair(dentry));
  10099. + IMustLock(dir);
  10100. +
  10101. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10102. + parent = dentry->d_parent;
  10103. + di_write_lock_parent(parent);
  10104. + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
  10105. + /*do_lock_srcdir*/0);
  10106. + //wh_dentry = ERR_PTR(-1);
  10107. + err = PTR_ERR(wh_dentry);
  10108. + if (IS_ERR(wh_dentry))
  10109. + goto out;
  10110. +
  10111. + hidden_dentry = au_h_dptr(dentry);
  10112. + hidden_parent = hidden_dentry->d_parent;
  10113. + hidden_dir = hidden_parent->d_inode;
  10114. + IMustLock(hidden_dir);
  10115. + dlgt = need_dlgt(dir->i_sb);
  10116. +
  10117. +#if 1 // partial testing
  10118. + switch (arg->type) {
  10119. + case Creat:
  10120. +#if 0
  10121. + if (arg->u.c.nd) {
  10122. + struct nameidata fake_nd;
  10123. + fake_nd = *arg->u.c.nd;
  10124. + fake_nd.dentry = dget(hidden_parent);
  10125. + fake_nd.mnt = sbr_mnt(dentry->d_sb, dbstart(dentry));
  10126. + mntget(fake_nd.mnt);
  10127. + err = vfsub_create(hidden_dir, hidden_dentry,
  10128. + arg->u.c.mode, &fake_nd, dlgt);
  10129. + path_release(&fake_nd);
  10130. + } else
  10131. +#endif
  10132. + err = vfsub_create(hidden_dir, hidden_dentry,
  10133. + arg->u.c.mode, NULL, dlgt);
  10134. + break;
  10135. + case Symlink:
  10136. + err = vfsub_symlink(hidden_dir, hidden_dentry,
  10137. + arg->u.s.symname, S_IALLUGO, dlgt);
  10138. + break;
  10139. + case Mknod:
  10140. + err = vfsub_mknod(hidden_dir, hidden_dentry,
  10141. + arg->u.m.mode, arg->u.m.dev, dlgt);
  10142. + break;
  10143. + default:
  10144. + BUG();
  10145. + }
  10146. +#else
  10147. + err = -1;
  10148. +#endif
  10149. + if (!err)
  10150. + err = epilog(wh_dentry, dentry);
  10151. + //err = -1;
  10152. +
  10153. + /* revert */
  10154. + if (unlikely(err && hidden_dentry->d_inode)) {
  10155. + int rerr;
  10156. + rerr = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
  10157. + //rerr = -1;
  10158. + if (rerr) {
  10159. + IOErr("%.*s revert failure(%d, %d)\n",
  10160. + DLNPair(dentry), err, rerr);
  10161. + err = -EIO;
  10162. + }
  10163. + dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
  10164. + d_drop(dentry);
  10165. + }
  10166. +
  10167. + hdir_unlock(hidden_dir, dir, dbstart(dentry));
  10168. + dput(wh_dentry);
  10169. +
  10170. + out:
  10171. + if (unlikely(err)) {
  10172. + au_update_dbstart(dentry);
  10173. + d_drop(dentry);
  10174. + }
  10175. + di_write_unlock(parent);
  10176. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  10177. + TraceErr(err);
  10178. + return err;
  10179. +}
  10180. +
  10181. +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
  10182. +{
  10183. + struct simple_arg arg = {
  10184. + .type = Mknod,
  10185. + .u.m = {.mode = mode, .dev = dev}
  10186. + };
  10187. + return add_simple(dir, dentry, &arg);
  10188. +}
  10189. +
  10190. +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
  10191. +{
  10192. + struct simple_arg arg = {
  10193. + .type = Symlink,
  10194. + .u.s.symname = symname
  10195. + };
  10196. + return add_simple(dir, dentry, &arg);
  10197. +}
  10198. +
  10199. +int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
  10200. + struct nameidata *nd)
  10201. +{
  10202. + struct simple_arg arg = {
  10203. + .type = Creat,
  10204. + .u.c = {.mode = mode, .nd = nd}
  10205. + };
  10206. + return add_simple(dir, dentry, &arg);
  10207. +}
  10208. +
  10209. +/* ---------------------------------------------------------------------- */
  10210. +
  10211. +struct link_arg {
  10212. + aufs_bindex_t bdst, bsrc;
  10213. + int issamedir, dlgt;
  10214. + struct dentry *src_parent, *parent, *hidden_dentry;
  10215. + struct inode *hidden_dir, *inode;
  10216. +};
  10217. +
  10218. +static int cpup_before_link(struct dentry *src_dentry, struct inode *dir,
  10219. + struct link_arg *a)
  10220. +{
  10221. + int err;
  10222. + unsigned int flags;
  10223. + struct inode *hi, *hdir = NULL, *src_dir;
  10224. +
  10225. + TraceEnter();
  10226. +
  10227. + err = 0;
  10228. + flags = au_flags_cpup(CPUP_DTIME, a->parent);
  10229. + src_dir = a->src_parent->d_inode;
  10230. + if (!a->issamedir) {
  10231. + // todo: dead lock?
  10232. + di_read_lock_parent2(a->src_parent, AUFS_I_RLOCK);
  10233. + // this temporary unlock/lock is safe
  10234. + hdir_unlock(a->hidden_dir, dir, a->bdst);
  10235. + err = test_and_cpup_dirs(src_dentry, a->bdst, a->parent);
  10236. + //err = -1;
  10237. + if (!err) {
  10238. + hdir = au_h_iptr_i(src_dir, a->bdst);
  10239. + hdir_lock(hdir, src_dir, a->bdst);
  10240. + flags = au_flags_cpup(CPUP_DTIME, a->src_parent);
  10241. + }
  10242. + }
  10243. +
  10244. + if (!err) {
  10245. + hi = au_h_dptr(src_dentry)->d_inode;
  10246. + hi_lock_child(hi);
  10247. + err = sio_cpup_simple(src_dentry, a->bdst, -1, flags);
  10248. + //err = -1;
  10249. + i_unlock(hi);
  10250. + }
  10251. +
  10252. + if (!a->issamedir) {
  10253. + if (hdir)
  10254. + hdir_unlock(hdir, src_dir, a->bdst);
  10255. + hdir_lock(a->hidden_dir, dir, a->bdst);
  10256. + di_read_unlock(a->src_parent, AUFS_I_RLOCK);
  10257. + }
  10258. +
  10259. + TraceErr(err);
  10260. + return err;
  10261. +}
  10262. +
  10263. +static int cpup_or_link(struct dentry *src_dentry, struct link_arg *a)
  10264. +{
  10265. + int err;
  10266. + struct inode *inode, *h_inode, *h_dst_inode;
  10267. + struct dentry *h_dentry;
  10268. + aufs_bindex_t bstart;
  10269. + struct super_block *sb;
  10270. +
  10271. + TraceEnter();
  10272. +
  10273. + sb = src_dentry->d_sb;
  10274. + inode = src_dentry->d_inode;
  10275. + h_dentry = au_h_dptr(src_dentry);
  10276. + h_inode = h_dentry->d_inode;
  10277. + bstart = ibstart(inode);
  10278. + h_dst_inode = NULL;
  10279. + if (bstart <= a->bdst)
  10280. + h_dst_inode = au_h_iptr_i(inode, a->bdst);
  10281. +
  10282. + if (!h_dst_inode) {
  10283. + /* copyup src_dentry as the name of dentry. */
  10284. + set_dbstart(src_dentry, a->bdst);
  10285. + set_h_dptr(src_dentry, a->bdst, dget(a->hidden_dentry));
  10286. + hi_lock_child(h_inode);
  10287. + err = sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
  10288. + au_flags_cpup(!CPUP_DTIME, a->parent));
  10289. + //err = -1;
  10290. + i_unlock(h_inode);
  10291. + set_h_dptr(src_dentry, a->bdst, NULL);
  10292. + set_dbstart(src_dentry, a->bsrc);
  10293. + } else {
  10294. + /* the inode of src_dentry already exists on a.bdst branch */
  10295. + h_dentry = d_find_alias(h_dst_inode);
  10296. + if (h_dentry) {
  10297. + err = vfsub_link(h_dentry, a->hidden_dir,
  10298. + a->hidden_dentry, a->dlgt);
  10299. + dput(h_dentry);
  10300. + } else {
  10301. + IOErr("no dentry found for i%lu on b%d\n",
  10302. + h_dst_inode->i_ino, a->bdst);
  10303. + err = -EIO;
  10304. + }
  10305. + }
  10306. +
  10307. + if (!err)
  10308. + append_plink(sb, a->inode, a->hidden_dentry, a->bdst);
  10309. +
  10310. + TraceErr(err);
  10311. + return err;
  10312. +}
  10313. +
  10314. +int aufs_link(struct dentry *src_dentry, struct inode *dir,
  10315. + struct dentry *dentry)
  10316. +{
  10317. + int err, rerr;
  10318. + struct dentry *hidden_parent, *wh_dentry, *hidden_src_dentry;
  10319. + struct dtime dt;
  10320. + struct link_arg a;
  10321. + struct super_block *sb;
  10322. +
  10323. + LKTRTrace("src %.*s, i%lu, dst %.*s\n",
  10324. + DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
  10325. + IMustLock(dir);
  10326. + IMustLock(src_dentry->d_inode);
  10327. +
  10328. + aufs_read_and_write_lock2(dentry, src_dentry, /*isdir*/0);
  10329. + a.src_parent = src_dentry->d_parent;
  10330. + a.parent = dentry->d_parent;
  10331. + a.issamedir = (a.src_parent == a.parent);
  10332. + di_write_lock_parent(a.parent);
  10333. + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, !a.issamedir);
  10334. + //wh_dentry = ERR_PTR(-1);
  10335. + err = PTR_ERR(wh_dentry);
  10336. + if (IS_ERR(wh_dentry))
  10337. + goto out;
  10338. +
  10339. + a.inode = src_dentry->d_inode;
  10340. + a.hidden_dentry = au_h_dptr(dentry);
  10341. + hidden_parent = a.hidden_dentry->d_parent;
  10342. + a.hidden_dir = hidden_parent->d_inode;
  10343. + IMustLock(a.hidden_dir);
  10344. +
  10345. + err = 0;
  10346. + sb = dentry->d_sb;
  10347. + a.dlgt = need_dlgt(sb);
  10348. +
  10349. + //todo: minor optimize, their sb may be same while their bindex differs.
  10350. + a.bsrc = dbstart(src_dentry);
  10351. + a.bdst = dbstart(dentry);
  10352. + hidden_src_dentry = au_h_dptr(src_dentry);
  10353. + if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
  10354. + /*
  10355. + * copyup src_dentry to the branch we process,
  10356. + * and then link(2) to it.
  10357. + * gave up 'pseudo link by cpup' approach,
  10358. + * since nlink may be one and some applications will not work.
  10359. + */
  10360. + if (a.bdst < a.bsrc
  10361. + /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
  10362. + err = cpup_before_link(src_dentry, dir, &a);
  10363. + if (!err) {
  10364. + hidden_src_dentry = au_h_dptr(src_dentry);
  10365. + err = vfsub_link(hidden_src_dentry, a.hidden_dir,
  10366. + a.hidden_dentry, a.dlgt);
  10367. + //err = -1;
  10368. + }
  10369. + } else {
  10370. + if (a.bdst < a.bsrc
  10371. + /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
  10372. + err = cpup_or_link(src_dentry, &a);
  10373. + else {
  10374. + hidden_src_dentry = au_h_dptr(src_dentry);
  10375. + err = vfsub_link(hidden_src_dentry, a.hidden_dir,
  10376. + a.hidden_dentry, a.dlgt);
  10377. + //err = -1;
  10378. + }
  10379. + }
  10380. + if (unlikely(err))
  10381. + goto out_unlock;
  10382. + if (wh_dentry) {
  10383. + err = au_unlink_wh_dentry(a.hidden_dir, wh_dentry, dentry,
  10384. + a.dlgt);
  10385. + //err = -1;
  10386. + if (unlikely(err))
  10387. + goto out_revert;
  10388. + }
  10389. +
  10390. + dir->i_version++;
  10391. + if (ibstart(dir) == dbstart(dentry))
  10392. + au_cpup_attr_timesizes(dir);
  10393. + if (!d_unhashed(a.hidden_dentry)
  10394. + /* || hidden_old_inode->i_nlink <= nlink */
  10395. + /* || SB_NFS(hidden_src_dentry->d_sb) */) {
  10396. + dentry->d_inode = igrab(a.inode);
  10397. + d_instantiate(dentry, a.inode);
  10398. + a.inode->i_nlink++;
  10399. + a.inode->i_ctime = dir->i_ctime;
  10400. + } else
  10401. + /* nfs case (< 2.6.15) */
  10402. + d_drop(dentry);
  10403. +#if 0
  10404. + au_debug_on();
  10405. + DbgInode(a.inode);
  10406. + au_debug_off();
  10407. + {
  10408. + aufs_bindex_t i;
  10409. + for (i = ibstart(a.inode); i <= ibend(a.inode); i++) {
  10410. + struct xino xino;
  10411. + struct inode *hi;
  10412. + hi = au_h_iptr_i(a.inode, i);
  10413. + if (hi) {
  10414. + xino_read(sb, i, hi->i_ino, &xino);
  10415. + Dbg("hi%lu, i%lu\n", hi->i_ino, xino.ino);
  10416. + }
  10417. + }
  10418. + }
  10419. +#endif
  10420. + goto out_unlock; /* success */
  10421. +
  10422. + out_revert:
  10423. +#if 0 // remove
  10424. + if (d_unhashed(a.hidden_dentry)) {
  10425. + /* hardlink on nfs (< 2.6.15) */
  10426. + struct dentry *d;
  10427. + const struct qstr *name = &a.hidden_dentry->d_name;
  10428. + DEBUG_ON(a.hidden_dentry->d_parent->d_inode != a.hidden_dir);
  10429. + // do not superio.
  10430. + d = lkup_one(name->name, a.hidden_dentry->d_parent, name->len,
  10431. + au_nfsmnt(sb, a.bdst)??, need_dlgt(sb));
  10432. + rerr = PTR_ERR(d);
  10433. + if (IS_ERR(d))
  10434. + goto out_rerr;
  10435. + dput(a.hidden_dentry);
  10436. + a.hidden_dentry = d;
  10437. + DEBUG_ON(!d->d_inode);
  10438. + }
  10439. +#endif
  10440. + rerr = vfsub_unlink(a.hidden_dir, a.hidden_dentry, a.dlgt);
  10441. + //rerr = -1;
  10442. + if (!rerr)
  10443. + goto out_dt;
  10444. +// out_rerr:
  10445. + IOErr("%.*s reverting failed(%d, %d)\n", DLNPair(dentry), err, rerr);
  10446. + err = -EIO;
  10447. + out_dt:
  10448. + d_drop(dentry);
  10449. + dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
  10450. + out_unlock:
  10451. + hdir_unlock(a.hidden_dir, dir, a.bdst);
  10452. + dput(wh_dentry);
  10453. + out:
  10454. + if (unlikely(err)) {
  10455. + au_update_dbstart(dentry);
  10456. + d_drop(dentry);
  10457. + }
  10458. + di_write_unlock(a.parent);
  10459. + aufs_read_and_write_unlock2(dentry, src_dentry);
  10460. + TraceErr(err);
  10461. + return err;
  10462. +}
  10463. +
  10464. +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  10465. +{
  10466. + int err, rerr, diropq, dlgt;
  10467. + struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent,
  10468. + *opq_dentry;
  10469. + struct inode *hidden_dir, *hidden_inode;
  10470. + struct dtime dt;
  10471. + aufs_bindex_t bindex;
  10472. + struct super_block *sb;
  10473. +
  10474. + LKTRTrace("i%lu, %.*s, mode 0%o\n", dir->i_ino, DLNPair(dentry), mode);
  10475. + IMustLock(dir);
  10476. +
  10477. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10478. + parent = dentry->d_parent;
  10479. + di_write_lock_parent(parent);
  10480. + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
  10481. + /*do_lock_srcdir*/0);
  10482. + //wh_dentry = ERR_PTR(-1);
  10483. + err = PTR_ERR(wh_dentry);
  10484. + if (IS_ERR(wh_dentry))
  10485. + goto out;
  10486. +
  10487. + sb = dentry->d_sb;
  10488. + bindex = dbstart(dentry);
  10489. + hidden_dentry = au_h_dptr(dentry);
  10490. + hidden_parent = hidden_dentry->d_parent;
  10491. + hidden_dir = hidden_parent->d_inode;
  10492. + IMustLock(hidden_dir);
  10493. + dlgt = need_dlgt(sb);
  10494. +
  10495. + err = vfsub_mkdir(hidden_dir, hidden_dentry, mode, dlgt);
  10496. + //err = -1;
  10497. + if (unlikely(err))
  10498. + goto out_unlock;
  10499. + hidden_inode = hidden_dentry->d_inode;
  10500. +
  10501. + /* make the dir opaque */
  10502. + diropq = 0;
  10503. + if (unlikely(wh_dentry || au_flag_test(sb, AuFlag_ALWAYS_DIROPQ))) {
  10504. + hi_lock_child(hidden_inode);
  10505. + opq_dentry = create_diropq(dentry, bindex, dlgt);
  10506. + //opq_dentry = ERR_PTR(-1);
  10507. + i_unlock(hidden_inode);
  10508. + err = PTR_ERR(opq_dentry);
  10509. + if (IS_ERR(opq_dentry))
  10510. + goto out_dir;
  10511. + dput(opq_dentry);
  10512. + diropq = 1;
  10513. + }
  10514. +
  10515. + err = epilog(wh_dentry, dentry);
  10516. + //err = -1;
  10517. + if (!err) {
  10518. + dir->i_nlink++;
  10519. + goto out_unlock; /* success */
  10520. + }
  10521. +
  10522. + /* revert */
  10523. + if (unlikely(diropq)) {
  10524. + LKTRLabel(revert opq);
  10525. + hi_lock_child(hidden_inode);
  10526. + rerr = remove_diropq(dentry, bindex, dlgt);
  10527. + //rerr = -1;
  10528. + i_unlock(hidden_inode);
  10529. + if (rerr) {
  10530. + IOErr("%.*s reverting diropq failed(%d, %d)\n",
  10531. + DLNPair(dentry), err, rerr);
  10532. + err = -EIO;
  10533. + }
  10534. + }
  10535. +
  10536. + out_dir:
  10537. + LKTRLabel(revert dir);
  10538. + rerr = vfsub_rmdir(hidden_dir, hidden_dentry, dlgt);
  10539. + //rerr = -1;
  10540. + if (rerr) {
  10541. + IOErr("%.*s reverting dir failed(%d, %d)\n",
  10542. + DLNPair(dentry), err, rerr);
  10543. + err = -EIO;
  10544. + }
  10545. + d_drop(dentry);
  10546. + dtime_revert(&dt, /*fake flag*/CPUP_LOCKED_GHDIR);
  10547. + out_unlock:
  10548. + hdir_unlock(hidden_dir, dir, bindex);
  10549. + dput(wh_dentry);
  10550. + out:
  10551. + if (unlikely(err)) {
  10552. + au_update_dbstart(dentry);
  10553. + d_drop(dentry);
  10554. + }
  10555. + di_write_unlock(parent);
  10556. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  10557. + TraceErr(err);
  10558. + return err;
  10559. +}
  10560. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op_del.c linux-2.6.22.1/fs/aufs/i_op_del.c
  10561. --- linux-2.6.22.1.oorig/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
  10562. +++ linux-2.6.22.1/fs/aufs/i_op_del.c 2007-07-24 14:17:46.000000000 +0200
  10563. @@ -0,0 +1,414 @@
  10564. +/*
  10565. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  10566. + *
  10567. + * This program, aufs is free software; you can redistribute it and/or modify
  10568. + * it under the terms of the GNU General Public License as published by
  10569. + * the Free Software Foundation; either version 2 of the License, or
  10570. + * (at your option) any later version.
  10571. + *
  10572. + * This program is distributed in the hope that it will be useful,
  10573. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10574. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10575. + * GNU General Public License for more details.
  10576. + *
  10577. + * You should have received a copy of the GNU General Public License
  10578. + * along with this program; if not, write to the Free Software
  10579. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  10580. + */
  10581. +
  10582. +/* $Id: i_op_del.c,v 1.35 2007/05/14 03:41:52 sfjro Exp $ */
  10583. +
  10584. +#include "aufs.h"
  10585. +
  10586. +/* returns,
  10587. + * 0: wh is unnecessary
  10588. + * plus: wh is necessary
  10589. + * minus: error
  10590. + */
  10591. +int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
  10592. + struct dentry *locked)
  10593. +{
  10594. + int need_wh, err;
  10595. + aufs_bindex_t bstart;
  10596. + struct dentry *hidden_dentry;
  10597. + struct super_block *sb;
  10598. +
  10599. + LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
  10600. + DLNPair(dentry), isdir, *bcpup, locked);
  10601. + sb = dentry->d_sb;
  10602. +
  10603. + bstart = dbstart(dentry);
  10604. + LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
  10605. + hidden_dentry = au_h_dptr(dentry);
  10606. + if (*bcpup < 0) {
  10607. + *bcpup = bstart;
  10608. + if (test_ro(sb, bstart, dentry->d_inode)) {
  10609. + *bcpup = err = find_rw_parent_br(dentry, bstart);
  10610. + //*bcpup = err = find_rw_br(sb, bstart);
  10611. + //err = -1;
  10612. + if (unlikely(err < 0))
  10613. + goto out;
  10614. + }
  10615. + } else {
  10616. + /* braces are added to stop a warning */
  10617. + DEBUG_ON(bstart < *bcpup
  10618. + || test_ro(sb, *bcpup, dentry->d_inode));
  10619. + }
  10620. + LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
  10621. +
  10622. + if (*bcpup != bstart) {
  10623. + err = cpup_dirs(dentry, *bcpup, locked);
  10624. + //err = -1;
  10625. + if (unlikely(err))
  10626. + goto out;
  10627. + need_wh = 1;
  10628. + } else {
  10629. + //struct nameidata nd;
  10630. + aufs_bindex_t old_bend, new_bend, bdiropq = -1;
  10631. + old_bend = dbend(dentry);
  10632. + if (isdir) {
  10633. + bdiropq = dbdiropq(dentry);
  10634. + set_dbdiropq(dentry, -1);
  10635. + }
  10636. + err = need_wh = lkup_dentry(dentry, bstart + 1, /*type*/0);
  10637. + //err = -1;
  10638. + if (isdir)
  10639. + set_dbdiropq(dentry, bdiropq);
  10640. + if (unlikely(err < 0))
  10641. + goto out;
  10642. + new_bend = dbend(dentry);
  10643. + if (!need_wh && old_bend != new_bend) {
  10644. + set_h_dptr(dentry, new_bend, NULL);
  10645. + set_dbend(dentry, old_bend);
  10646. +#if 0
  10647. + } else if (!au_h_dptr_i(dentry, new_bend)->d_inode) {
  10648. + LKTRTrace("negative\n");
  10649. + set_h_dptr(dentry, new_bend, NULL);
  10650. + set_dbend(dentry, old_bend);
  10651. + need_wh = 0;
  10652. +#endif
  10653. + }
  10654. + }
  10655. + LKTRTrace("need_wh %d\n", need_wh);
  10656. + err = need_wh;
  10657. +
  10658. + out:
  10659. + TraceErr(err);
  10660. + return err;
  10661. +}
  10662. +
  10663. +static struct dentry *
  10664. +lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
  10665. + struct dtime *dt)
  10666. +{
  10667. + struct dentry *wh_dentry;
  10668. + int err, need_wh;
  10669. + struct dentry *hidden_parent, *parent;
  10670. + struct inode *dir, *h_dir;
  10671. + struct lkup_args lkup;
  10672. +
  10673. + LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir);
  10674. +
  10675. + err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL);
  10676. + //err = -1;
  10677. + wh_dentry = ERR_PTR(err);
  10678. + if (unlikely(err < 0))
  10679. + goto out;
  10680. +
  10681. + parent = dentry->d_parent;
  10682. + dir = parent->d_inode;
  10683. + hidden_parent = au_h_dptr_i(parent, *bcpup);
  10684. + h_dir = hidden_parent->d_inode;
  10685. + hdir_lock(h_dir, dir, *bcpup);
  10686. + dtime_store(dt, parent, hidden_parent);
  10687. + if (!need_wh)
  10688. + return NULL; /* success, no need to create whiteout */
  10689. +
  10690. + lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
  10691. + lkup.dlgt = need_dlgt(dentry->d_sb);
  10692. + wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup);
  10693. + //wh_dentry = ERR_PTR(-1);
  10694. + if (!IS_ERR(wh_dentry))
  10695. + goto out; /* success */
  10696. + /* returns with the parent is locked and wh_dentry is DGETed */
  10697. +
  10698. + hdir_unlock(h_dir, dir, *bcpup);
  10699. +
  10700. + out:
  10701. + TraceErrPtr(wh_dentry);
  10702. + return wh_dentry;
  10703. +}
  10704. +
  10705. +static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
  10706. + struct aufs_nhash *whlist, struct inode *dir)
  10707. +{
  10708. + int rmdir_later, err;
  10709. + struct dentry *hidden_dentry;
  10710. +
  10711. + LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
  10712. +
  10713. + err = rename_whtmp(dentry, bindex);
  10714. + //err = -1;
  10715. +#if 0
  10716. + //todo: bug
  10717. + if (unlikely(err)) {
  10718. + au_direval_inc(dentry->d_parent);
  10719. + return err;
  10720. + }
  10721. +#endif
  10722. +
  10723. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  10724. + if (!au_is_nfs(hidden_dentry->d_sb)) {
  10725. + const int dirwh = stosi(dentry->d_sb)->si_dirwh;
  10726. + rmdir_later = (dirwh <= 1);
  10727. + if (!rmdir_later)
  10728. + rmdir_later = is_longer_wh(whlist, bindex, dirwh);
  10729. + if (rmdir_later)
  10730. + return rmdir_later;
  10731. + }
  10732. +
  10733. + err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode);
  10734. + //err = -1;
  10735. + if (unlikely(err)) {
  10736. + IOErr("rmdir %.*s, b%d failed, %d. ignored\n",
  10737. + DLNPair(hidden_dentry), bindex, err);
  10738. + err = 0;
  10739. + }
  10740. + TraceErr(err);
  10741. + return err;
  10742. +}
  10743. +
  10744. +static void epilog(struct inode *dir, struct dentry *dentry,
  10745. + aufs_bindex_t bindex)
  10746. +{
  10747. + d_drop(dentry);
  10748. + dentry->d_inode->i_ctime = dir->i_ctime;
  10749. + if (atomic_read(&dentry->d_count) == 1) {
  10750. + set_h_dptr(dentry, dbstart(dentry), NULL);
  10751. + au_update_dbstart(dentry);
  10752. + }
  10753. + if (ibstart(dir) == bindex)
  10754. + au_cpup_attr_timesizes(dir);
  10755. + dir->i_version++;
  10756. +}
  10757. +
  10758. +static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
  10759. + aufs_bindex_t bwh, struct dtime *dt, int dlgt)
  10760. +{
  10761. + int rerr;
  10762. +
  10763. + rerr = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode, wh_dentry,
  10764. + dentry, dlgt);
  10765. + //rerr = -1;
  10766. + if (!rerr) {
  10767. + set_dbwh(dentry, bwh);
  10768. + dtime_revert(dt, !CPUP_LOCKED_GHDIR);
  10769. + return 0;
  10770. + }
  10771. +
  10772. + IOErr("%.*s reverting whiteout failed(%d, %d)\n",
  10773. + DLNPair(dentry), err, rerr);
  10774. + return -EIO;
  10775. +}
  10776. +
  10777. +/* ---------------------------------------------------------------------- */
  10778. +
  10779. +int aufs_unlink(struct inode *dir, struct dentry *dentry)
  10780. +{
  10781. + int err, dlgt;
  10782. + struct inode *inode, *hidden_dir;
  10783. + struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
  10784. + struct dtime dt;
  10785. + aufs_bindex_t bwh, bindex, bstart;
  10786. + struct super_block *sb;
  10787. +
  10788. + LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  10789. + IMustLock(dir);
  10790. + inode = dentry->d_inode;
  10791. + if (unlikely(!inode))
  10792. + return -ENOENT; // possible?
  10793. + IMustLock(inode);
  10794. +
  10795. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10796. + parent = dentry->d_parent;
  10797. + di_write_lock_parent(parent);
  10798. +
  10799. + bstart = dbstart(dentry);
  10800. + bwh = dbwh(dentry);
  10801. + bindex = -1;
  10802. + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt);
  10803. + //wh_dentry = ERR_PTR(-1);
  10804. + err = PTR_ERR(wh_dentry);
  10805. + if (IS_ERR(wh_dentry))
  10806. + goto out;
  10807. +
  10808. + sb = dir->i_sb;
  10809. + dlgt = need_dlgt(sb);
  10810. + hidden_dentry = au_h_dptr(dentry);
  10811. + dget(hidden_dentry);
  10812. + hidden_parent = hidden_dentry->d_parent;
  10813. + hidden_dir = hidden_parent->d_inode;
  10814. +
  10815. + if (bindex == bstart) {
  10816. + err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
  10817. + //err = -1;
  10818. + } else {
  10819. + DEBUG_ON(!wh_dentry);
  10820. + hidden_parent = wh_dentry->d_parent;
  10821. + DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
  10822. + hidden_dir = hidden_parent->d_inode;
  10823. + IMustLock(hidden_dir);
  10824. + err = 0;
  10825. + }
  10826. +
  10827. + if (!err) {
  10828. + inode->i_nlink--;
  10829. + epilog(dir, dentry, bindex);
  10830. +#if 0
  10831. + xino_write0(sb, bstart, hidden_dentry->d_inode->i_ino);
  10832. + /* ignore this error */
  10833. +#endif
  10834. + goto out_unlock; /* success */
  10835. + }
  10836. +
  10837. + /* revert */
  10838. + if (wh_dentry) {
  10839. + int rerr;
  10840. + rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt);
  10841. + if (rerr)
  10842. + err = rerr;
  10843. + }
  10844. +
  10845. + out_unlock:
  10846. + hdir_unlock(hidden_dir, dir, bindex);
  10847. + dput(wh_dentry);
  10848. + dput(hidden_dentry);
  10849. + out:
  10850. + di_write_unlock(parent);
  10851. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  10852. + TraceErr(err);
  10853. + return err;
  10854. +}
  10855. +
  10856. +int aufs_rmdir(struct inode *dir, struct dentry *dentry)
  10857. +{
  10858. + int err, rmdir_later;
  10859. + struct inode *inode, *hidden_dir;
  10860. + struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
  10861. + struct dtime dt;
  10862. + aufs_bindex_t bwh, bindex, bstart;
  10863. + struct rmdir_whtmp_arg *arg;
  10864. + struct aufs_nhash *whlist;
  10865. + struct super_block *sb;
  10866. +
  10867. + LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  10868. + IMustLock(dir);
  10869. + inode = dentry->d_inode;
  10870. + if (unlikely(!inode))
  10871. + return -ENOENT; // possible?
  10872. + IMustLock(inode);
  10873. +
  10874. + whlist = nhash_new(GFP_KERNEL);
  10875. + err = PTR_ERR(whlist);
  10876. + if (IS_ERR(whlist))
  10877. + goto out;
  10878. +
  10879. + err = -ENOMEM;
  10880. + arg = kmalloc(sizeof(*arg), GFP_KERNEL);
  10881. + //arg = NULL;
  10882. + if (unlikely(!arg))
  10883. + goto out_whlist;
  10884. +
  10885. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10886. + parent = dentry->d_parent;
  10887. + di_write_lock_parent(parent);
  10888. + err = test_empty(dentry, whlist);
  10889. + //err = -1;
  10890. + if (unlikely(err))
  10891. + goto out_arg;
  10892. +
  10893. + bstart = dbstart(dentry);
  10894. + bwh = dbwh(dentry);
  10895. + bindex = -1;
  10896. + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/ 1, &bindex, &dt);
  10897. + //wh_dentry = ERR_PTR(-1);
  10898. + err = PTR_ERR(wh_dentry);
  10899. + if (IS_ERR(wh_dentry))
  10900. + goto out_arg;
  10901. +
  10902. + hidden_dentry = au_h_dptr(dentry);
  10903. + dget(hidden_dentry);
  10904. + hidden_parent = hidden_dentry->d_parent;
  10905. + hidden_dir = hidden_parent->d_inode;
  10906. +
  10907. + rmdir_later = 0;
  10908. + if (bindex == bstart) {
  10909. + IMustLock(hidden_dir);
  10910. + err = renwh_and_rmdir(dentry, bstart, whlist, dir);
  10911. + //err = -1;
  10912. + if (err > 0) {
  10913. + rmdir_later = err;
  10914. + err = 0;
  10915. + }
  10916. + } else {
  10917. + DEBUG_ON(!wh_dentry);
  10918. + hidden_parent = wh_dentry->d_parent;
  10919. + DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
  10920. + hidden_dir = hidden_parent->d_inode;
  10921. + IMustLock(hidden_dir);
  10922. + err = 0;
  10923. + }
  10924. +
  10925. + sb = dentry->d_sb;
  10926. + if (!err) {
  10927. + //aufs_bindex_t bi, bend;
  10928. +
  10929. + au_reset_hinotify(inode, /*flags*/0);
  10930. + inode->i_nlink = 0;
  10931. + set_dbdiropq(dentry, -1);
  10932. + epilog(dir, dentry, bindex);
  10933. +
  10934. + if (rmdir_later) {
  10935. + kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir,
  10936. + inode, arg);
  10937. + arg = NULL;
  10938. + }
  10939. +
  10940. +#if 0
  10941. + bend = dbend(dentry);
  10942. + for (bi = bstart; bi <= bend; bi++) {
  10943. + struct dentry *hd;
  10944. + hd = au_h_dptr_i(dentry, bi);
  10945. + if (hd && hd->d_inode)
  10946. + xino_write0(sb, bi, hd->d_inode->i_ino);
  10947. + /* ignore this error */
  10948. + }
  10949. +#endif
  10950. +
  10951. + goto out_unlock; /* success */
  10952. + }
  10953. +
  10954. + /* revert */
  10955. + LKTRLabel(revert);
  10956. + if (wh_dentry) {
  10957. + int rerr;
  10958. + rerr = do_revert(err, wh_dentry, dentry, bwh, &dt,
  10959. + need_dlgt(sb));
  10960. + if (rerr)
  10961. + err = rerr;
  10962. + }
  10963. +
  10964. + out_unlock:
  10965. + hdir_unlock(hidden_dir, dir, bindex);
  10966. + dput(wh_dentry);
  10967. + dput(hidden_dentry);
  10968. + out_arg:
  10969. + di_write_unlock(parent);
  10970. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  10971. + kfree(arg);
  10972. + out_whlist:
  10973. + nhash_del(whlist);
  10974. + out:
  10975. + TraceErr(err);
  10976. + return err;
  10977. +}
  10978. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/i_op_ren.c linux-2.6.22.1/fs/aufs/i_op_ren.c
  10979. --- linux-2.6.22.1.oorig/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
  10980. +++ linux-2.6.22.1/fs/aufs/i_op_ren.c 2007-07-24 14:17:46.000000000 +0200
  10981. @@ -0,0 +1,637 @@
  10982. +/*
  10983. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  10984. + *
  10985. + * This program, aufs is free software; you can redistribute it and/or modify
  10986. + * it under the terms of the GNU General Public License as published by
  10987. + * the Free Software Foundation; either version 2 of the License, or
  10988. + * (at your option) any later version.
  10989. + *
  10990. + * This program is distributed in the hope that it will be useful,
  10991. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10992. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10993. + * GNU General Public License for more details.
  10994. + *
  10995. + * You should have received a copy of the GNU General Public License
  10996. + * along with this program; if not, write to the Free Software
  10997. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  10998. + */
  10999. +
  11000. +/* $Id: i_op_ren.c,v 1.39 2007/05/14 03:41:52 sfjro Exp $ */
  11001. +
  11002. +//#include <linux/fs.h>
  11003. +//#include <linux/namei.h>
  11004. +#include "aufs.h"
  11005. +
  11006. +enum {SRC, DST};
  11007. +struct rename_args {
  11008. + struct dentry *hidden_dentry[2], *parent[2], *hidden_parent[2];
  11009. + struct aufs_nhash whlist;
  11010. + aufs_bindex_t btgt, bstart[2];
  11011. + struct super_block *sb;
  11012. +
  11013. + unsigned int isdir:1;
  11014. + unsigned int issamedir:1;
  11015. + unsigned int whsrc:1;
  11016. + unsigned int whdst:1;
  11017. + unsigned int dlgt:1;
  11018. +} __attribute__((aligned(sizeof(long))));
  11019. +
  11020. +static int do_rename(struct inode *src_dir, struct dentry *src_dentry,
  11021. + struct inode *dir, struct dentry *dentry,
  11022. + struct rename_args *a)
  11023. +{
  11024. + int err, need_diropq, bycpup, rerr;
  11025. + struct rmdir_whtmp_arg *tharg;
  11026. + struct dentry *wh_dentry[2], *hidden_dst, *hg_parent;
  11027. + struct inode *hidden_dir[2];
  11028. + aufs_bindex_t bindex, bend;
  11029. + unsigned int flags;
  11030. + struct lkup_args lkup = {.dlgt = a->dlgt};
  11031. +
  11032. + LKTRTrace("%.*s/%.*s, %.*s/%.*s, "
  11033. + "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, "
  11034. + "flags{%d, %d, %d, %d}\n",
  11035. + DLNPair(a->parent[SRC]), DLNPair(src_dentry),
  11036. + DLNPair(a->parent[DST]), DLNPair(dentry),
  11037. + a->hidden_dentry[SRC], a->hidden_dentry[DST],
  11038. + a->hidden_parent[SRC], a->hidden_parent[DST],
  11039. + &a->whlist, a->btgt,
  11040. + a->bstart[SRC], a->bstart[DST],
  11041. + a->isdir, a->issamedir, a->whsrc, a->whdst);
  11042. + hidden_dir[SRC] = a->hidden_parent[SRC]->d_inode;
  11043. + hidden_dir[DST] = a->hidden_parent[DST]->d_inode;
  11044. + IMustLock(hidden_dir[SRC]);
  11045. + IMustLock(hidden_dir[DST]);
  11046. +
  11047. + /* prepare workqueue arg */
  11048. + hidden_dst = NULL;
  11049. + tharg = NULL;
  11050. + if (a->isdir && a->hidden_dentry[DST]->d_inode) {
  11051. + err = -ENOMEM;
  11052. + tharg = kmalloc(sizeof(*tharg), GFP_KERNEL);
  11053. + //tharg = NULL;
  11054. + if (unlikely(!tharg))
  11055. + goto out;
  11056. + hidden_dst = dget(a->hidden_dentry[DST]);
  11057. + }
  11058. +
  11059. + wh_dentry[SRC] = wh_dentry[DST] = NULL;
  11060. + lkup.nfsmnt = au_nfsmnt(a->sb, a->btgt);
  11061. + /* create whiteout for src_dentry */
  11062. + if (a->whsrc) {
  11063. + wh_dentry[SRC] = simple_create_wh(src_dentry, a->btgt,
  11064. + a->hidden_parent[SRC], &lkup);
  11065. + //wh_dentry[SRC] = ERR_PTR(-1);
  11066. + err = PTR_ERR(wh_dentry[SRC]);
  11067. + if (IS_ERR(wh_dentry[SRC]))
  11068. + goto out_tharg;
  11069. + }
  11070. +
  11071. + /* lookup whiteout for dentry */
  11072. + if (a->whdst) {
  11073. + struct dentry *d;
  11074. + d = lkup_wh(a->hidden_parent[DST], &dentry->d_name, &lkup);
  11075. + //d = ERR_PTR(-1);
  11076. + err = PTR_ERR(d);
  11077. + if (IS_ERR(d))
  11078. + goto out_whsrc;
  11079. + if (!d->d_inode)
  11080. + dput(d);
  11081. + else
  11082. + wh_dentry[DST] = d;
  11083. + }
  11084. +
  11085. + /* rename dentry to tmpwh */
  11086. + if (tharg) {
  11087. + err = rename_whtmp(dentry, a->btgt);
  11088. + //err = -1;
  11089. + if (unlikely(err))
  11090. + goto out_whdst;
  11091. + set_h_dptr(dentry, a->btgt, NULL);
  11092. + err = lkup_neg(dentry, a->btgt);
  11093. + //err = -1;
  11094. + if (unlikely(err))
  11095. + goto out_whtmp;
  11096. + a->hidden_dentry[DST] = au_h_dptr_i(dentry, a->btgt);
  11097. + }
  11098. +
  11099. + /* cpup src */
  11100. + if (a->hidden_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) {
  11101. + flags = au_flags_cpup(!CPUP_DTIME, a->parent[SRC]);
  11102. + hg_parent = a->hidden_parent[SRC]->d_parent;
  11103. + if (!(flags & CPUP_LOCKED_GHDIR)
  11104. + && hg_parent == a->hidden_parent[DST])
  11105. + flags |= CPUP_LOCKED_GHDIR;
  11106. +
  11107. + hi_lock_child(a->hidden_dentry[SRC]->d_inode);
  11108. + err = sio_cpup_simple(src_dentry, a->btgt, -1, flags);
  11109. + //err = -1; // untested dir
  11110. + i_unlock(a->hidden_dentry[SRC]->d_inode);
  11111. + if (unlikely(err))
  11112. + goto out_whtmp;
  11113. + }
  11114. +
  11115. +#if 0
  11116. + /* clear the target ino in xino */
  11117. + LKTRTrace("dir %d, dst inode %p\n", a->isdir, a->hidden_dentry[DST]->d_inode);
  11118. + if (a->isdir && a->hidden_dentry[DST]->d_inode) {
  11119. + Dbg("here\n");
  11120. + err = xino_write(a->sb, a->btgt,
  11121. + a->hidden_dentry[DST]->d_inode->i_ino, 0);
  11122. + if (unlikely(err))
  11123. + goto out_whtmp;
  11124. + }
  11125. +#endif
  11126. +
  11127. + /* rename by vfs_rename or cpup */
  11128. + need_diropq = a->isdir
  11129. + && (wh_dentry[DST]
  11130. + || dbdiropq(dentry) == a->btgt
  11131. + || au_flag_test(a->sb, AuFlag_ALWAYS_DIROPQ));
  11132. + bycpup = 0;
  11133. + if (dbstart(src_dentry) == a->btgt) {
  11134. + if (need_diropq && dbdiropq(src_dentry) == a->btgt)
  11135. + need_diropq = 0;
  11136. + err = vfsub_rename(hidden_dir[SRC], au_h_dptr(src_dentry),
  11137. + hidden_dir[DST], a->hidden_dentry[DST],
  11138. + a->dlgt);
  11139. + //err = -1;
  11140. + } else {
  11141. + bycpup = 1;
  11142. + flags = au_flags_cpup(!CPUP_DTIME, a->parent[DST]);
  11143. + hg_parent = a->hidden_parent[DST]->d_parent;
  11144. + if (!(flags & CPUP_LOCKED_GHDIR)
  11145. + && hg_parent == a->hidden_parent[SRC])
  11146. + flags |= CPUP_LOCKED_GHDIR;
  11147. +
  11148. + hi_lock_child(a->hidden_dentry[SRC]->d_inode);
  11149. + set_dbstart(src_dentry, a->btgt);
  11150. + set_h_dptr(src_dentry, a->btgt, dget(a->hidden_dentry[DST]));
  11151. + //DbgDentry(src_dentry);
  11152. + //DbgInode(src_dentry->d_inode);
  11153. + err = sio_cpup_single(src_dentry, a->btgt, a->bstart[SRC], -1,
  11154. + flags);
  11155. + //err = -1; // untested dir
  11156. + if (unlikely(err)) {
  11157. + set_h_dptr(src_dentry, a->btgt, NULL);
  11158. + set_dbstart(src_dentry, a->bstart[SRC]);
  11159. + }
  11160. + i_unlock(a->hidden_dentry[SRC]->d_inode);
  11161. + }
  11162. + if (unlikely(err))
  11163. + goto out_whtmp;
  11164. +
  11165. + /* make dir opaque */
  11166. + if (need_diropq) {
  11167. + struct dentry *diropq;
  11168. + struct inode *h_inode;
  11169. +
  11170. + h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
  11171. + hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
  11172. + diropq = create_diropq(src_dentry, a->btgt, a->dlgt);
  11173. + //diropq = ERR_PTR(-1);
  11174. + hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
  11175. + err = PTR_ERR(diropq);
  11176. + if (IS_ERR(diropq))
  11177. + goto out_rename;
  11178. + dput(diropq);
  11179. + }
  11180. +
  11181. + /* remove whiteout for dentry */
  11182. + if (wh_dentry[DST]) {
  11183. + err = au_unlink_wh_dentry(hidden_dir[DST], wh_dentry[DST],
  11184. + dentry, a->dlgt);
  11185. + //err = -1;
  11186. + if (unlikely(err))
  11187. + goto out_diropq;
  11188. + }
  11189. +
  11190. + /* remove whtmp */
  11191. + if (tharg) {
  11192. + if (au_is_nfs(hidden_dst->d_sb)
  11193. + || !is_longer_wh(&a->whlist, a->btgt,
  11194. + stosi(a->sb)->si_dirwh)) {
  11195. + err = rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
  11196. + dentry->d_inode);
  11197. + if (unlikely(err))
  11198. + Warn("failed removing whtmp dir %.*s (%d), "
  11199. + "ignored.\n", DLNPair(hidden_dst), err);
  11200. + } else {
  11201. + kick_rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
  11202. + dentry->d_inode, tharg);
  11203. + dput(hidden_dst);
  11204. + tharg = NULL;
  11205. + }
  11206. + }
  11207. + err = 0;
  11208. + goto out_success;
  11209. +
  11210. +#define RevertFailure(fmt, args...) do { \
  11211. + IOErrWhck("revert failure: " fmt " (%d, %d)\n", \
  11212. + ##args, err, rerr); \
  11213. + err = -EIO; \
  11214. + } while(0)
  11215. +
  11216. + out_diropq:
  11217. + if (need_diropq) {
  11218. + struct inode *h_inode;
  11219. +
  11220. + h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
  11221. + // i_lock simplly since inotify is not set to h_inode.
  11222. + hi_lock_parent(h_inode);
  11223. + //hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
  11224. + rerr = remove_diropq(src_dentry, a->btgt, a->dlgt);
  11225. + //rerr = -1;
  11226. + //hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
  11227. + i_unlock(h_inode);
  11228. + if (rerr)
  11229. + RevertFailure("remove diropq %.*s",
  11230. + DLNPair(src_dentry));
  11231. + }
  11232. + out_rename:
  11233. + if (!bycpup) {
  11234. + struct dentry *d;
  11235. + struct qstr *name = &src_dentry->d_name;
  11236. + d = lkup_one(name->name, a->hidden_parent[SRC], name->len,
  11237. + &lkup);
  11238. + //d = ERR_PTR(-1);
  11239. + rerr = PTR_ERR(d);
  11240. + if (IS_ERR(d)) {
  11241. + RevertFailure("lkup_one %.*s", DLNPair(src_dentry));
  11242. + goto out_whtmp;
  11243. + }
  11244. + DEBUG_ON(d->d_inode);
  11245. + rerr = vfsub_rename
  11246. + (hidden_dir[DST], au_h_dptr_i(src_dentry, a->btgt),
  11247. + hidden_dir[SRC], d, a->dlgt);
  11248. + //rerr = -1;
  11249. + d_drop(d);
  11250. + dput(d);
  11251. + //set_h_dptr(src_dentry, a->btgt, NULL);
  11252. + if (rerr)
  11253. + RevertFailure("rename %.*s", DLNPair(src_dentry));
  11254. + } else {
  11255. + rerr = vfsub_unlink(hidden_dir[DST], a->hidden_dentry[DST],
  11256. + a->dlgt);
  11257. + //rerr = -1;
  11258. + set_h_dptr(src_dentry, a->btgt, NULL);
  11259. + set_dbstart(src_dentry, a->bstart[SRC]);
  11260. + if (rerr)
  11261. + RevertFailure("unlink %.*s",
  11262. + DLNPair(a->hidden_dentry[DST]));
  11263. + }
  11264. + out_whtmp:
  11265. + if (tharg) {
  11266. + struct dentry *d;
  11267. + struct qstr *name = &dentry->d_name;
  11268. + LKTRLabel(here);
  11269. + d = lkup_one(name->name, a->hidden_parent[DST], name->len,
  11270. + &lkup);
  11271. + //d = ERR_PTR(-1);
  11272. + rerr = PTR_ERR(d);
  11273. + if (IS_ERR(d)) {
  11274. + RevertFailure("lookup %.*s", LNPair(name));
  11275. + goto out_whdst;
  11276. + }
  11277. + if (d->d_inode) {
  11278. + d_drop(d);
  11279. + dput(d);
  11280. + goto out_whdst;
  11281. + }
  11282. + DEBUG_ON(d->d_inode);
  11283. + rerr = vfsub_rename(hidden_dir[DST], hidden_dst,
  11284. + hidden_dir[DST], d, a->dlgt);
  11285. + //rerr = -1;
  11286. + d_drop(d);
  11287. + dput(d);
  11288. + if (rerr) {
  11289. + RevertFailure("rename %.*s", DLNPair(hidden_dst));
  11290. + goto out_whdst;
  11291. + }
  11292. + set_h_dptr(dentry, a->btgt, NULL);
  11293. + set_h_dptr(dentry, a->btgt, dget(hidden_dst));
  11294. + }
  11295. + out_whdst:
  11296. + dput(wh_dentry[DST]);
  11297. + wh_dentry[DST] = NULL;
  11298. + out_whsrc:
  11299. + if (wh_dentry[SRC]) {
  11300. + LKTRLabel(here);
  11301. + rerr = au_unlink_wh_dentry(hidden_dir[SRC], wh_dentry[SRC],
  11302. + src_dentry, a->dlgt);
  11303. + //rerr = -1;
  11304. + if (rerr)
  11305. + RevertFailure("unlink %.*s", DLNPair(wh_dentry[SRC]));
  11306. + }
  11307. +#undef RevertFailure
  11308. + d_drop(src_dentry);
  11309. + bend = dbend(src_dentry);
  11310. + for (bindex = dbstart(src_dentry); bindex <= bend; bindex++) {
  11311. + struct dentry *hd;
  11312. + hd = au_h_dptr_i(src_dentry, bindex);
  11313. + if (hd)
  11314. + d_drop(hd);
  11315. + }
  11316. + d_drop(dentry);
  11317. + bend = dbend(dentry);
  11318. + for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
  11319. + struct dentry *hd;
  11320. + hd = au_h_dptr_i(dentry, bindex);
  11321. + if (hd)
  11322. + d_drop(hd);
  11323. + }
  11324. + au_update_dbstart(dentry);
  11325. + if (tharg)
  11326. + d_drop(hidden_dst);
  11327. + out_success:
  11328. + dput(wh_dentry[SRC]);
  11329. + dput(wh_dentry[DST]);
  11330. + out_tharg:
  11331. + if (tharg) {
  11332. + dput(hidden_dst);
  11333. + kfree(tharg);
  11334. + }
  11335. + out:
  11336. + TraceErr(err);
  11337. + return err;
  11338. +}
  11339. +
  11340. +/*
  11341. + * test if @dentry dir can be rename destination or not.
  11342. + * success means, it is a logically empty dir.
  11343. + */
  11344. +static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt,
  11345. + struct aufs_nhash *whlist)
  11346. +{
  11347. + LKTRTrace("%.*s\n", DLNPair(dentry));
  11348. +
  11349. + return test_empty(dentry, whlist);
  11350. +}
  11351. +
  11352. +/*
  11353. + * test if @dentry dir can be rename source or not.
  11354. + * if it can, return 0 and @children is filled.
  11355. + * success means,
  11356. + * - or, it is a logically empty dir.
  11357. + * - or, it exists on writable branch and has no children including whiteouts
  11358. + * on the lower branch.
  11359. + */
  11360. +static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
  11361. +{
  11362. + int err;
  11363. + aufs_bindex_t bstart;
  11364. +
  11365. + LKTRTrace("%.*s\n", DLNPair(dentry));
  11366. +
  11367. + bstart = dbstart(dentry);
  11368. + if (bstart != btgt) {
  11369. + struct aufs_nhash *whlist;
  11370. +
  11371. + whlist = nhash_new(GFP_KERNEL);
  11372. + err = PTR_ERR(whlist);
  11373. + if (IS_ERR(whlist))
  11374. + goto out;
  11375. + err = test_empty(dentry, whlist);
  11376. + nhash_del(whlist);
  11377. + goto out;
  11378. + }
  11379. +
  11380. + if (bstart == dbtaildir(dentry))
  11381. + return 0; /* success */
  11382. +
  11383. + err = au_test_empty_lower(dentry);
  11384. +
  11385. + out:
  11386. + if (/* unlikely */(err == -ENOTEMPTY))
  11387. + err = -EXDEV;
  11388. + TraceErr(err);
  11389. + return err;
  11390. +}
  11391. +
  11392. +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
  11393. + struct inode *dir, struct dentry *dentry)
  11394. +{
  11395. + int err, do_dt_dstdir;
  11396. + aufs_bindex_t bend, bindex;
  11397. + struct inode *inode, *dirs[2];
  11398. + enum {PARENT, CHILD};
  11399. + /* reduce stack space */
  11400. + struct {
  11401. + struct rename_args a;
  11402. + struct dtime dt[2][2];
  11403. + } *p;
  11404. +
  11405. + LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
  11406. + src_dir->i_ino, DLNPair(src_dentry),
  11407. + dir->i_ino, DLNPair(dentry));
  11408. + IMustLock(src_dir);
  11409. + IMustLock(dir);
  11410. + /* braces are added to stop a warning */
  11411. + if (dentry->d_inode) {
  11412. + IMustLock(dentry->d_inode);
  11413. + }
  11414. +
  11415. + err = -ENOMEM;
  11416. + BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE);
  11417. + p = kmalloc(sizeof(*p), GFP_KERNEL);
  11418. + if (unlikely(!p))
  11419. + goto out;
  11420. +
  11421. + err = -ENOTDIR;
  11422. + p->a.sb = src_dentry->d_sb;
  11423. + inode = src_dentry->d_inode;
  11424. + p->a.isdir = !!S_ISDIR(inode->i_mode);
  11425. + if (unlikely(p->a.isdir && dentry->d_inode
  11426. + && !S_ISDIR(dentry->d_inode->i_mode)))
  11427. + goto out_free;
  11428. +
  11429. + aufs_read_and_write_lock2(dentry, src_dentry, p->a.isdir);
  11430. + p->a.dlgt = !!need_dlgt(p->a.sb);
  11431. + p->a.parent[SRC] = p->a.parent[DST] = dentry->d_parent;
  11432. + p->a.issamedir = (src_dir == dir);
  11433. + if (p->a.issamedir)
  11434. + di_write_lock_parent(p->a.parent[DST]);
  11435. + else {
  11436. + p->a.parent[SRC] = src_dentry->d_parent;
  11437. + di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST],
  11438. + /*isdir*/1);
  11439. + }
  11440. +
  11441. + /* which branch we process */
  11442. + p->a.bstart[DST] = dbstart(dentry);
  11443. + p->a.btgt = err = wr_dir(dentry, 1, src_dentry, /*force_btgt*/-1,
  11444. + /*do_lock_srcdir*/0);
  11445. + if (unlikely(err < 0))
  11446. + goto out_unlock;
  11447. +
  11448. + /* are they available to be renamed */
  11449. + err = 0;
  11450. + nhash_init(&p->a.whlist);
  11451. + if (p->a.isdir && dentry->d_inode) {
  11452. + set_dbstart(dentry, p->a.bstart[DST]);
  11453. + err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist);
  11454. + set_dbstart(dentry, p->a.btgt);
  11455. + }
  11456. + p->a.hidden_dentry[DST] = au_h_dptr(dentry);
  11457. + if (unlikely(err))
  11458. + goto out_unlock;
  11459. + //todo: minor optimize, their sb may be same while their bindex differs.
  11460. + p->a.bstart[SRC] = dbstart(src_dentry);
  11461. + p->a.hidden_dentry[SRC] = au_h_dptr(src_dentry);
  11462. + if (p->a.isdir) {
  11463. + err = may_rename_srcdir(src_dentry, p->a.btgt);
  11464. + if (unlikely(err))
  11465. + goto out_children;
  11466. + }
  11467. +
  11468. + /* prepare the writable parent dir on the same branch */
  11469. + err = wr_dir_need_wh(src_dentry, p->a.isdir, &p->a.btgt,
  11470. + p->a.issamedir ? NULL : p->a.parent[DST]);
  11471. + if (unlikely(err < 0))
  11472. + goto out_children;
  11473. + p->a.whsrc = !!err;
  11474. + p->a.whdst = (p->a.bstart[DST] == p->a.btgt);
  11475. + if (!p->a.whdst) {
  11476. + err = cpup_dirs(dentry, p->a.btgt,
  11477. + p->a.issamedir ? NULL : p->a.parent[SRC]);
  11478. + if (unlikely(err))
  11479. + goto out_children;
  11480. + }
  11481. +
  11482. + p->a.hidden_parent[SRC] = au_h_dptr_i(p->a.parent[SRC], p->a.btgt);
  11483. + p->a.hidden_parent[DST] = au_h_dptr_i(p->a.parent[DST], p->a.btgt);
  11484. + dirs[0] = src_dir;
  11485. + dirs[1] = dir;
  11486. + hdir_lock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
  11487. +
  11488. + /* store timestamps to be revertible */
  11489. + dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC],
  11490. + p->a.hidden_parent[SRC]);
  11491. + if (!p->a.issamedir)
  11492. + dtime_store(p->dt[PARENT] + DST, p->a.parent[DST],
  11493. + p->a.hidden_parent[DST]);
  11494. + do_dt_dstdir = 0;
  11495. + if (p->a.isdir) {
  11496. + dtime_store(p->dt[CHILD] + SRC, src_dentry,
  11497. + p->a.hidden_dentry[SRC]);
  11498. + if (p->a.hidden_dentry[DST]->d_inode) {
  11499. + do_dt_dstdir = 1;
  11500. + dtime_store(p->dt[CHILD] + DST, dentry,
  11501. + p->a.hidden_dentry[DST]);
  11502. + }
  11503. + }
  11504. +
  11505. + err = do_rename(src_dir, src_dentry, dir, dentry, &p->a);
  11506. + if (unlikely(err))
  11507. + goto out_dt;
  11508. + hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
  11509. +
  11510. + /* update dir attributes */
  11511. + dir->i_version++;
  11512. + if (p->a.isdir)
  11513. + au_cpup_attr_nlink(dir);
  11514. + if (ibstart(dir) == p->a.btgt)
  11515. + au_cpup_attr_timesizes(dir);
  11516. +
  11517. + if (!p->a.issamedir) {
  11518. + src_dir->i_version++;
  11519. + if (p->a.isdir)
  11520. + au_cpup_attr_nlink(src_dir);
  11521. + if (ibstart(src_dir) == p->a.btgt)
  11522. + au_cpup_attr_timesizes(src_dir);
  11523. + }
  11524. +
  11525. + // is this updating defined in POSIX?
  11526. + if (unlikely(p->a.isdir)) {
  11527. + //i_lock(inode);
  11528. + au_cpup_attr_timesizes(inode);
  11529. + //i_unlock(inode);
  11530. + }
  11531. +
  11532. +#if 0
  11533. + d_drop(src_dentry);
  11534. +#else
  11535. + /* dput/iput all lower dentries */
  11536. + set_dbwh(src_dentry, -1);
  11537. + bend = dbend(src_dentry);
  11538. + for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
  11539. + struct dentry *hd;
  11540. + hd = au_h_dptr_i(src_dentry, bindex);
  11541. + if (hd)
  11542. + set_h_dptr(src_dentry, bindex, NULL);
  11543. + }
  11544. + set_dbend(src_dentry, p->a.btgt);
  11545. +
  11546. + bend = ibend(inode);
  11547. + for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
  11548. + struct inode *hi;
  11549. + hi = au_h_iptr_i(inode, bindex);
  11550. + if (hi)
  11551. + set_h_iptr(inode, bindex, NULL, 0);
  11552. + }
  11553. + set_ibend(inode, p->a.btgt);
  11554. +#endif
  11555. +
  11556. +#if 0
  11557. + //au_debug_on();
  11558. + //DbgDentry(dentry);
  11559. + //DbgInode(dentry->d_inode);
  11560. + //au_debug_off();
  11561. + inode = dentry->d_inode;
  11562. + if (inode) {
  11563. + aufs_bindex_t bindex, bend;
  11564. + struct dentry *hd;
  11565. + bend = dbend(dentry);
  11566. + for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
  11567. + hd = au_h_dptr_i(dentry, bindex);
  11568. + if (hd && hd->d_inode)
  11569. + xino_write0(p->a.sb, bindex, hd->d_inode->i_ino);
  11570. + /* ignore this error */
  11571. + }
  11572. + }
  11573. +#endif
  11574. +
  11575. + goto out_children; /* success */
  11576. +
  11577. + out_dt:
  11578. + dtime_revert(p->dt[PARENT] + SRC,
  11579. + p->a.hidden_parent[SRC]->d_parent
  11580. + == p->a.hidden_parent[DST]);
  11581. + if (!p->a.issamedir)
  11582. + dtime_revert(p->dt[PARENT] + DST,
  11583. + p->a.hidden_parent[DST]->d_parent
  11584. + == p->a.hidden_parent[SRC]);
  11585. + if (p->a.isdir && err != -EIO) {
  11586. + struct dentry *hd;
  11587. +
  11588. + hd = p->dt[CHILD][SRC].dt_h_dentry;
  11589. + hi_lock_child(hd->d_inode);
  11590. + dtime_revert(p->dt[CHILD] + SRC, 1);
  11591. + i_unlock(hd->d_inode);
  11592. + if (do_dt_dstdir) {
  11593. + hd = p->dt[CHILD][DST].dt_h_dentry;
  11594. + hi_lock_child(hd->d_inode);
  11595. + dtime_revert(p->dt[CHILD] + DST, 1);
  11596. + i_unlock(hd->d_inode);
  11597. + }
  11598. + }
  11599. + hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
  11600. + out_children:
  11601. + nhash_fin(&p->a.whlist);
  11602. + out_unlock:
  11603. + //if (unlikely(err /* && p->a.isdir */)) {
  11604. + if (unlikely(err && p->a.isdir)) {
  11605. + au_update_dbstart(dentry);
  11606. + d_drop(dentry);
  11607. + }
  11608. + if (p->a.issamedir)
  11609. + di_write_unlock(p->a.parent[DST]);
  11610. + else
  11611. + di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]);
  11612. + aufs_read_and_write_unlock2(dentry, src_dentry);
  11613. + out_free:
  11614. + kfree(p);
  11615. + out:
  11616. + TraceErr(err);
  11617. + return err;
  11618. +}
  11619. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/iinfo.c linux-2.6.22.1/fs/aufs/iinfo.c
  11620. --- linux-2.6.22.1.oorig/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
  11621. +++ linux-2.6.22.1/fs/aufs/iinfo.c 2007-07-24 14:17:46.000000000 +0200
  11622. @@ -0,0 +1,286 @@
  11623. +/*
  11624. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  11625. + *
  11626. + * This program, aufs is free software; you can redistribute it and/or modify
  11627. + * it under the terms of the GNU General Public License as published by
  11628. + * the Free Software Foundation; either version 2 of the License, or
  11629. + * (at your option) any later version.
  11630. + *
  11631. + * This program is distributed in the hope that it will be useful,
  11632. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11633. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11634. + * GNU General Public License for more details.
  11635. + *
  11636. + * You should have received a copy of the GNU General Public License
  11637. + * along with this program; if not, write to the Free Software
  11638. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  11639. + */
  11640. +
  11641. +/* $Id: iinfo.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
  11642. +
  11643. +//#include <linux/mm.h>
  11644. +#include "aufs.h"
  11645. +
  11646. +struct aufs_iinfo *itoii(struct inode *inode)
  11647. +{
  11648. + struct aufs_iinfo *iinfo;
  11649. +
  11650. + iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
  11651. + /* bad_inode case */
  11652. + if (unlikely(!iinfo->ii_hinode))
  11653. + return NULL;
  11654. + DEBUG_ON(!iinfo->ii_hinode
  11655. + /* || stosi(inode->i_sb)->si_bend < iinfo->ii_bend */
  11656. + || iinfo->ii_bend < iinfo->ii_bstart);
  11657. + return iinfo;
  11658. +}
  11659. +
  11660. +aufs_bindex_t ibstart(struct inode *inode)
  11661. +{
  11662. + IiMustAnyLock(inode);
  11663. + return itoii(inode)->ii_bstart;
  11664. +}
  11665. +
  11666. +aufs_bindex_t ibend(struct inode *inode)
  11667. +{
  11668. + IiMustAnyLock(inode);
  11669. + return itoii(inode)->ii_bend;
  11670. +}
  11671. +
  11672. +struct aufs_vdir *ivdir(struct inode *inode)
  11673. +{
  11674. + IiMustAnyLock(inode);
  11675. + DEBUG_ON(!S_ISDIR(inode->i_mode));
  11676. + return itoii(inode)->ii_vdir;
  11677. +}
  11678. +
  11679. +struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex)
  11680. +{
  11681. + struct inode *hidden_inode;
  11682. +
  11683. + IiMustAnyLock(inode);
  11684. + DEBUG_ON(bindex < 0 || ibend(inode) < bindex);
  11685. + hidden_inode = itoii(inode)->ii_hinode[0 + bindex].hi_inode;
  11686. + DEBUG_ON(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
  11687. + return hidden_inode;
  11688. +}
  11689. +
  11690. +struct inode *au_h_iptr(struct inode *inode)
  11691. +{
  11692. + return au_h_iptr_i(inode, ibstart(inode));
  11693. +}
  11694. +
  11695. +aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex)
  11696. +{
  11697. + IiMustAnyLock(inode);
  11698. + DEBUG_ON(bindex < 0
  11699. + || ibend(inode) < bindex
  11700. + || !itoii(inode)->ii_hinode[0 + bindex].hi_inode);
  11701. + return itoii(inode)->ii_hinode[0 + bindex].hi_id;
  11702. +}
  11703. +
  11704. +// hard/soft set
  11705. +void set_ibstart(struct inode *inode, aufs_bindex_t bindex)
  11706. +{
  11707. + struct aufs_iinfo *iinfo = itoii(inode);
  11708. + struct inode *h_inode;
  11709. +
  11710. + IiMustWriteLock(inode);
  11711. + DEBUG_ON(sbend(inode->i_sb) < bindex);
  11712. + iinfo->ii_bstart = bindex;
  11713. + h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
  11714. + if (h_inode)
  11715. + au_cpup_igen(inode, h_inode);
  11716. +}
  11717. +
  11718. +void set_ibend(struct inode *inode, aufs_bindex_t bindex)
  11719. +{
  11720. + IiMustWriteLock(inode);
  11721. + DEBUG_ON(sbend(inode->i_sb) < bindex
  11722. + || bindex < ibstart(inode));
  11723. + itoii(inode)->ii_bend = bindex;
  11724. +}
  11725. +
  11726. +void set_ivdir(struct inode *inode, struct aufs_vdir *vdir)
  11727. +{
  11728. + IiMustWriteLock(inode);
  11729. + DEBUG_ON(!S_ISDIR(inode->i_mode)
  11730. + || (itoii(inode)->ii_vdir && vdir));
  11731. + itoii(inode)->ii_vdir = vdir;
  11732. +}
  11733. +
  11734. +void aufs_hiput(struct aufs_hinode *hinode)
  11735. +{
  11736. + if (unlikely(hinode->hi_notify))
  11737. + do_free_hinotify(hinode);
  11738. + if (hinode->hi_inode)
  11739. + iput(hinode->hi_inode);
  11740. +}
  11741. +
  11742. +unsigned int au_hi_flags(struct inode *inode, int isdir)
  11743. +{
  11744. + unsigned int flags;
  11745. + struct super_block *sb = inode->i_sb;
  11746. +
  11747. + flags = 0;
  11748. + if (au_flag_test(sb, AuFlag_XINO))
  11749. + flags = AUFS_HI_XINO;
  11750. + if (unlikely(isdir && au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
  11751. + flags |= AUFS_HI_NOTIFY;
  11752. + return flags;
  11753. +}
  11754. +
  11755. +void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
  11756. + struct inode *h_inode, unsigned int flags)
  11757. +{
  11758. + struct aufs_hinode *hinode;
  11759. + struct inode *hi;
  11760. + struct aufs_iinfo *iinfo = itoii(inode);
  11761. +
  11762. + LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
  11763. + inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
  11764. + IiMustWriteLock(inode);
  11765. + hinode = iinfo->ii_hinode + bindex;
  11766. + hi = hinode->hi_inode;
  11767. + DEBUG_ON(bindex < ibstart(inode) || ibend(inode) < bindex
  11768. + || (h_inode && atomic_read(&h_inode->i_count) <= 0)
  11769. + || (h_inode && hi));
  11770. +
  11771. + if (hi)
  11772. + aufs_hiput(hinode);
  11773. + hinode->hi_inode = h_inode;
  11774. + if (h_inode) {
  11775. + int err;
  11776. + struct super_block *sb = inode->i_sb;
  11777. +
  11778. + if (bindex == iinfo->ii_bstart)
  11779. + au_cpup_igen(inode, h_inode);
  11780. + hinode->hi_id = sbr_id(sb, bindex);
  11781. + if (flags & AUFS_HI_XINO) {
  11782. + struct xino xino = {
  11783. + .ino = inode->i_ino,
  11784. + //.h_gen = h_inode->i_generation
  11785. + };
  11786. + //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
  11787. + err = xino_write(sb, bindex, h_inode->i_ino, &xino);
  11788. + if (unlikely(err)) {
  11789. + IOErr1("failed xino_write() %d, force noxino\n",
  11790. + err);
  11791. + au_flag_clr(sb, AuFlag_XINO);
  11792. + }
  11793. + }
  11794. + if (flags & AUFS_HI_NOTIFY) {
  11795. + err = alloc_hinotify(hinode, inode, h_inode);
  11796. + if (unlikely(err))
  11797. + IOErr1("alloc_hinotify() %d\n", err);
  11798. + else {
  11799. + /* braces are added to stop a warning */
  11800. + DEBUG_ON(!hinode->hi_notify);
  11801. + }
  11802. + }
  11803. + }
  11804. +}
  11805. +
  11806. +void au_update_iigen(struct inode *inode)
  11807. +{
  11808. + //IiMustWriteLock(inode);
  11809. + DEBUG_ON(!inode->i_sb);
  11810. + atomic_set(&itoii(inode)->ii_generation, au_sigen(inode->i_sb));
  11811. +}
  11812. +
  11813. +/* it may be called at remount time, too */
  11814. +void au_update_brange(struct inode *inode, int do_put_zero)
  11815. +{
  11816. + struct aufs_iinfo *iinfo;
  11817. +
  11818. + LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
  11819. + IiMustWriteLock(inode);
  11820. +
  11821. + iinfo = itoii(inode);
  11822. + if (unlikely(!iinfo) || iinfo->ii_bstart < 0)
  11823. + return;
  11824. +
  11825. + if (do_put_zero) {
  11826. + aufs_bindex_t bindex;
  11827. + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
  11828. + bindex++) {
  11829. + struct inode *h_i;
  11830. + h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
  11831. + if (h_i && !h_i->i_nlink)
  11832. + set_h_iptr(inode, bindex, NULL, 0);
  11833. + }
  11834. + }
  11835. +
  11836. + iinfo->ii_bstart = -1;
  11837. + while (++iinfo->ii_bstart <= iinfo->ii_bend)
  11838. + if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
  11839. + break;
  11840. + if (iinfo->ii_bstart > iinfo->ii_bend) {
  11841. + iinfo->ii_bend = iinfo->ii_bstart = -1;
  11842. + return;
  11843. + }
  11844. +
  11845. + iinfo->ii_bend++;
  11846. + while (0 <= --iinfo->ii_bend)
  11847. + if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
  11848. + break;
  11849. +}
  11850. +
  11851. +/* ---------------------------------------------------------------------- */
  11852. +
  11853. +int au_iinfo_init(struct inode *inode)
  11854. +{
  11855. + struct aufs_iinfo *iinfo;
  11856. + struct super_block *sb;
  11857. + int nbr, i;
  11858. +
  11859. + sb = inode->i_sb;
  11860. + DEBUG_ON(!sb);
  11861. + iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
  11862. + DEBUG_ON(iinfo->ii_hinode);
  11863. + nbr = sbend(sb) + 1;
  11864. + if (unlikely(!nbr))
  11865. + nbr++;
  11866. + iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_KERNEL);
  11867. + //iinfo->ii_hinode = NULL;
  11868. + if (iinfo->ii_hinode) {
  11869. + for (i = 0; i < nbr; i++)
  11870. + iinfo->ii_hinode[i].hi_id = -1;
  11871. + atomic_set(&iinfo->ii_generation, au_sigen(sb));
  11872. + rw_init_nolock(&iinfo->ii_rwsem);
  11873. + iinfo->ii_bstart = -1;
  11874. + iinfo->ii_bend = -1;
  11875. + iinfo->ii_vdir = NULL;
  11876. + return 0;
  11877. + }
  11878. + return -ENOMEM;
  11879. +}
  11880. +
  11881. +void au_iinfo_fin(struct inode *inode)
  11882. +{
  11883. + struct aufs_iinfo *iinfo;
  11884. +
  11885. + iinfo = itoii(inode);
  11886. + /* bad_inode case */
  11887. + if (unlikely(!iinfo))
  11888. + return;
  11889. +
  11890. + if (unlikely(iinfo->ii_vdir))
  11891. + free_vdir(iinfo->ii_vdir);
  11892. +
  11893. + if (iinfo->ii_bstart >= 0) {
  11894. + aufs_bindex_t bend;
  11895. + struct aufs_hinode *hi;
  11896. + hi = iinfo->ii_hinode + iinfo->ii_bstart;
  11897. + bend = iinfo->ii_bend;
  11898. + while (iinfo->ii_bstart++ <= bend) {
  11899. + if (hi->hi_inode)
  11900. + aufs_hiput(hi);
  11901. + hi++;
  11902. + }
  11903. + //iinfo->ii_bstart = iinfo->ii_bend = -1;
  11904. + }
  11905. +
  11906. + kfree(iinfo->ii_hinode);
  11907. + //iinfo->ii_hinode = NULL;
  11908. +}
  11909. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/inode.c linux-2.6.22.1/fs/aufs/inode.c
  11910. --- linux-2.6.22.1.oorig/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
  11911. +++ linux-2.6.22.1/fs/aufs/inode.c 2007-07-24 14:17:46.000000000 +0200
  11912. @@ -0,0 +1,339 @@
  11913. +/*
  11914. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  11915. + *
  11916. + * This program, aufs is free software; you can redistribute it and/or modify
  11917. + * it under the terms of the GNU General Public License as published by
  11918. + * the Free Software Foundation; either version 2 of the License, or
  11919. + * (at your option) any later version.
  11920. + *
  11921. + * This program is distributed in the hope that it will be useful,
  11922. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11923. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11924. + * GNU General Public License for more details.
  11925. + *
  11926. + * You should have received a copy of the GNU General Public License
  11927. + * along with this program; if not, write to the Free Software
  11928. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  11929. + */
  11930. +
  11931. +/* $Id: inode.c,v 1.22 2007/05/07 03:44:35 sfjro Exp $ */
  11932. +
  11933. +#include "aufs.h"
  11934. +
  11935. +int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
  11936. +{
  11937. + int err, new_sz, update, isdir;
  11938. + struct inode *first;
  11939. + struct aufs_hinode *p, *q, tmp;
  11940. + struct super_block *sb;
  11941. + struct aufs_iinfo *iinfo;
  11942. + aufs_bindex_t bindex, bend, new_bindex;
  11943. + unsigned int flags;
  11944. +
  11945. + LKTRTrace("%.*s\n", DLNPair(dentry));
  11946. + IiMustWriteLock(inode);
  11947. +
  11948. + err = -ENOMEM;
  11949. + sb = dentry->d_sb;
  11950. + bend = sbend(sb);
  11951. + new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1);
  11952. + iinfo = itoii(inode);
  11953. + p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1),
  11954. + new_sz, GFP_KERNEL);
  11955. + //p = NULL;
  11956. + if (unlikely(!p))
  11957. + goto out;
  11958. +
  11959. + iinfo->ii_hinode = p;
  11960. + err = 0;
  11961. + update = 0;
  11962. + p = iinfo->ii_hinode + iinfo->ii_bstart;
  11963. + first = p->hi_inode;
  11964. + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
  11965. + bindex++, p++) {
  11966. + if (unlikely(!p->hi_inode))
  11967. + continue;
  11968. +
  11969. + new_bindex = find_brindex(sb, p->hi_id);
  11970. + if (new_bindex == bindex)
  11971. + continue;
  11972. + if (new_bindex < 0) {
  11973. + update++;
  11974. + aufs_hiput(p);
  11975. + p->hi_inode = NULL;
  11976. + continue;
  11977. + }
  11978. +
  11979. + if (new_bindex < iinfo->ii_bstart)
  11980. + iinfo->ii_bstart = new_bindex;
  11981. + if (iinfo->ii_bend < new_bindex)
  11982. + iinfo->ii_bend = new_bindex;
  11983. + /* swap two hidden inode, and loop again */
  11984. + q = iinfo->ii_hinode + new_bindex;
  11985. + tmp = *q;
  11986. + *q = *p;
  11987. + *p = tmp;
  11988. + if (tmp.hi_inode) {
  11989. + bindex--;
  11990. + p--;
  11991. + }
  11992. + }
  11993. +
  11994. + isdir = S_ISDIR(inode->i_mode);
  11995. + flags = au_hi_flags(inode, isdir);
  11996. + bend = dbend(dentry);
  11997. + for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
  11998. + struct inode *hi;
  11999. + struct dentry *hd;
  12000. +
  12001. + hd = au_h_dptr_i(dentry, bindex);
  12002. + if (!hd || !hd->d_inode)
  12003. + continue;
  12004. +
  12005. + if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
  12006. + hi = au_h_iptr_i(inode, bindex);
  12007. + if (hi) {
  12008. + if (hi == hd->d_inode)
  12009. + continue;
  12010. + //Dbg("here\n");
  12011. + err = -ESTALE;
  12012. + break;
  12013. + }
  12014. + }
  12015. + if (bindex < iinfo->ii_bstart)
  12016. + iinfo->ii_bstart = bindex;
  12017. + if (iinfo->ii_bend < bindex)
  12018. + iinfo->ii_bend = bindex;
  12019. + set_h_iptr(inode, bindex, igrab(hd->d_inode), flags);
  12020. + update++;
  12021. + }
  12022. +
  12023. + bend = iinfo->ii_bend;
  12024. + p = iinfo->ii_hinode;
  12025. + for (bindex = 0; bindex <= bend; bindex++, p++)
  12026. + if (p->hi_inode) {
  12027. + iinfo->ii_bstart = bindex;
  12028. + break;
  12029. + }
  12030. + p = iinfo->ii_hinode + bend;
  12031. + for (bindex = bend; bindex > iinfo->ii_bstart; bindex--, p--)
  12032. + if (p->hi_inode) {
  12033. + iinfo->ii_bend = bindex;
  12034. + break;
  12035. + }
  12036. + DEBUG_ON(iinfo->ii_bstart > bend || iinfo->ii_bend < 0);
  12037. +
  12038. + if (unlikely(err))
  12039. + goto out;
  12040. +
  12041. + if (1 || first != au_h_iptr(inode))
  12042. + au_cpup_attr_all(inode);
  12043. + if (update && isdir)
  12044. + inode->i_version++;
  12045. + au_update_iigen(inode);
  12046. +
  12047. + out:
  12048. + //au_debug_on();
  12049. + TraceErr(err);
  12050. + //au_debug_off();
  12051. + return err;
  12052. +}
  12053. +
  12054. +static int set_inode(struct inode *inode, struct dentry *dentry)
  12055. +{
  12056. + int err, isdir;
  12057. + struct dentry *hidden_dentry;
  12058. + struct inode *hidden_inode;
  12059. + umode_t mode;
  12060. + aufs_bindex_t bindex, bstart, btail;
  12061. + struct aufs_iinfo *iinfo;
  12062. + unsigned int flags;
  12063. +
  12064. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
  12065. + DEBUG_ON(!(inode->i_state & I_NEW));
  12066. + IiMustWriteLock(inode);
  12067. + hidden_dentry = au_h_dptr(dentry);
  12068. + DEBUG_ON(!hidden_dentry);
  12069. + hidden_inode = hidden_dentry->d_inode;
  12070. + DEBUG_ON(!hidden_inode);
  12071. +
  12072. + err = 0;
  12073. + isdir = 0;
  12074. + bstart = dbstart(dentry);
  12075. + mode = hidden_inode->i_mode;
  12076. + switch (mode & S_IFMT) {
  12077. + case S_IFREG:
  12078. + btail = dbtail(dentry);
  12079. + break;
  12080. + case S_IFDIR:
  12081. + isdir = 1;
  12082. + btail = dbtaildir(dentry);
  12083. + inode->i_op = &aufs_dir_iop;
  12084. + inode->i_fop = &aufs_dir_fop;
  12085. + break;
  12086. + case S_IFLNK:
  12087. + btail = dbtail(dentry);
  12088. + inode->i_op = &aufs_symlink_iop;
  12089. + break;
  12090. + case S_IFBLK:
  12091. + case S_IFCHR:
  12092. + case S_IFIFO:
  12093. + case S_IFSOCK:
  12094. + btail = dbtail(dentry);
  12095. + init_special_inode(inode, mode, hidden_inode->i_rdev);
  12096. + break;
  12097. + default:
  12098. + IOErr("Unknown file type 0%o\n", mode);
  12099. + err = -EIO;
  12100. + goto out;
  12101. + }
  12102. +
  12103. + flags = au_hi_flags(inode, isdir);
  12104. + iinfo = itoii(inode);
  12105. + iinfo->ii_bstart = bstart;
  12106. + iinfo->ii_bend = btail;
  12107. + for (bindex = bstart; bindex <= btail; bindex++) {
  12108. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  12109. + if (!hidden_dentry)
  12110. + continue;
  12111. + DEBUG_ON(!hidden_dentry->d_inode);
  12112. + set_h_iptr(inode, bindex, igrab(hidden_dentry->d_inode), flags);
  12113. + }
  12114. + au_cpup_attr_all(inode);
  12115. +
  12116. + out:
  12117. + TraceErr(err);
  12118. + return err;
  12119. +}
  12120. +
  12121. +/* successful returns with iinfo write_locked */
  12122. +//todo: return with unlocked?
  12123. +static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
  12124. +{
  12125. + int err;
  12126. + struct inode *h_inode, *h_dinode;
  12127. + aufs_bindex_t bindex, bend;
  12128. + //const int udba = !au_flag_test(inode->i_sb, AuFlag_UDBA_NONE);
  12129. +
  12130. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
  12131. +
  12132. + *matched = 0;
  12133. +
  12134. + /*
  12135. + * before this function, if aufs got any iinfo lock, it must be only
  12136. + * one, the parent dir.
  12137. + * it can happen by UDBA and the obsoleted inode number.
  12138. + */
  12139. + err = -EIO;
  12140. + if (unlikely(inode->i_ino == parent_ino(dentry)))
  12141. + goto out;
  12142. +
  12143. + h_dinode = au_h_dptr(dentry)->d_inode;
  12144. + hi_lock_child(inode); // bad name, this is not a hidden inode.
  12145. + ii_write_lock_new(inode);
  12146. + bend = ibend(inode);
  12147. + for (bindex = ibstart(inode); bindex <= bend; bindex++) {
  12148. + h_inode = au_h_iptr_i(inode, bindex);
  12149. + if (h_inode && h_inode == h_dinode) {
  12150. + //&& (ibs != bstart || !au_test_higen(inode, h_inode)));
  12151. + *matched = 1;
  12152. + err = 0;
  12153. + if (unlikely(au_iigen(inode) != au_digen(dentry)))
  12154. + err = au_refresh_hinode(inode, dentry);
  12155. + break;
  12156. + }
  12157. + }
  12158. + i_unlock(inode);
  12159. + if (unlikely(err))
  12160. + ii_write_unlock(inode);
  12161. +
  12162. + out:
  12163. + TraceErr(err);
  12164. + return err;
  12165. +}
  12166. +
  12167. +/* successful returns with iinfo write_locked */
  12168. +//todo: return with unlocked?
  12169. +struct inode *au_new_inode(struct dentry *dentry)
  12170. +{
  12171. + struct inode *inode, *h_inode;
  12172. + struct dentry *h_dentry;
  12173. + ino_t h_ino;
  12174. + struct super_block *sb;
  12175. + int err, match;
  12176. + aufs_bindex_t bstart;
  12177. + struct xino xino;
  12178. +
  12179. + LKTRTrace("%.*s\n", DLNPair(dentry));
  12180. + sb = dentry->d_sb;
  12181. + h_dentry = au_h_dptr(dentry);
  12182. + DEBUG_ON(!h_dentry);
  12183. + h_inode = h_dentry->d_inode;
  12184. + DEBUG_ON(!h_inode);
  12185. +
  12186. + bstart = dbstart(dentry);
  12187. + h_ino = h_inode->i_ino;
  12188. + err = xino_read(sb, bstart, h_ino, &xino);
  12189. + //err = -1;
  12190. + inode = ERR_PTR(err);
  12191. + if (unlikely(err))
  12192. + goto out;
  12193. + new_ino:
  12194. + if (!xino.ino) {
  12195. + xino.ino = xino_new_ino(sb);
  12196. + if (!xino.ino) {
  12197. + inode = ERR_PTR(-EIO);
  12198. + goto out;
  12199. + }
  12200. + }
  12201. +
  12202. + LKTRTrace("i%lu\n", xino.ino);
  12203. + err = -ENOMEM;
  12204. + inode = iget_locked(sb, xino.ino);
  12205. + if (unlikely(!inode))
  12206. + goto out;
  12207. + err = PTR_ERR(inode);
  12208. + if (IS_ERR(inode))
  12209. + goto out;
  12210. + err = -ENOMEM;
  12211. + if (unlikely(is_bad_inode(inode)))
  12212. + goto out_iput;
  12213. +
  12214. + LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
  12215. + if (inode->i_state & I_NEW) {
  12216. + sb->s_op->read_inode(inode);
  12217. + if (!is_bad_inode(inode)) {
  12218. + ii_write_lock_new(inode);
  12219. + err = set_inode(inode, dentry);
  12220. + //err = -1;
  12221. + }
  12222. + unlock_new_inode(inode);
  12223. + if (!err)
  12224. + goto out; /* success */
  12225. + ii_write_unlock(inode);
  12226. + goto out_iput;
  12227. + } else {
  12228. + err = reval_inode(inode, dentry, &match);
  12229. + if (!err)
  12230. + goto out; /* success */
  12231. + else if (match)
  12232. + goto out_iput;
  12233. + }
  12234. +
  12235. + Warn1("broken ino, b%d, %.*s/%.*s, hi%lu, i%lu. Try udba=inotify.\n",
  12236. + bstart, DLNPair(dentry->d_parent), DLNPair(dentry), h_ino,
  12237. + xino.ino);
  12238. + xino.ino = 0;
  12239. + err = xino_write0(sb, bstart, h_ino);
  12240. + if (!err) {
  12241. + iput(inode);
  12242. + goto new_ino;
  12243. + }
  12244. +
  12245. + out_iput:
  12246. + iput(inode);
  12247. + inode = ERR_PTR(err);
  12248. + out:
  12249. + TraceErrPtr(inode);
  12250. + return inode;
  12251. +}
  12252. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/inode.h linux-2.6.22.1/fs/aufs/inode.h
  12253. --- linux-2.6.22.1.oorig/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
  12254. +++ linux-2.6.22.1/fs/aufs/inode.h 2007-07-24 14:17:46.000000000 +0200
  12255. @@ -0,0 +1,377 @@
  12256. +/*
  12257. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  12258. + *
  12259. + * This program, aufs is free software; you can redistribute it and/or modify
  12260. + * it under the terms of the GNU General Public License as published by
  12261. + * the Free Software Foundation; either version 2 of the License, or
  12262. + * (at your option) any later version.
  12263. + *
  12264. + * This program is distributed in the hope that it will be useful,
  12265. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12266. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12267. + * GNU General Public License for more details.
  12268. + *
  12269. + * You should have received a copy of the GNU General Public License
  12270. + * along with this program; if not, write to the Free Software
  12271. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  12272. + */
  12273. +
  12274. +/* $Id: inode.h,v 1.32 2007/05/14 03:41:52 sfjro Exp $ */
  12275. +
  12276. +#ifndef __AUFS_INODE_H__
  12277. +#define __AUFS_INODE_H__
  12278. +
  12279. +#ifdef __KERNEL__
  12280. +
  12281. +#include <linux/fs.h>
  12282. +#include <linux/inotify.h>
  12283. +#include <linux/version.h>
  12284. +#include <linux/aufs_type.h>
  12285. +#include "misc.h"
  12286. +#include "vfsub.h"
  12287. +
  12288. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  12289. +#else
  12290. +struct inotify_watch {};
  12291. +#endif
  12292. +
  12293. +/* ---------------------------------------------------------------------- */
  12294. +
  12295. +struct aufs_hinotify {
  12296. + struct inotify_watch hin_watch;
  12297. + struct inode *hin_aufs_inode; /* no get/put */
  12298. +};
  12299. +
  12300. +struct aufs_hinode {
  12301. + struct inode *hi_inode;
  12302. + aufs_bindex_t hi_id;
  12303. + struct aufs_hinotify *hi_notify;
  12304. +};
  12305. +
  12306. +struct aufs_vdir;
  12307. +struct aufs_iinfo {
  12308. + atomic_t ii_generation;
  12309. + struct super_block *ii_hsb1; /* no get/put */
  12310. +
  12311. + struct aufs_rwsem ii_rwsem;
  12312. + aufs_bindex_t ii_bstart, ii_bend;
  12313. + struct aufs_hinode *ii_hinode;
  12314. + struct aufs_vdir *ii_vdir;
  12315. +};
  12316. +
  12317. +struct aufs_icntnr {
  12318. + struct aufs_iinfo iinfo;
  12319. + struct inode vfs_inode;
  12320. +};
  12321. +
  12322. +/* ---------------------------------------------------------------------- */
  12323. +
  12324. +/* inode.c */
  12325. +int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
  12326. +struct inode *au_new_inode(struct dentry *dentry);
  12327. +
  12328. +/* i_op.c */
  12329. +extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
  12330. +int wr_dir(struct dentry *dentry, int negative, struct dentry *src_dentry,
  12331. + aufs_bindex_t force_btgt, int do_lock_srcdir);
  12332. +
  12333. +/* i_op_del.c */
  12334. +int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
  12335. + struct dentry *locked);
  12336. +
  12337. +/* iinfo.c */
  12338. +struct aufs_iinfo *itoii(struct inode *inode);
  12339. +aufs_bindex_t ibstart(struct inode *inode);
  12340. +aufs_bindex_t ibend(struct inode *inode);
  12341. +struct aufs_vdir *ivdir(struct inode *inode);
  12342. +struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex);
  12343. +struct inode *au_h_iptr(struct inode *inode);
  12344. +aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex);
  12345. +
  12346. +void set_ibstart(struct inode *inode, aufs_bindex_t bindex);
  12347. +void set_ibend(struct inode *inode, aufs_bindex_t bindex);
  12348. +void set_ivdir(struct inode *inode, struct aufs_vdir *vdir);
  12349. +void aufs_hiput(struct aufs_hinode *hinode);
  12350. +#define AUFS_HI_XINO 1
  12351. +#define AUFS_HI_NOTIFY 2
  12352. +unsigned int au_hi_flags(struct inode *inode, int isdir);
  12353. +void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
  12354. + struct inode *h_inode, unsigned int flags);
  12355. +void au_update_iigen(struct inode *inode);
  12356. +void au_update_brange(struct inode *inode, int do_put_zero);
  12357. +
  12358. +int au_iinfo_init(struct inode *inode);
  12359. +void au_iinfo_fin(struct inode *inode);
  12360. +
  12361. +/* plink.c */
  12362. +#ifdef CONFIG_AUFS_DEBUG
  12363. +void au_list_plink(struct super_block *sb);
  12364. +#else
  12365. +static inline void au_list_plink(struct super_block *sb)
  12366. +{
  12367. + /* nothing */
  12368. +}
  12369. +#endif
  12370. +int au_is_plinked(struct super_block *sb, struct inode *inode);
  12371. +struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
  12372. + struct inode *inode);
  12373. +void append_plink(struct super_block *sb, struct inode *inode,
  12374. + struct dentry *h_dentry, aufs_bindex_t bindex);
  12375. +void au_put_plink(struct super_block *sb);
  12376. +void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id);
  12377. +
  12378. +/* ---------------------------------------------------------------------- */
  12379. +
  12380. +/* lock subclass for hidden inode */
  12381. +/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
  12382. +// todo: reduce it by dcsub.
  12383. +enum {
  12384. + AuLsc_Begin = I_MUTEX_QUOTA,
  12385. + AuLsc_HI_GPARENT, /* setattr with inotify */
  12386. + AuLsc_HI_PARENT, /* hidden inode, parent first */
  12387. + AuLsc_HI_CHILD,
  12388. + AuLsc_HI_PARENT2, /* copyup dirs */
  12389. + AuLsc_HI_CHILD2,
  12390. + AuLsc_End
  12391. +};
  12392. +
  12393. +/* simple abstraction */
  12394. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
  12395. +static inline void i_lock(struct inode *i)
  12396. +{
  12397. + down(&i->i_sem);
  12398. +}
  12399. +
  12400. +static inline void i_unlock(struct inode *i)
  12401. +{
  12402. + up(&i->i_sem);
  12403. +}
  12404. +
  12405. +static inline int i_trylock(struct inode *i)
  12406. +{
  12407. + return down_trylock(&i->i_sem);
  12408. +}
  12409. +
  12410. +static inline void hi_lock(struct inode *i, unsigned int lsc)
  12411. +{
  12412. + i_lock(i);
  12413. +}
  12414. +
  12415. +#define IMustLock(i) DEBUG_ON(!down_trylock(&(i)->i_sem))
  12416. +#else
  12417. +static inline void i_lock(struct inode *i)
  12418. +{
  12419. + mutex_lock(&i->i_mutex);
  12420. +}
  12421. +
  12422. +static inline void i_unlock(struct inode *i)
  12423. +{
  12424. + mutex_unlock(&i->i_mutex);
  12425. +}
  12426. +
  12427. +static inline int i_trylock(struct inode *i)
  12428. +{
  12429. + return mutex_trylock(&i->i_mutex);
  12430. +}
  12431. +
  12432. +static inline void hi_lock(struct inode *i, unsigned int lsc)
  12433. +{
  12434. + mutex_lock_nested(&i->i_mutex, lsc);
  12435. +}
  12436. +
  12437. +#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
  12438. +#endif
  12439. +
  12440. +/*
  12441. + * hi_lock_gparent, hi_lock_parent, hi_lock_parent2, hi_lock_child,
  12442. + * hi_lock_child2, hi_lock_whplink
  12443. + */
  12444. +#define LockFunc(name, lsc) \
  12445. +static inline void hi_lock_##name(struct inode *h_i) \
  12446. +{hi_lock(h_i, AuLsc_HI_##lsc);}
  12447. +
  12448. +LockFunc(gparent, GPARENT);
  12449. +LockFunc(parent, PARENT);
  12450. +LockFunc(parent2, PARENT2);
  12451. +LockFunc(child, CHILD);
  12452. +LockFunc(child2, CHILD2);
  12453. +LockFunc(whplink, CHILD2); /* sharing lock-subclass */
  12454. +
  12455. +#undef LockFunc
  12456. +
  12457. +/* ---------------------------------------------------------------------- */
  12458. +
  12459. +/* tiny test for inode number */
  12460. +/* tmpfs generation is too rough */
  12461. +static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
  12462. +{
  12463. + //IiMustAnyLock(inode);
  12464. + return !(itoii(inode)->ii_hsb1 == h_inode->i_sb
  12465. + && inode->i_generation == h_inode->i_generation);
  12466. +}
  12467. +
  12468. +static inline int au_iigen(struct inode *inode)
  12469. +{
  12470. + return atomic_read(&itoii(inode)->ii_generation);
  12471. +}
  12472. +
  12473. +#ifdef CONFIG_AUFS_HINOTIFY
  12474. +static inline void au_iigen_dec(struct inode *inode)
  12475. +{
  12476. + //Dbg("i%lu\n", inode->i_ino);
  12477. + atomic_dec(&itoii(inode)->ii_generation);
  12478. +}
  12479. +
  12480. +/* hinotify.c */
  12481. +int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
  12482. + struct inode *h_inode);
  12483. +void do_free_hinotify(struct aufs_hinode *hinode);
  12484. +void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
  12485. + unsigned int lsc);
  12486. +void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex);
  12487. +void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
  12488. + aufs_bindex_t bindex, int issamedir);
  12489. +void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
  12490. + aufs_bindex_t bindex, int issamedir);
  12491. +void au_reset_hinotify(struct inode *inode, unsigned int flags);
  12492. +int __init au_inotify_init(void);
  12493. +void au_inotify_fin(void);
  12494. +#else
  12495. +static inline
  12496. +int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
  12497. + struct inode *h_inode)
  12498. +{
  12499. + return -EOPNOTSUPP;
  12500. +}
  12501. +
  12502. +static inline void do_free_hinotify(struct aufs_hinode *hinode)
  12503. +{
  12504. + /* nothing */
  12505. +}
  12506. +
  12507. +static inline
  12508. +void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
  12509. + unsigned int lsc)
  12510. +{
  12511. + hi_lock(h_dir, lsc);
  12512. +}
  12513. +
  12514. +static inline
  12515. +void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
  12516. +{
  12517. + i_unlock(h_dir);
  12518. +}
  12519. +
  12520. +static inline
  12521. +void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
  12522. + aufs_bindex_t bindex, int issamedir)
  12523. +{
  12524. + vfsub_lock_rename(h_parents[0], h_parents[1]);
  12525. +}
  12526. +
  12527. +static inline
  12528. +void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
  12529. + aufs_bindex_t bindex, int issamedir)
  12530. +{
  12531. + vfsub_unlock_rename(h_parents[0], h_parents[1]);
  12532. +}
  12533. +
  12534. +static inline void au_reset_hinotify(struct inode *inode, unsigned int flags)
  12535. +{
  12536. + /* nothing */
  12537. +}
  12538. +
  12539. +#define au_inotify_init() 0
  12540. +#define au_inotify_fin() /* */
  12541. +#endif /* CONFIG_AUFS_HINOTIFY */
  12542. +
  12543. +static inline void free_hinotify(struct inode *inode, aufs_bindex_t bindex)
  12544. +{
  12545. + do_free_hinotify(itoii(inode)->ii_hinode + bindex);
  12546. +}
  12547. +
  12548. +/*
  12549. + * hgdir_lock, hdir_lock, hdir2_lock
  12550. + */
  12551. +#define LockFunc(name, lsc) \
  12552. +static inline \
  12553. +void name##_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex) \
  12554. +{do_hdir_lock(h_dir, dir, bindex, AuLsc_HI_##lsc);}
  12555. +
  12556. +LockFunc(hgdir, GPARENT);
  12557. +LockFunc(hdir, PARENT);
  12558. +LockFunc(hdir2, PARENT2);
  12559. +
  12560. +#undef LockFunc
  12561. +
  12562. +/* ---------------------------------------------------------------------- */
  12563. +
  12564. +/* lock subclass for iinfo */
  12565. +enum {
  12566. + AuLsc_II_CHILD, /* child first */
  12567. + AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
  12568. + AuLsc_II_CHILD3, /* copyup dirs */
  12569. + AuLsc_II_PARENT,
  12570. + AuLsc_II_PARENT2,
  12571. + AuLsc_II_PARENT3,
  12572. + AuLsc_II_NEW /* new inode */
  12573. +};
  12574. +
  12575. +/*
  12576. + * ii_read_lock_child, ii_write_lock_child,
  12577. + * ii_read_lock_child2, ii_write_lock_child2,
  12578. + * ii_read_lock_child3, ii_write_lock_child3,
  12579. + * ii_read_lock_parent, ii_write_lock_parent,
  12580. + * ii_read_lock_parent2, ii_write_lock_parent2,
  12581. + * ii_read_lock_parent3, ii_write_lock_parent3,
  12582. + * ii_read_lock_new, ii_write_lock_new
  12583. + */
  12584. +#define ReadLockFunc(name, lsc) \
  12585. +static inline void ii_read_lock_##name(struct inode *i) \
  12586. +{rw_read_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
  12587. +
  12588. +#define WriteLockFunc(name, lsc) \
  12589. +static inline void ii_write_lock_##name(struct inode *i) \
  12590. +{rw_write_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
  12591. +
  12592. +#define RWLockFuncs(name, lsc) \
  12593. + ReadLockFunc(name, lsc); \
  12594. + WriteLockFunc(name, lsc)
  12595. +
  12596. +RWLockFuncs(child, CHILD);
  12597. +RWLockFuncs(child2, CHILD2);
  12598. +RWLockFuncs(child3, CHILD3);
  12599. +RWLockFuncs(parent, PARENT);
  12600. +RWLockFuncs(parent2, PARENT2);
  12601. +RWLockFuncs(parent3, PARENT3);
  12602. +RWLockFuncs(new, NEW);
  12603. +
  12604. +#undef ReadLockFunc
  12605. +#undef WriteLockFunc
  12606. +#undef RWLockFunc
  12607. +
  12608. +/*
  12609. + * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
  12610. + */
  12611. +SimpleUnlockRwsemFuncs(ii, struct inode *i, itoii(i)->ii_rwsem);
  12612. +
  12613. +/* to debug easier, do not make them inlined functions */
  12614. +#define IiMustReadLock(i) do { \
  12615. + SiMustAnyLock((i)->i_sb); \
  12616. + RwMustReadLock(&itoii(i)->ii_rwsem); \
  12617. +} while (0)
  12618. +
  12619. +#define IiMustWriteLock(i) do { \
  12620. + SiMustAnyLock((i)->i_sb); \
  12621. + RwMustWriteLock(&itoii(i)->ii_rwsem); \
  12622. +} while (0)
  12623. +
  12624. +#define IiMustAnyLock(i) do { \
  12625. + SiMustAnyLock((i)->i_sb); \
  12626. + RwMustAnyLock(&itoii(i)->ii_rwsem); \
  12627. +} while (0)
  12628. +
  12629. +#define IiMustNoWaiters(i) RwMustNoWaiters(&itoii(i)->ii_rwsem)
  12630. +
  12631. +#endif /* __KERNEL__ */
  12632. +#endif /* __AUFS_INODE_H__ */
  12633. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/misc.c linux-2.6.22.1/fs/aufs/misc.c
  12634. --- linux-2.6.22.1.oorig/fs/aufs/misc.c 1970-01-01 01:00:00.000000000 +0100
  12635. +++ linux-2.6.22.1/fs/aufs/misc.c 2007-07-24 14:17:46.000000000 +0200
  12636. @@ -0,0 +1,228 @@
  12637. +/*
  12638. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  12639. + *
  12640. + * This program, aufs is free software; you can redistribute it and/or modify
  12641. + * it under the terms of the GNU General Public License as published by
  12642. + * the Free Software Foundation; either version 2 of the License, or
  12643. + * (at your option) any later version.
  12644. + *
  12645. + * This program is distributed in the hope that it will be useful,
  12646. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12647. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12648. + * GNU General Public License for more details.
  12649. + *
  12650. + * You should have received a copy of the GNU General Public License
  12651. + * along with this program; if not, write to the Free Software
  12652. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  12653. + */
  12654. +
  12655. +/* $Id: misc.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
  12656. +
  12657. +//#include <linux/fs.h>
  12658. +//#include <linux/namei.h>
  12659. +//#include <linux/mm.h>
  12660. +//#include <asm/uaccess.h>
  12661. +#include "aufs.h"
  12662. +
  12663. +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
  12664. +{
  12665. + void *q;
  12666. +
  12667. + LKTRTrace("p %p, nused %d, sz %d, ksize %d\n",
  12668. + p, nused, new_sz, ksize(p));
  12669. + DEBUG_ON(new_sz <= 0);
  12670. + if (new_sz <= nused)
  12671. + return p;
  12672. + if (new_sz <= ksize(p)) {
  12673. + memset(p + nused, 0, new_sz - nused);
  12674. + return p;
  12675. + }
  12676. +
  12677. + q = kmalloc(new_sz, gfp);
  12678. + //q = NULL;
  12679. + if (unlikely(!q))
  12680. + return NULL;
  12681. + memcpy(q, p, nused);
  12682. + memset(q + nused, 0, new_sz - nused);
  12683. + //smp_mb();
  12684. + kfree(p);
  12685. + return q;
  12686. +}
  12687. +
  12688. +/* ---------------------------------------------------------------------- */
  12689. +
  12690. +// todo: make it inline
  12691. +struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
  12692. + struct super_block *sb, aufs_bindex_t bindex)
  12693. +{
  12694. + LKTRTrace("nd %p, b%d\n", nd, bindex);
  12695. +
  12696. + if (!nd)
  12697. + return NULL;
  12698. +
  12699. + fake_nd->dentry = NULL;
  12700. + fake_nd->mnt = NULL;
  12701. +
  12702. +#ifndef CONFIG_AUFS_FAKE_DM
  12703. + DiMustAnyLock(nd->dentry);
  12704. +
  12705. + if (bindex <= dbend(nd->dentry))
  12706. + fake_nd->dentry = au_h_dptr_i(nd->dentry, bindex);
  12707. + if (fake_nd->dentry) {
  12708. + dget(fake_nd->dentry);
  12709. + fake_nd->mnt = sbr_mnt(sb, bindex);
  12710. + DEBUG_ON(!fake_nd->mnt);
  12711. + mntget(fake_nd->mnt);
  12712. + } else
  12713. + fake_nd = ERR_PTR(-ENOENT);
  12714. +#endif
  12715. +
  12716. + TraceErrPtr(fake_nd);
  12717. + return fake_nd;
  12718. +}
  12719. +
  12720. +void fake_dm_release(struct nameidata *fake_nd)
  12721. +{
  12722. +#ifndef CONFIG_AUFS_FAKE_DM
  12723. + if (fake_nd) {
  12724. + mntput(fake_nd->mnt);
  12725. + dput(fake_nd->dentry);
  12726. + }
  12727. +#endif
  12728. +}
  12729. +
  12730. +/* ---------------------------------------------------------------------- */
  12731. +
  12732. +int au_copy_file(struct file *dst, struct file *src, loff_t len,
  12733. + struct super_block *sb, int *sparse)
  12734. +{
  12735. + int err, all_zero, dlgt;
  12736. + unsigned long blksize;
  12737. + char *buf;
  12738. + /* reduce stack space */
  12739. + struct iattr *ia;
  12740. +
  12741. + LKTRTrace("%.*s, %.*s\n",
  12742. + DLNPair(dst->f_dentry), DLNPair(src->f_dentry));
  12743. + DEBUG_ON(!(dst->f_mode & FMODE_WRITE));
  12744. + IMustLock(dst->f_dentry->d_parent->d_inode);
  12745. +
  12746. + err = -ENOMEM;
  12747. + blksize = dst->f_dentry->d_sb->s_blocksize;
  12748. + if (!blksize || PAGE_SIZE < blksize)
  12749. + blksize = PAGE_SIZE;
  12750. + LKTRTrace("blksize %lu\n", blksize);
  12751. + buf = kmalloc(blksize, GFP_KERNEL);
  12752. + //buf = NULL;
  12753. + if (unlikely(!buf))
  12754. + goto out;
  12755. + ia = kmalloc(sizeof(*ia), GFP_KERNEL);
  12756. + if (unlikely(!ia))
  12757. + goto out_buf;
  12758. +
  12759. + dlgt = need_dlgt(sb);
  12760. + err = all_zero = 0;
  12761. + dst->f_pos = src->f_pos = 0;
  12762. + while (len) {
  12763. + size_t sz, rbytes, wbytes, i;
  12764. + char *p;
  12765. +
  12766. + LKTRTrace("len %lld\n", len);
  12767. + sz = blksize;
  12768. + if (len < blksize)
  12769. + sz = len;
  12770. +
  12771. + /* support LSM and notify */
  12772. + rbytes = 0;
  12773. + while (!rbytes || err == -EAGAIN || err == -EINTR)
  12774. + err = rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
  12775. + dlgt);
  12776. + if (unlikely(err < 0))
  12777. + break;
  12778. +
  12779. + all_zero = 0;
  12780. + if (len >= rbytes && rbytes == blksize) {
  12781. + all_zero = 1;
  12782. + p = buf;
  12783. + for (i = 0; all_zero && i < rbytes; i++)
  12784. + all_zero = !*p++;
  12785. + }
  12786. + if (!all_zero) {
  12787. + wbytes = rbytes;
  12788. + p = buf;
  12789. + while (wbytes) {
  12790. + size_t b;
  12791. + /* support LSM and notify */
  12792. + err = b = vfsub_write_k(dst, p, wbytes,
  12793. + &dst->f_pos, dlgt);
  12794. + if (unlikely(err == -EAGAIN || err == -EINTR))
  12795. + continue;
  12796. + if (unlikely(err < 0))
  12797. + break;
  12798. + wbytes -= b;
  12799. + p += b;
  12800. + }
  12801. + } else {
  12802. + loff_t res;
  12803. + LKTRLabel(hole);
  12804. + *sparse = 1;
  12805. + err = res = vfsub_llseek(dst, rbytes, SEEK_CUR);
  12806. + if (unlikely(res < 0))
  12807. + break;
  12808. + }
  12809. + len -= rbytes;
  12810. + err = 0;
  12811. + }
  12812. +
  12813. + /* the last block may be a hole */
  12814. + if (unlikely(!err && all_zero)) {
  12815. + struct dentry *h_d = dst->f_dentry;
  12816. + struct inode *h_i = h_d->d_inode;
  12817. +
  12818. + LKTRLabel(last hole);
  12819. + do {
  12820. + err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, dlgt);
  12821. + } while (err == -EAGAIN || err == -EINTR);
  12822. + if (err == 1) {
  12823. + ia->ia_size = dst->f_pos;
  12824. + ia->ia_valid = ATTR_SIZE | ATTR_FILE;
  12825. + ia->ia_file = dst;
  12826. + hi_lock_child2(h_i);
  12827. + err = vfsub_notify_change(h_d, ia, dlgt);
  12828. + i_unlock(h_i);
  12829. + }
  12830. + }
  12831. +
  12832. + kfree(ia);
  12833. + out_buf:
  12834. + kfree(buf);
  12835. + out:
  12836. + TraceErr(err);
  12837. + return err;
  12838. +}
  12839. +
  12840. +/* ---------------------------------------------------------------------- */
  12841. +
  12842. +int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode)
  12843. +{
  12844. + int err;
  12845. +
  12846. + err = br_rdonly(stobr(sb, bindex));
  12847. + if (!err && inode) {
  12848. + struct inode *hi = au_h_iptr_i(inode, bindex);
  12849. + if (hi)
  12850. + err = IS_IMMUTABLE(hi) ? -EROFS : 0;
  12851. + }
  12852. + return err;
  12853. +}
  12854. +
  12855. +int au_test_perm(struct inode *hidden_inode, int mask, int dlgt)
  12856. +{
  12857. + if (!current->fsuid)
  12858. + return 0;
  12859. + if (unlikely(au_is_nfs(hidden_inode->i_sb)
  12860. + && (mask & MAY_WRITE)
  12861. + && S_ISDIR(hidden_inode->i_mode)))
  12862. + mask |= MAY_READ; /* force permission check */
  12863. + return vfsub_permission(hidden_inode, mask, NULL, dlgt);
  12864. +}
  12865. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/misc.h linux-2.6.22.1/fs/aufs/misc.h
  12866. --- linux-2.6.22.1.oorig/fs/aufs/misc.h 1970-01-01 01:00:00.000000000 +0100
  12867. +++ linux-2.6.22.1/fs/aufs/misc.h 2007-07-24 14:17:46.000000000 +0200
  12868. @@ -0,0 +1,187 @@
  12869. +/*
  12870. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  12871. + *
  12872. + * This program, aufs is free software; you can redistribute it and/or modify
  12873. + * it under the terms of the GNU General Public License as published by
  12874. + * the Free Software Foundation; either version 2 of the License, or
  12875. + * (at your option) any later version.
  12876. + *
  12877. + * This program is distributed in the hope that it will be useful,
  12878. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12879. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12880. + * GNU General Public License for more details.
  12881. + *
  12882. + * You should have received a copy of the GNU General Public License
  12883. + * along with this program; if not, write to the Free Software
  12884. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  12885. + */
  12886. +
  12887. +/* $Id: misc.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
  12888. +
  12889. +#ifndef __AUFS_MISC_H__
  12890. +#define __AUFS_MISC_H__
  12891. +
  12892. +#ifdef __KERNEL__
  12893. +
  12894. +#include <linux/fs.h>
  12895. +#include <linux/namei.h>
  12896. +#include <linux/sched.h>
  12897. +#include <linux/version.h>
  12898. +#include <linux/aufs_type.h>
  12899. +
  12900. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  12901. +#define I_MUTEX_QUOTA 0
  12902. +#define lockdep_off() /* */
  12903. +#define lockdep_on() /* */
  12904. +#define mutex_lock_nested(mtx, lsc) mutex_lock(mtx)
  12905. +#define down_write_nested(rw, lsc) down_write(rw)
  12906. +#define down_read_nested(rw, lsc) down_read(rw)
  12907. +#endif
  12908. +
  12909. +/* ---------------------------------------------------------------------- */
  12910. +
  12911. +struct aufs_rwsem {
  12912. + struct rw_semaphore rwsem;
  12913. +#ifdef CONFIG_AUFS_DEBUG
  12914. + atomic_t rcnt;
  12915. +#endif
  12916. +};
  12917. +
  12918. +#ifdef CONFIG_AUFS_DEBUG
  12919. +#define DbgRcntInit(rw) atomic_set(&(rw)->rcnt, 0)
  12920. +#define DbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
  12921. +#define DbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
  12922. +#else
  12923. +#define DbgRcntInit(rw) /* */
  12924. +#define DbgRcntInc(rw) /* */
  12925. +#define DbgRcntDec(rw) /* */
  12926. +#endif
  12927. +
  12928. +static inline void rw_init_nolock(struct aufs_rwsem *rw)
  12929. +{
  12930. + DbgRcntInit(rw);
  12931. + init_rwsem(&rw->rwsem);
  12932. +}
  12933. +
  12934. +static inline void rw_init_wlock(struct aufs_rwsem *rw)
  12935. +{
  12936. + rw_init_nolock(rw);
  12937. + down_write(&rw->rwsem);
  12938. +}
  12939. +
  12940. +static inline void rw_init_wlock_nested(struct aufs_rwsem *rw, unsigned int lsc)
  12941. +{
  12942. + rw_init_nolock(rw);
  12943. + down_write_nested(&rw->rwsem, lsc);
  12944. +}
  12945. +
  12946. +static inline void rw_read_lock(struct aufs_rwsem *rw)
  12947. +{
  12948. + down_read(&rw->rwsem);
  12949. + DbgRcntInc(rw);
  12950. +}
  12951. +
  12952. +static inline void rw_read_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
  12953. +{
  12954. + down_read_nested(&rw->rwsem, lsc);
  12955. + DbgRcntInc(rw);
  12956. +}
  12957. +
  12958. +static inline void rw_read_unlock(struct aufs_rwsem *rw)
  12959. +{
  12960. + DbgRcntDec(rw);
  12961. + up_read(&rw->rwsem);
  12962. +}
  12963. +
  12964. +static inline void rw_dgrade_lock(struct aufs_rwsem *rw)
  12965. +{
  12966. + DbgRcntInc(rw);
  12967. + downgrade_write(&rw->rwsem);
  12968. +}
  12969. +
  12970. +static inline void rw_write_lock(struct aufs_rwsem *rw)
  12971. +{
  12972. + down_write(&rw->rwsem);
  12973. +}
  12974. +
  12975. +static inline void rw_write_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
  12976. +{
  12977. + down_write_nested(&rw->rwsem, lsc);
  12978. +}
  12979. +
  12980. +static inline void rw_write_unlock(struct aufs_rwsem *rw)
  12981. +{
  12982. + up_write(&rw->rwsem);
  12983. +}
  12984. +
  12985. +#if 0 // why is not _nested version defined
  12986. +static inline int rw_read_trylock(struct aufs_rwsem *rw)
  12987. +{
  12988. + int ret = down_read_trylock(&rw->rwsem);
  12989. + if (ret)
  12990. + DbgRcntInc(rw);
  12991. + return ret;
  12992. +}
  12993. +
  12994. +static inline int rw_write_trylock(struct aufs_rwsem *rw)
  12995. +{
  12996. + return down_write_trylock(&rw->rwsem);
  12997. +}
  12998. +#endif
  12999. +
  13000. +#undef DbgRcntInit
  13001. +#undef DbgRcntInc
  13002. +#undef DbgRcntDec
  13003. +
  13004. +/* to debug easier, do not make them inlined functions */
  13005. +#define RwMustNoWaiters(rw) DEBUG_ON(!list_empty(&(rw)->rwsem.wait_list))
  13006. +#define RwMustAnyLock(rw) DEBUG_ON(down_write_trylock(&(rw)->rwsem))
  13007. +#ifdef CONFIG_AUFS_DEBUG
  13008. +#define RwMustReadLock(rw) do { \
  13009. + RwMustAnyLock(rw); \
  13010. + DEBUG_ON(!atomic_read(&(rw)->rcnt)); \
  13011. +} while (0)
  13012. +#define RwMustWriteLock(rw) do { \
  13013. + RwMustAnyLock(rw); \
  13014. + DEBUG_ON(atomic_read(&(rw)->rcnt)); \
  13015. +} while (0)
  13016. +#else
  13017. +#define RwMustReadLock(rw) RwMustAnyLock(rw)
  13018. +#define RwMustWriteLock(rw) RwMustAnyLock(rw)
  13019. +#endif
  13020. +
  13021. +#define SimpleLockRwsemFuncs(prefix, param, rwsem) \
  13022. +static inline void prefix##_read_lock(param) {rw_read_lock(&(rwsem));} \
  13023. +static inline void prefix##_write_lock(param) {rw_write_lock(&(rwsem));}
  13024. +//static inline void prefix##_read_trylock(param) {rw_read_trylock(&(rwsem));}
  13025. +//static inline void prefix##_write_trylock(param) {rw_write_trylock(&(rwsem));}
  13026. +//static inline void prefix##_read_trylock_nested(param, lsc)
  13027. +//{rw_read_trylock_nested(&(rwsem, lsc));}
  13028. +//static inline void prefix##_write_trylock_nestd(param, lsc)
  13029. +//{rw_write_trylock_nested(&(rwsem), nested);}
  13030. +
  13031. +#define SimpleUnlockRwsemFuncs(prefix, param, rwsem) \
  13032. +static inline void prefix##_read_unlock(param) {rw_read_unlock(&(rwsem));} \
  13033. +static inline void prefix##_write_unlock(param) {rw_write_unlock(&(rwsem));} \
  13034. +static inline void prefix##_downgrade_lock(param) {rw_dgrade_lock(&(rwsem));}
  13035. +
  13036. +#define SimpleRwsemFuncs(prefix, param, rwsem) \
  13037. + SimpleLockRwsemFuncs(prefix, param, rwsem); \
  13038. + SimpleUnlockRwsemFuncs(prefix, param, rwsem)
  13039. +
  13040. +/* ---------------------------------------------------------------------- */
  13041. +
  13042. +typedef ssize_t (*readf_t)(struct file*, char __user*, size_t, loff_t*);
  13043. +typedef ssize_t (*writef_t)(struct file*, const char __user*, size_t, loff_t*);
  13044. +
  13045. +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
  13046. +struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
  13047. + struct super_block *sb, aufs_bindex_t bindex);
  13048. +void fake_dm_release(struct nameidata *fake_nd);
  13049. +int au_copy_file(struct file *dst, struct file *src, loff_t len,
  13050. + struct super_block *sb, int *sparse);
  13051. +int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode);
  13052. +int au_test_perm(struct inode *h_inode, int mask, int dlgt);
  13053. +
  13054. +#endif /* __KERNEL__ */
  13055. +#endif /* __AUFS_MISC_H__ */
  13056. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/module.c linux-2.6.22.1/fs/aufs/module.c
  13057. --- linux-2.6.22.1.oorig/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
  13058. +++ linux-2.6.22.1/fs/aufs/module.c 2007-07-24 14:17:46.000000000 +0200
  13059. @@ -0,0 +1,334 @@
  13060. +/*
  13061. + * Copyright (C) 2007 Junjiro Okajima
  13062. + *
  13063. + * This program, aufs is free software; you can redistribute it and/or modify
  13064. + * it under the terms of the GNU General Public License as published by
  13065. + * the Free Software Foundation; either version 2 of the License, or
  13066. + * (at your option) any later version.
  13067. + *
  13068. + * This program is distributed in the hope that it will be useful,
  13069. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13070. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13071. + * GNU General Public License for more details.
  13072. + *
  13073. + * You should have received a copy of the GNU General Public License
  13074. + * along with this program; if not, write to the Free Software
  13075. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  13076. + */
  13077. +
  13078. +/* $Id: module.c,v 1.9 2007/04/30 05:46:32 sfjro Exp $ */
  13079. +
  13080. +//#include <linux/init.h>
  13081. +//#include <linux/kobject.h>
  13082. +#include <linux/module.h>
  13083. +//#include <linux/seq_file.h>
  13084. +//#include <linux/sysfs.h>
  13085. +#include "aufs.h"
  13086. +
  13087. +/* ---------------------------------------------------------------------- */
  13088. +
  13089. +/*
  13090. + * aufs caches
  13091. + */
  13092. +struct kmem_cache *aufs_cachep[AuCache_Last];
  13093. +static int __init create_cache(void)
  13094. +{
  13095. +#define Cache(type) kmem_cache_create(#type, sizeof(struct type), 0, \
  13096. + SLAB_RECLAIM_ACCOUNT, NULL, NULL)
  13097. +
  13098. + if ((aufs_cachep[AuCache_DINFO] = Cache(aufs_dinfo))
  13099. + && (aufs_cachep[AuCache_ICNTNR] = Cache(aufs_icntnr))
  13100. + && (aufs_cachep[AuCache_FINFO] = Cache(aufs_finfo))
  13101. + //&& (aufs_cachep[AuCache_FINFO] = NULL)
  13102. + && (aufs_cachep[AuCache_VDIR] = Cache(aufs_vdir))
  13103. + && (aufs_cachep[AuCache_DEHSTR] = Cache(aufs_dehstr))
  13104. + && (aufs_cachep[AuCache_HINOTIFY] = Cache(aufs_hinotify)))
  13105. + return 0;
  13106. + return -ENOMEM;
  13107. +
  13108. +#undef Cache
  13109. +}
  13110. +
  13111. +static void destroy_cache(void)
  13112. +{
  13113. + int i;
  13114. + for (i = 0; i < AuCache_Last; i++)
  13115. + if (aufs_cachep[i])
  13116. + kmem_cache_destroy(aufs_cachep[i]);
  13117. +}
  13118. +
  13119. +/* ---------------------------------------------------------------------- */
  13120. +
  13121. +char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
  13122. +int au_dir_roflags;
  13123. +extern struct file_system_type aufs_fs_type;
  13124. +
  13125. +#ifdef DbgDlgt
  13126. +#include <linux/security.h>
  13127. +#include "dbg_dlgt.c"
  13128. +#else
  13129. +#define dbg_dlgt_init() 0
  13130. +#define dbg_dlgt_fin() /* */
  13131. +#endif
  13132. +
  13133. +/*
  13134. + * functions for module interface.
  13135. + */
  13136. +MODULE_LICENSE("GPL");
  13137. +MODULE_AUTHOR("Junjiro Okajima");
  13138. +MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs");
  13139. +MODULE_VERSION(AUFS_VERSION);
  13140. +
  13141. +/* it should be 'byte', but param_set_byte() prints by "%c" */
  13142. +short aufs_nwkq = AUFS_NWKQ_DEF;
  13143. +MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
  13144. +module_param_named(nwkq, aufs_nwkq, short, 0444);
  13145. +
  13146. +int sysaufs_brs = 0;
  13147. +MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/brs");
  13148. +module_param_named(brs, sysaufs_brs, int, 0444);
  13149. +
  13150. +static int __init aufs_init(void)
  13151. +{
  13152. + int err, i;
  13153. + char *p;
  13154. +
  13155. + //sbinfo->si_xino is atomic_long_t
  13156. + BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
  13157. +
  13158. +#ifdef CONFIG_AUFS_DEBUG
  13159. + {
  13160. + struct aufs_destr destr;
  13161. + destr.len = -1;
  13162. + DEBUG_ON(destr.len < NAME_MAX);
  13163. + }
  13164. +
  13165. +#ifdef CONFIG_4KSTACKS
  13166. + printk("CONFIG_4KSTACKS is defined.\n");
  13167. +#endif
  13168. +#if 0 // verbose debug
  13169. + {
  13170. + union {
  13171. + struct aufs_branch *br;
  13172. + struct aufs_dinfo *di;
  13173. + struct aufs_finfo *fi;
  13174. + struct aufs_iinfo *ii;
  13175. + struct aufs_hinode *hi;
  13176. + struct aufs_sbinfo *si;
  13177. + struct aufs_destr *destr;
  13178. + struct aufs_de *de;
  13179. + struct aufs_wh *wh;
  13180. + struct aufs_vdir *vd;
  13181. + } u;
  13182. +
  13183. + printk("br{"
  13184. + "xino %d, readf %d, writef %d, "
  13185. + "id %d, perm %d, mnt %d, count %d, "
  13186. + "wh_sem %d, wh %d, run %d} %d\n",
  13187. + offsetof(typeof(*u.br), br_xino),
  13188. + offsetof(typeof(*u.br), br_xino_read),
  13189. + offsetof(typeof(*u.br), br_xino_write),
  13190. + offsetof(typeof(*u.br), br_id),
  13191. + offsetof(typeof(*u.br), br_perm),
  13192. + offsetof(typeof(*u.br), br_mnt),
  13193. + offsetof(typeof(*u.br), br_count),
  13194. + offsetof(typeof(*u.br), br_wh_rwsem),
  13195. + offsetof(typeof(*u.br), br_wh),
  13196. + offsetof(typeof(*u.br), br_wh_running),
  13197. + sizeof(*u.br));
  13198. + printk("di{gen %d, rwsem %d, bstart %d, bend %d, bwh %d, "
  13199. + "bdiropq %d, hdentry %d, reval %d} %d\n",
  13200. + offsetof(typeof(*u.di), di_generation),
  13201. + offsetof(typeof(*u.di), di_rwsem),
  13202. + offsetof(typeof(*u.di), di_bstart),
  13203. + offsetof(typeof(*u.di), di_bend),
  13204. + offsetof(typeof(*u.di), di_bwh),
  13205. + offsetof(typeof(*u.di), di_bdiropq),
  13206. + offsetof(typeof(*u.di), di_hdentry),
  13207. + offsetof(typeof(*u.di), di_reval),
  13208. + sizeof(*u.di));
  13209. + printk("fi{gen %d, rwsem %d, hfile %d, bstart %d, bend %d, "
  13210. + "h_vm_ops %d, vdir_cach %d} %d\n",
  13211. + offsetof(typeof(*u.fi), fi_generation),
  13212. + offsetof(typeof(*u.fi), fi_rwsem),
  13213. + offsetof(typeof(*u.fi), fi_hfile),
  13214. + offsetof(typeof(*u.fi), fi_bstart),
  13215. + offsetof(typeof(*u.fi), fi_bend),
  13216. + offsetof(typeof(*u.fi), fi_h_vm_ops),
  13217. + offsetof(typeof(*u.fi), fi_vdir_cache),
  13218. + sizeof(*u.fi));
  13219. + printk("ii{rwsem %d, bstart %d, bend %d, hinode %d, vdir %d} "
  13220. + "%d\n",
  13221. + offsetof(typeof(*u.ii), ii_rwsem),
  13222. + offsetof(typeof(*u.ii), ii_bstart),
  13223. + offsetof(typeof(*u.ii), ii_bend),
  13224. + offsetof(typeof(*u.ii), ii_hinode),
  13225. + offsetof(typeof(*u.ii), ii_vdir),
  13226. + sizeof(*u.ii));
  13227. + printk("hi{inode %d, id %d, notify %d} %d\n",
  13228. + offsetof(typeof(*u.hi), hi_inode),
  13229. + offsetof(typeof(*u.hi), hi_id),
  13230. + offsetof(typeof(*u.hi), hi_notify),
  13231. + sizeof(*u.hi));
  13232. + printk("si{rwsem %d, gen %d, "
  13233. + "failed_refresh %d, "
  13234. + "bend %d, last id %d, br %d, "
  13235. + "flags %d, "
  13236. + "xino %d, "
  13237. + "rdcache %d, "
  13238. + "dirwh %d, "
  13239. + "pl_lock %d, pl %d, "
  13240. + "kobj %d} %d\n",
  13241. + offsetof(typeof(*u.si), si_rwsem),
  13242. + offsetof(typeof(*u.si), si_generation),
  13243. + -1,//offsetof(typeof(*u.si), si_failed_refresh_dirs),
  13244. + offsetof(typeof(*u.si), si_bend),
  13245. + offsetof(typeof(*u.si), si_last_br_id),
  13246. + offsetof(typeof(*u.si), si_branch),
  13247. + offsetof(typeof(*u.si), si_flags),
  13248. + offsetof(typeof(*u.si), si_xino),
  13249. + offsetof(typeof(*u.si), si_rdcache),
  13250. + offsetof(typeof(*u.si), si_dirwh),
  13251. + offsetof(typeof(*u.si), si_plink_lock),
  13252. + offsetof(typeof(*u.si), si_plink),
  13253. + offsetof(typeof(*u.si), si_kobj),
  13254. + sizeof(*u.si));
  13255. + printk("destr{len %d, name %d} %d\n",
  13256. + offsetof(typeof(*u.destr), len),
  13257. + offsetof(typeof(*u.destr), name),
  13258. + sizeof(*u.destr));
  13259. + printk("de{ino %d, type %d, str %d} %d\n",
  13260. + offsetof(typeof(*u.de), de_ino),
  13261. + offsetof(typeof(*u.de), de_type),
  13262. + offsetof(typeof(*u.de), de_str),
  13263. + sizeof(*u.de));
  13264. + printk("wh{hash %d, bindex %d, str %d} %d\n",
  13265. + offsetof(typeof(*u.wh), wh_hash),
  13266. + offsetof(typeof(*u.wh), wh_bindex),
  13267. + offsetof(typeof(*u.wh), wh_str),
  13268. + sizeof(*u.wh));
  13269. + printk("vd{deblk %d, nblk %d, last %d, ver %d, jiffy %d} %d\n",
  13270. + offsetof(typeof(*u.vd), vd_deblk),
  13271. + offsetof(typeof(*u.vd), vd_nblk),
  13272. + offsetof(typeof(*u.vd), vd_last),
  13273. + offsetof(typeof(*u.vd), vd_version),
  13274. + offsetof(typeof(*u.vd), vd_jiffy),
  13275. + sizeof(*u.vd));
  13276. + }
  13277. +#endif
  13278. +#endif
  13279. +
  13280. + p = au_esc_chars;
  13281. + for (i = 1; i <= ' '; i++)
  13282. + *p++ = i;
  13283. + *p++ = '\\';
  13284. + *p++ = '\x7f';
  13285. + *p = 0;
  13286. +
  13287. + au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
  13288. +#ifndef CONFIG_AUFS_SYSAUFS
  13289. + sysaufs_brs = 0;
  13290. +#endif
  13291. +
  13292. + err = -EINVAL;
  13293. + if (unlikely(aufs_nwkq <= 0))
  13294. + goto out;
  13295. + err = create_cache();
  13296. + if (unlikely(err))
  13297. + goto out;
  13298. + err = sysaufs_init();
  13299. + if (unlikely(err))
  13300. + goto out_cache;
  13301. + err = au_wkq_init();
  13302. + if (unlikely(err))
  13303. + goto out_kobj;
  13304. + err = au_inotify_init();
  13305. + if (unlikely(err))
  13306. + goto out_wkq;
  13307. + err = dbg_dlgt_init();
  13308. + if (unlikely(err))
  13309. + goto out_inotify;
  13310. + err = register_filesystem(&aufs_fs_type);
  13311. + if (unlikely(err))
  13312. + goto out_dlgt;
  13313. + printk(AUFS_NAME " " AUFS_VERSION "\n");
  13314. + return 0; /* success */
  13315. +
  13316. + out_dlgt:
  13317. + dbg_dlgt_fin();
  13318. + out_inotify:
  13319. + au_inotify_fin();
  13320. + out_wkq:
  13321. + au_wkq_fin();
  13322. + out_kobj:
  13323. + sysaufs_fin();
  13324. + out_cache:
  13325. + destroy_cache();
  13326. + out:
  13327. + TraceErr(err);
  13328. + return err;
  13329. +}
  13330. +
  13331. +static void __exit aufs_exit(void)
  13332. +{
  13333. + unregister_filesystem(&aufs_fs_type);
  13334. + dbg_dlgt_fin();
  13335. + au_inotify_fin();
  13336. + au_wkq_fin();
  13337. + sysaufs_fin();
  13338. + destroy_cache();
  13339. +}
  13340. +
  13341. +module_init(aufs_init);
  13342. +module_exit(aufs_exit);
  13343. +
  13344. +/* ---------------------------------------------------------------------- */
  13345. +
  13346. +// fake Kconfig
  13347. +#if 1
  13348. +#ifdef CONFIG_AUFS_HINOTIFY
  13349. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  13350. +#error CONFIG_AUFS_HINOTIFY is supported in linux-2.6.18 and later.
  13351. +#endif
  13352. +#ifndef CONFIG_INOTIFY
  13353. +#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY.
  13354. +#endif
  13355. +#endif
  13356. +
  13357. +#if AUFS_BRANCH_MAX > 511 && BITS_PER_LONG == 64 && PAGE_SIZE == 4096
  13358. +#warning For 4k pagesize and 64bit environment, \
  13359. + CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended.
  13360. +#endif
  13361. +
  13362. +#ifdef CONFIG_AUFS_SYSAUFS
  13363. +#ifndef CONFIG_SYSFS
  13364. +#error CONFIG_AUFS_SYSAUFS requires CONFIG_SYSFS.
  13365. +#endif
  13366. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  13367. +#error CONFIG_AUFS_SYSAUFS requires linux-2.6.18 and later.
  13368. +#endif
  13369. +#endif
  13370. +
  13371. +#ifdef CONFIG_AUFS_EXPORT
  13372. +#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE)
  13373. +#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS
  13374. +#endif
  13375. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  13376. +#error CONFIG_AUFS_EXPORT requires linux-2.6.18 and later.
  13377. +#endif
  13378. +#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS)
  13379. +#error need CONFIG_EXPORTFS=y to link aufs statically with CONFIG_AUFS_EXPORT
  13380. +#endif
  13381. +#endif
  13382. +
  13383. +#ifdef CONFIG_DEBUG_PROVE_LOCKING
  13384. +#if MAX_LOCKDEP_SUBCLASSES < AuLsc_End
  13385. +#warning lockdep will not work since aufs uses deeper locks.
  13386. +#endif
  13387. +#endif
  13388. +
  13389. +#ifdef CONFIG_AUFS_COMPAT
  13390. +#warning CONFIG_AUFS_COMPAT will be removed in the near future.
  13391. +#endif
  13392. +
  13393. +#endif
  13394. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/module.h linux-2.6.22.1/fs/aufs/module.h
  13395. --- linux-2.6.22.1.oorig/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
  13396. +++ linux-2.6.22.1/fs/aufs/module.h 2007-07-24 14:17:46.000000000 +0200
  13397. @@ -0,0 +1,60 @@
  13398. +/*
  13399. + * Copyright (C) 2007 Junjiro Okajima
  13400. + *
  13401. + * This program, aufs is free software; you can redistribute it and/or modify
  13402. + * it under the terms of the GNU General Public License as published by
  13403. + * the Free Software Foundation; either version 2 of the License, or
  13404. + * (at your option) any later version.
  13405. + *
  13406. + * This program is distributed in the hope that it will be useful,
  13407. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13408. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13409. + * GNU General Public License for more details.
  13410. + *
  13411. + * You should have received a copy of the GNU General Public License
  13412. + * along with this program; if not, write to the Free Software
  13413. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  13414. + */
  13415. +
  13416. +/* $Id: module.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
  13417. +
  13418. +#ifndef __AUFS_MODULE_H__
  13419. +#define __AUFS_MODULE_H__
  13420. +
  13421. +#ifdef __KERNEL__
  13422. +
  13423. +#include <linux/slab.h>
  13424. +
  13425. +/* ---------------------------------------------------------------------- */
  13426. +
  13427. +/* module parameters */
  13428. +extern short aufs_nwkq;
  13429. +extern int sysaufs_brs;
  13430. +
  13431. +/* ---------------------------------------------------------------------- */
  13432. +
  13433. +extern char au_esc_chars[];
  13434. +extern int au_dir_roflags;
  13435. +
  13436. +/* kmem cache */
  13437. +enum {AuCache_DINFO, AuCache_ICNTNR, AuCache_FINFO, AuCache_VDIR,
  13438. + AuCache_DEHSTR, AuCache_HINOTIFY, AuCache_Last};
  13439. +extern struct kmem_cache *aufs_cachep[];
  13440. +
  13441. +#define CacheFuncs(name, index) \
  13442. +static inline void *cache_alloc_##name(void) \
  13443. +{return kmem_cache_alloc(aufs_cachep[index], GFP_KERNEL);} \
  13444. +static inline void cache_free_##name(void *p) \
  13445. +{kmem_cache_free(aufs_cachep[index], p);}
  13446. +
  13447. +CacheFuncs(dinfo, AuCache_DINFO);
  13448. +CacheFuncs(icntnr, AuCache_ICNTNR);
  13449. +CacheFuncs(finfo, AuCache_FINFO);
  13450. +CacheFuncs(vdir, AuCache_VDIR);
  13451. +CacheFuncs(dehstr, AuCache_DEHSTR);
  13452. +CacheFuncs(hinotify, AuCache_HINOTIFY);
  13453. +
  13454. +#undef CacheFuncs
  13455. +
  13456. +#endif /* __KERNEL__ */
  13457. +#endif /* __AUFS_MODULE_H__ */
  13458. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/opts.c linux-2.6.22.1/fs/aufs/opts.c
  13459. --- linux-2.6.22.1.oorig/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
  13460. +++ linux-2.6.22.1/fs/aufs/opts.c 2007-07-24 14:17:46.000000000 +0200
  13461. @@ -0,0 +1,1043 @@
  13462. +/*
  13463. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  13464. + *
  13465. + * This program, aufs is free software; you can redistribute it and/or modify
  13466. + * it under the terms of the GNU General Public License as published by
  13467. + * the Free Software Foundation; either version 2 of the License, or
  13468. + * (at your option) any later version.
  13469. + *
  13470. + * This program is distributed in the hope that it will be useful,
  13471. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13472. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13473. + * GNU General Public License for more details.
  13474. + *
  13475. + * You should have received a copy of the GNU General Public License
  13476. + * along with this program; if not, write to the Free Software
  13477. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  13478. + */
  13479. +
  13480. +/* $Id: opts.c,v 1.34 2007/05/14 03:40:27 sfjro Exp $ */
  13481. +
  13482. +#include <asm/types.h> // a distribution requires
  13483. +#include <linux/parser.h>
  13484. +#include "aufs.h"
  13485. +
  13486. +enum {
  13487. + Opt_br,
  13488. + Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
  13489. + Opt_idel, Opt_imod,
  13490. + Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash,
  13491. + Opt_xino, Opt_zxino, Opt_noxino,
  13492. + Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink,
  13493. + Opt_udba,
  13494. + Opt_diropq_a, Opt_diropq_w,
  13495. + Opt_warn_perm, Opt_nowarn_perm,
  13496. + Opt_findrw_dir, Opt_findrw_br,
  13497. + Opt_coo,
  13498. + Opt_dlgt, Opt_nodlgt,
  13499. + Opt_tail, Opt_ignore, Opt_err
  13500. +};
  13501. +
  13502. +static match_table_t options = {
  13503. + {Opt_br, "br=%s"},
  13504. + {Opt_br, "br:%s"},
  13505. +
  13506. + {Opt_add, "add=%d:%s"},
  13507. + {Opt_add, "add:%d:%s"},
  13508. + {Opt_add, "ins=%d:%s"},
  13509. + {Opt_add, "ins:%d:%s"},
  13510. + {Opt_append, "append=%s"},
  13511. + {Opt_append, "append:%s"},
  13512. + {Opt_prepend, "prepend=%s"},
  13513. + {Opt_prepend, "prepend:%s"},
  13514. +
  13515. + {Opt_del, "del=%s"},
  13516. + {Opt_del, "del:%s"},
  13517. + //{Opt_idel, "idel:%d"},
  13518. + {Opt_mod, "mod=%s"},
  13519. + {Opt_mod, "mod:%s"},
  13520. + //{Opt_imod, "imod:%d:%s"},
  13521. +
  13522. + {Opt_dirwh, "dirwh=%d"},
  13523. + {Opt_dirwh, "dirwh:%d"},
  13524. +
  13525. + {Opt_xino, "xino=%s"},
  13526. + {Opt_xino, "xino:%s"},
  13527. + {Opt_noxino, "noxino"},
  13528. + //{Opt_zxino, "zxino=%s"},
  13529. +
  13530. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
  13531. + {Opt_plink, "plink"},
  13532. + {Opt_noplink, "noplink"},
  13533. +#ifdef CONFIG_AUFS_DEBUG
  13534. + {Opt_list_plink, "list_plink"},
  13535. +#endif
  13536. + {Opt_clean_plink, "clean_plink"},
  13537. +#endif
  13538. +
  13539. + {Opt_udba, "udba=%s"},
  13540. +
  13541. + {Opt_diropq_a, "diropq=always"},
  13542. + {Opt_diropq_a, "diropq=a"},
  13543. + {Opt_diropq_w, "diropq=whiteouted"},
  13544. + {Opt_diropq_w, "diropq=w"},
  13545. +
  13546. + {Opt_warn_perm, "warn_perm"},
  13547. + {Opt_nowarn_perm, "nowarn_perm"},
  13548. +
  13549. +#ifdef CONFIG_AUFS_DLGT
  13550. + {Opt_dlgt, "dlgt"},
  13551. + {Opt_nodlgt, "nodlgt"},
  13552. +#endif
  13553. +
  13554. + {Opt_rdcache, "rdcache=%d"},
  13555. + {Opt_rdcache, "rdcache:%d"},
  13556. +#if 0
  13557. + {Opt_findrw_dir, "findrw=dir"},
  13558. + {Opt_findrw_br, "findrw=br"},
  13559. +
  13560. + {Opt_coo, "coo=%s"},
  13561. +
  13562. + {Opt_deblk, "deblk=%d"},
  13563. + {Opt_deblk, "deblk:%d"},
  13564. + {Opt_nhash, "nhash=%d"},
  13565. + {Opt_nhash, "nhash:%d"},
  13566. +#endif
  13567. +
  13568. + {Opt_br, "dirs=%s"},
  13569. + {Opt_ignore, "debug=%d"},
  13570. + {Opt_ignore, "delete=whiteout"},
  13571. + {Opt_ignore, "delete=all"},
  13572. + {Opt_ignore, "imap=%s"},
  13573. +
  13574. + {Opt_err, NULL}
  13575. +};
  13576. +
  13577. +/* ---------------------------------------------------------------------- */
  13578. +
  13579. +#define RW "rw"
  13580. +#define RO "ro"
  13581. +#define WH "wh"
  13582. +#define RR "rr"
  13583. +#define NoLinkWH "nolwh"
  13584. +
  13585. +static match_table_t brperms = {
  13586. + {AuBr_RR, RR},
  13587. + {AuBr_RO, RO},
  13588. + {AuBr_RW, RW},
  13589. +
  13590. + {AuBr_RRWH, RR "+" WH},
  13591. + {AuBr_ROWH, RO "+" WH},
  13592. + {AuBr_RWNoLinkWH, RW "+" NoLinkWH},
  13593. +
  13594. + {AuBr_ROWH, "nfsro"},
  13595. + {AuBr_RO, NULL}
  13596. +};
  13597. +
  13598. +static int br_perm_val(char *perm)
  13599. +{
  13600. + int val;
  13601. + substring_t args[MAX_OPT_ARGS];
  13602. +
  13603. + DEBUG_ON(!perm || !*perm);
  13604. + LKTRTrace("perm %s\n", perm);
  13605. + val = match_token(perm, brperms, args);
  13606. + TraceErr(val);
  13607. + return val;
  13608. +}
  13609. +
  13610. +int br_perm_str(char *p, unsigned int len, int brperm)
  13611. +{
  13612. + struct match_token *bp = brperms;
  13613. +
  13614. + LKTRTrace("len %d, 0x%x\n", len, brperm);
  13615. +
  13616. + while (bp->pattern) {
  13617. + if (bp->token == brperm) {
  13618. + if (strlen(bp->pattern) < len) {
  13619. + strcpy(p, bp->pattern);
  13620. + return 0;
  13621. + } else
  13622. + return -E2BIG;
  13623. + }
  13624. + bp++;
  13625. + }
  13626. +
  13627. + return -EIO;
  13628. +}
  13629. +
  13630. +/* ---------------------------------------------------------------------- */
  13631. +
  13632. +static match_table_t udbalevel = {
  13633. + {AuFlag_UDBA_REVAL, "reval"},
  13634. +#ifdef CONFIG_AUFS_HINOTIFY
  13635. + {AuFlag_UDBA_INOTIFY, "inotify"},
  13636. +#endif
  13637. + {AuFlag_UDBA_NONE, "none"},
  13638. + {-1, NULL}
  13639. +};
  13640. +
  13641. +static int udba_val(char *str)
  13642. +{
  13643. + substring_t args[MAX_OPT_ARGS];
  13644. + return match_token(str, udbalevel, args);
  13645. +}
  13646. +
  13647. +au_parser_pattern_t udba_str(int udba)
  13648. +{
  13649. + struct match_token *p = udbalevel;
  13650. + while (p->pattern) {
  13651. + if (p->token == udba)
  13652. + return p->pattern;
  13653. + p++;
  13654. + }
  13655. + BUG();
  13656. + return "??";
  13657. +}
  13658. +
  13659. +void udba_set(struct super_block *sb, unsigned int flg)
  13660. +{
  13661. + au_flag_clr(sb, AuMask_UDBA);
  13662. + au_flag_set(sb, flg);
  13663. +}
  13664. +
  13665. +/* ---------------------------------------------------------------------- */
  13666. +
  13667. +static match_table_t coolevel = {
  13668. + {AuFlag_COO_LEAF, "leaf"},
  13669. + {AuFlag_COO_ALL, "all"},
  13670. + {AuFlag_COO_NONE, "none"},
  13671. + {-1, NULL}
  13672. +};
  13673. +
  13674. +#if 0
  13675. +static int coo_val(char *str)
  13676. +{
  13677. + substring_t args[MAX_OPT_ARGS];
  13678. + return match_token(str, coolevel, args);
  13679. +}
  13680. +#endif
  13681. +
  13682. +au_parser_pattern_t coo_str(int coo)
  13683. +{
  13684. + struct match_token *p = coolevel;
  13685. + while (p->pattern) {
  13686. + if (p->token == coo)
  13687. + return p->pattern;
  13688. + p++;
  13689. + }
  13690. + BUG();
  13691. + return "??";
  13692. +}
  13693. +static void coo_set(struct super_block *sb, unsigned int flg)
  13694. +{
  13695. + au_flag_clr(sb, AuMask_COO);
  13696. + au_flag_set(sb, flg);
  13697. +}
  13698. +
  13699. +/* ---------------------------------------------------------------------- */
  13700. +
  13701. +static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
  13702. +
  13703. +#ifdef CONFIG_AUFS_DEBUG
  13704. +static void dump_opts(struct opts *opts)
  13705. +{
  13706. + /* reduce stack space */
  13707. + union {
  13708. + struct opt_add *add;
  13709. + struct opt_del *del;
  13710. + struct opt_mod *mod;
  13711. + struct opt_xino *xino;
  13712. + } u;
  13713. + struct opt *opt;
  13714. +
  13715. + TraceEnter();
  13716. +
  13717. + opt = opts->opt;
  13718. + while (/* opt < opts_tail && */ opt->type != Opt_tail) {
  13719. + switch (opt->type) {
  13720. + case Opt_add:
  13721. + u.add = &opt->add;
  13722. + LKTRTrace("add {b%d, %s, 0x%x, %p}\n",
  13723. + u.add->bindex, u.add->path, u.add->perm,
  13724. + u.add->nd.dentry);
  13725. + break;
  13726. + case Opt_del:
  13727. + case Opt_idel:
  13728. + u.del = &opt->del;
  13729. + LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root);
  13730. + break;
  13731. + case Opt_mod:
  13732. + case Opt_imod:
  13733. + u.mod = &opt->mod;
  13734. + LKTRTrace("mod {%s, 0x%x, %p}\n",
  13735. + u.mod->path, u.mod->perm, u.mod->h_root);
  13736. + break;
  13737. + case Opt_append:
  13738. + u.add = &opt->add;
  13739. + LKTRTrace("append {b%d, %s, 0x%x, %p}\n",
  13740. + u.add->bindex, u.add->path, u.add->perm,
  13741. + u.add->nd.dentry);
  13742. + break;
  13743. + case Opt_prepend:
  13744. + u.add = &opt->add;
  13745. + LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n",
  13746. + u.add->bindex, u.add->path, u.add->perm,
  13747. + u.add->nd.dentry);
  13748. + break;
  13749. + case Opt_dirwh:
  13750. + LKTRTrace("dirwh %d\n", opt->dirwh);
  13751. + break;
  13752. + case Opt_rdcache:
  13753. + LKTRTrace("rdcache %d\n", opt->rdcache);
  13754. + break;
  13755. + case Opt_xino:
  13756. + u.xino = &opt->xino;
  13757. + LKTRTrace("xino {%s %.*s}\n",
  13758. + u.xino->path, DLNPair(u.xino->file->f_dentry));
  13759. + break;
  13760. + case Opt_noxino:
  13761. + LKTRLabel(noxino);
  13762. + break;
  13763. + case Opt_plink:
  13764. + LKTRLabel(plink);
  13765. + break;
  13766. + case Opt_noplink:
  13767. + LKTRLabel(noplink);
  13768. + break;
  13769. + case Opt_list_plink:
  13770. + LKTRLabel(list_plink);
  13771. + break;
  13772. + case Opt_clean_plink:
  13773. + LKTRLabel(clean_plink);
  13774. + break;
  13775. + case Opt_udba:
  13776. + LKTRTrace("udba %d, %s\n",
  13777. + opt->udba, udba_str(opt->udba));
  13778. + break;
  13779. + case Opt_diropq_a:
  13780. + LKTRLabel(diropq_a);
  13781. + break;
  13782. + case Opt_diropq_w:
  13783. + LKTRLabel(diropq_w);
  13784. + break;
  13785. + case Opt_warn_perm:
  13786. + LKTRLabel(warn_perm);
  13787. + break;
  13788. + case Opt_nowarn_perm:
  13789. + LKTRLabel(nowarn_perm);
  13790. + break;
  13791. + case Opt_dlgt:
  13792. + LKTRLabel(dlgt);
  13793. + break;
  13794. + case Opt_nodlgt:
  13795. + LKTRLabel(nodlgt);
  13796. + break;
  13797. + case Opt_coo:
  13798. + LKTRTrace("coo %d, %s\n", opt->coo, coo_str(opt->coo));
  13799. + break;
  13800. + default:
  13801. + BUG();
  13802. + }
  13803. + opt++;
  13804. + }
  13805. +}
  13806. +#else
  13807. +#define dump_opts(opts) /* */
  13808. +#endif
  13809. +
  13810. +void au_free_opts(struct opts *opts)
  13811. +{
  13812. + struct opt *opt;
  13813. +
  13814. + TraceEnter();
  13815. +
  13816. + opt = opts->opt;
  13817. + while (opt->type != Opt_tail) {
  13818. + switch (opt->type) {
  13819. + case Opt_add:
  13820. + case Opt_append:
  13821. + case Opt_prepend:
  13822. + path_release(&opt->add.nd);
  13823. + break;
  13824. + case Opt_del:
  13825. + case Opt_idel:
  13826. + dput(opt->del.h_root);
  13827. + break;
  13828. + case Opt_mod:
  13829. + case Opt_imod:
  13830. + dput(opt->mod.h_root);
  13831. + break;
  13832. + case Opt_xino:
  13833. + fput(opt->xino.file);
  13834. + break;
  13835. + }
  13836. + opt++;
  13837. + }
  13838. +}
  13839. +
  13840. +static int opt_add(struct opt *opt, char *opt_str, struct super_block *sb,
  13841. + aufs_bindex_t bindex)
  13842. +{
  13843. + int err;
  13844. + struct opt_add *add = &opt->add;
  13845. + char *p;
  13846. +
  13847. + LKTRTrace("%s, b%d\n", opt_str, bindex);
  13848. +
  13849. + add->bindex = bindex;
  13850. + add->perm = AuBr_RO;
  13851. + if (!bindex && !(sb->s_flags & MS_RDONLY))
  13852. + add->perm = AuBr_RW;
  13853. +#ifdef CONFIG_AUFS_COMPAT
  13854. + add->perm = AuBr_RW;
  13855. +#endif
  13856. + add->path = opt_str;
  13857. + p = strchr(opt_str, '=');
  13858. + if (unlikely(p)) {
  13859. + *p++ = 0;
  13860. + if (*p)
  13861. + add->perm = br_perm_val(p);
  13862. + }
  13863. +
  13864. + // LSM may detect it
  13865. + // do not superio.
  13866. + err = path_lookup(add->path, lkup_dirflags, &add->nd);
  13867. + //err = -1;
  13868. + if (!err) {
  13869. + opt->type = Opt_add;
  13870. + goto out;
  13871. + }
  13872. + Err("lookup failed %s (%d)\n", add->path, err);
  13873. + err = -EINVAL;
  13874. +
  13875. + out:
  13876. + TraceErr(err);
  13877. + return err;
  13878. +}
  13879. +
  13880. +/* called without aufs lock */
  13881. +int au_parse_opts(struct super_block *sb, char *str, struct opts *opts)
  13882. +{
  13883. + int err, n;
  13884. + struct dentry *root;
  13885. + struct opt *opt, *opt_tail;
  13886. + char *opt_str;
  13887. + substring_t args[MAX_OPT_ARGS];
  13888. + aufs_bindex_t bindex;
  13889. + struct nameidata nd;
  13890. + /* reduce stack space */
  13891. + union {
  13892. + struct opt_del *del;
  13893. + struct opt_mod *mod;
  13894. + struct opt_xino *xino;
  13895. + } u;
  13896. + struct file *file;
  13897. +
  13898. + LKTRTrace("%s, nopts %d\n", str, opts->max_opt);
  13899. +
  13900. + root = sb->s_root;
  13901. + err = 0;
  13902. + bindex = 0;
  13903. + opt = opts->opt;
  13904. + opt_tail = opt + opts->max_opt - 1;
  13905. + opt->type = Opt_tail;
  13906. + while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
  13907. + int token, skipped;
  13908. + char *p;
  13909. + err = -EINVAL;
  13910. + token = match_token(opt_str, options, args);
  13911. + LKTRTrace("%s, token %d, args[0]{%p, %p}\n",
  13912. + opt_str, token, args[0].from, args[0].to);
  13913. +
  13914. + skipped = 0;
  13915. + switch (token) {
  13916. + case Opt_br:
  13917. + err = 0;
  13918. + while (!err && (opt_str = strsep(&args[0].from, ":"))
  13919. + && *opt_str) {
  13920. + err = opt_add(opt, opt_str, sb, bindex++);
  13921. + //if (LktrCond) err = -1;
  13922. + if (unlikely(!err && ++opt > opt_tail)) {
  13923. + err = -E2BIG;
  13924. + break;
  13925. + }
  13926. + opt->type = Opt_tail;
  13927. + skipped = 1;
  13928. + }
  13929. + break;
  13930. + case Opt_add:
  13931. + if (unlikely(match_int(&args[0], &n))) {
  13932. + Err("bad integer in %s\n", opt_str);
  13933. + break;
  13934. + }
  13935. + bindex = n;
  13936. + err = opt_add(opt, args[1].from, sb, bindex);
  13937. + break;
  13938. + case Opt_append:
  13939. + case Opt_prepend:
  13940. + err = opt_add(opt, args[0].from, sb, /*dummy bindex*/1);
  13941. + if (!err)
  13942. + opt->type = token;
  13943. + break;
  13944. + case Opt_del:
  13945. + u.del = &opt->del;
  13946. + u.del->path = args[0].from;
  13947. + LKTRTrace("del path %s\n", u.del->path);
  13948. + // LSM may detect it
  13949. + // do not superio.
  13950. + err = path_lookup(u.del->path, lkup_dirflags, &nd);
  13951. + if (unlikely(err)) {
  13952. + Err("lookup failed %s (%d)\n", u.del->path, err);
  13953. + break;
  13954. + }
  13955. + u.del->h_root = dget(nd.dentry);
  13956. + path_release(&nd);
  13957. + opt->type = token;
  13958. + break;
  13959. +#if 0
  13960. + case Opt_idel:
  13961. + u.del = &opt->del;
  13962. + u.del->path = "(indexed)";
  13963. + if (unlikely(match_int(&args[0], &n))) {
  13964. + Err("bad integer in %s\n", opt_str);
  13965. + break;
  13966. + }
  13967. + bindex = n;
  13968. + aufs_read_lock(root, !AUFS_I_RLOCK);
  13969. + if (bindex < 0 || sbend(sb) < bindex) {
  13970. + Err("out of bounds, %d\n", bindex);
  13971. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  13972. + break;
  13973. + }
  13974. + err = 0;
  13975. + u.del->h_root = dget(au_h_dptr_i(root, bindex));
  13976. + opt->type = token;
  13977. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  13978. + break;
  13979. +#endif
  13980. +
  13981. + case Opt_mod:
  13982. + u.mod = &opt->mod;
  13983. + u.mod->path = args[0].from;
  13984. + p = strchr(u.mod->path, '=');
  13985. + if (unlikely(!p)) {
  13986. + Err("no permssion %s\n", opt_str);
  13987. + break;
  13988. + }
  13989. + *p++ = 0;
  13990. + u.mod->perm = br_perm_val(p);
  13991. + LKTRTrace("mod path %s, perm 0x%x, %s\n",
  13992. + u.mod->path, u.mod->perm, p);
  13993. + // LSM may detect it
  13994. + // do not superio.
  13995. + err = path_lookup(u.mod->path, lkup_dirflags, &nd);
  13996. + if (unlikely(err)) {
  13997. + Err("lookup failed %s (%d)\n", u.mod->path, err);
  13998. + break;
  13999. + }
  14000. + u.mod->h_root = dget(nd.dentry);
  14001. + path_release(&nd);
  14002. + opt->type = token;
  14003. + break;
  14004. +#if 0
  14005. + case Opt_imod:
  14006. + u.mod = &opt->mod;
  14007. + u.mod->path = "(indexed)";
  14008. + if (unlikely(match_int(&args[0], &n))) {
  14009. + Err("bad integer in %s\n", opt_str);
  14010. + break;
  14011. + }
  14012. + bindex = n;
  14013. + aufs_read_lock(root, !AUFS_I_RLOCK);
  14014. + if (bindex < 0 || sbend(sb) < bindex) {
  14015. + Err("out of bounds, %d\n", bindex);
  14016. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  14017. + break;
  14018. + }
  14019. + u.mod->perm = br_perm_val(args[1].from);
  14020. + LKTRTrace("mod path %s, perm 0x%x, %s\n",
  14021. + u.mod->path, u.mod->perm, args[1].from);
  14022. + err = 0;
  14023. + u.mod->h_root = dget(au_h_dptr_i(root, bindex));
  14024. + opt->type = token;
  14025. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  14026. + break;
  14027. +#endif
  14028. + case Opt_xino:
  14029. + u.xino = &opt->xino;
  14030. + file = xino_create(sb, args[0].from, /*silent*/0,
  14031. + /*parent*/NULL);
  14032. + err = PTR_ERR(file);
  14033. + if (IS_ERR(file))
  14034. + break;
  14035. + err = -EINVAL;
  14036. + if (unlikely(file->f_dentry->d_sb == sb)) {
  14037. + fput(file);
  14038. + Err("%s must be outside\n", args[0].from);
  14039. + break;
  14040. + }
  14041. + err = 0;
  14042. + u.xino->file = file;
  14043. + u.xino->path = args[0].from;
  14044. + opt->type = token;
  14045. + break;
  14046. +
  14047. + case Opt_dirwh:
  14048. + if (unlikely(match_int(&args[0], &opt->dirwh)))
  14049. + break;
  14050. + err = 0;
  14051. + opt->type = token;
  14052. + break;
  14053. +
  14054. + case Opt_rdcache:
  14055. + if (unlikely(match_int(&args[0], &opt->rdcache)))
  14056. + break;
  14057. + err = 0;
  14058. + opt->type = token;
  14059. + break;
  14060. +
  14061. + case Opt_noxino:
  14062. + case Opt_plink:
  14063. + case Opt_noplink:
  14064. + case Opt_list_plink:
  14065. + case Opt_clean_plink:
  14066. + case Opt_diropq_a:
  14067. + case Opt_diropq_w:
  14068. + case Opt_warn_perm:
  14069. + case Opt_nowarn_perm:
  14070. + case Opt_dlgt:
  14071. + case Opt_nodlgt:
  14072. + err = 0;
  14073. + opt->type = token;
  14074. + break;
  14075. +
  14076. + case Opt_udba:
  14077. + opt->udba = udba_val(args[0].from);
  14078. + if (opt->udba >= 0) {
  14079. + err = 0;
  14080. + opt->type = token;
  14081. + }
  14082. + break;
  14083. +
  14084. +#if 0
  14085. + case Opt_coo:
  14086. + opt->coo = coo_val(args[0].from);
  14087. + if (opt->coo >= 0) {
  14088. + err = 0;
  14089. + opt->type = token;
  14090. + }
  14091. + break;
  14092. +#endif
  14093. +
  14094. + case Opt_ignore:
  14095. +#ifndef CONFIG_AUFS_COMPAT
  14096. + Warn("ignored %s\n", opt_str);
  14097. +#endif
  14098. + skipped = 1;
  14099. + err = 0;
  14100. + break;
  14101. + case Opt_err:
  14102. + Err("unknown option %s\n", opt_str);
  14103. + break;
  14104. + }
  14105. +
  14106. + if (!err && !skipped) {
  14107. + if (unlikely(++opt > opt_tail)) {
  14108. + err = -E2BIG;
  14109. + opt--;
  14110. + opt->type = Opt_tail;
  14111. + break;
  14112. + }
  14113. + opt->type = Opt_tail;
  14114. + }
  14115. + }
  14116. +
  14117. + dump_opts(opts);
  14118. + if (unlikely(err))
  14119. + au_free_opts(opts);
  14120. + TraceErr(err);
  14121. + return err;
  14122. +}
  14123. +
  14124. +/*
  14125. + * returns,
  14126. + * plus: processed without an error
  14127. + * zero: unprocessed
  14128. + */
  14129. +static int au_do_opt_simple(struct super_block *sb, struct opt *opt,
  14130. + int remount, unsigned int *given)
  14131. +{
  14132. + int err;
  14133. + struct aufs_sbinfo *sbinfo = stosi(sb);
  14134. +
  14135. + TraceEnter();
  14136. +
  14137. + err = 1; /* handled */
  14138. + switch (opt->type) {
  14139. + case Opt_udba:
  14140. + udba_set(sb, opt->udba);
  14141. + *given |= opt->udba;
  14142. + break;
  14143. +
  14144. + case Opt_plink:
  14145. + au_flag_set(sb, AuFlag_PLINK);
  14146. + *given |= AuFlag_PLINK;
  14147. + break;
  14148. + case Opt_noplink:
  14149. + if (au_flag_test(sb, AuFlag_PLINK))
  14150. + au_put_plink(sb);
  14151. + au_flag_clr(sb, AuFlag_PLINK);
  14152. + *given |= AuFlag_PLINK;
  14153. + break;
  14154. + case Opt_list_plink:
  14155. + if (au_flag_test(sb, AuFlag_PLINK))
  14156. + au_list_plink(sb);
  14157. + break;
  14158. + case Opt_clean_plink:
  14159. + if (au_flag_test(sb, AuFlag_PLINK))
  14160. + au_put_plink(sb);
  14161. + break;
  14162. +
  14163. + case Opt_diropq_a:
  14164. + au_flag_set(sb, AuFlag_ALWAYS_DIROPQ);
  14165. + *given |= AuFlag_ALWAYS_DIROPQ;
  14166. + break;
  14167. + case Opt_diropq_w:
  14168. + au_flag_clr(sb, AuFlag_ALWAYS_DIROPQ);
  14169. + *given |= AuFlag_ALWAYS_DIROPQ;
  14170. + break;
  14171. +
  14172. + case Opt_dlgt:
  14173. + au_flag_set(sb, AuFlag_DLGT);
  14174. + *given |= AuFlag_DLGT;
  14175. + break;
  14176. + case Opt_nodlgt:
  14177. + au_flag_clr(sb, AuFlag_DLGT);
  14178. + *given |= AuFlag_DLGT;
  14179. + break;
  14180. +
  14181. + case Opt_warn_perm:
  14182. + au_flag_set(sb, AuFlag_WARN_PERM);
  14183. + *given |= AuFlag_WARN_PERM;
  14184. + break;
  14185. + case Opt_nowarn_perm:
  14186. + au_flag_clr(sb, AuFlag_WARN_PERM);
  14187. + *given |= AuFlag_WARN_PERM;
  14188. + break;
  14189. +
  14190. + case Opt_coo:
  14191. + coo_set(sb, opt->coo);
  14192. + *given |= opt->coo;
  14193. + break;
  14194. +
  14195. + case Opt_dirwh:
  14196. + sbinfo->si_dirwh = opt->dirwh;
  14197. + break;
  14198. +
  14199. + case Opt_rdcache:
  14200. + sbinfo->si_rdcache = opt->rdcache * HZ;
  14201. + break;
  14202. +
  14203. + default:
  14204. + err = 0;
  14205. + break;
  14206. + }
  14207. +
  14208. + TraceErr(err);
  14209. + return err;
  14210. +}
  14211. +
  14212. +/*
  14213. + * returns tri-state.
  14214. + * plus: processed without an error
  14215. + * zero: unprocessed
  14216. + * minus: error
  14217. + */
  14218. +static int au_do_opt_br(struct super_block *sb, struct opt *opt, int remount,
  14219. + int *do_refresh)
  14220. +{
  14221. + int err;
  14222. +
  14223. + TraceEnter();
  14224. +
  14225. + err = 0;
  14226. + switch (opt->type) {
  14227. + case Opt_append:
  14228. + opt->add.bindex = sbend(sb) + 1;
  14229. + goto add;
  14230. + case Opt_prepend:
  14231. + opt->add.bindex = 0;
  14232. + add:
  14233. + case Opt_add:
  14234. + err = br_add(sb, &opt->add, remount);
  14235. + if (!err)
  14236. + *do_refresh = err = 1;
  14237. + break;
  14238. +
  14239. + case Opt_del:
  14240. + case Opt_idel:
  14241. + err = br_del(sb, &opt->del, remount);
  14242. + if (!err)
  14243. + *do_refresh = err = 1;
  14244. + break;
  14245. +
  14246. + case Opt_mod:
  14247. + case Opt_imod:
  14248. + err = br_mod(sb, &opt->mod, remount, do_refresh);
  14249. + if (!err)
  14250. + err = 1;
  14251. + break;
  14252. + }
  14253. +
  14254. + TraceErr(err);
  14255. + return err;
  14256. +}
  14257. +
  14258. +static int au_do_opt_xino(struct super_block *sb, struct opt *opt, int remount,
  14259. + struct opt_xino **opt_xino)
  14260. +{
  14261. + int err;
  14262. +
  14263. + TraceEnter();
  14264. +
  14265. + err = 0;
  14266. + switch (opt->type) {
  14267. + case Opt_xino:
  14268. + err = xino_set(sb, &opt->xino, remount);
  14269. + if (!err)
  14270. + *opt_xino = &opt->xino;
  14271. + break;
  14272. + case Opt_noxino:
  14273. + err = xino_clr(sb);
  14274. + break;
  14275. + }
  14276. +
  14277. + TraceErr(err);
  14278. + return err;
  14279. +}
  14280. +
  14281. +static int verify_opts(struct super_block *sb, int remount)
  14282. +{
  14283. + int err;
  14284. + aufs_bindex_t bindex, bend;
  14285. + struct aufs_branch *br;
  14286. + struct dentry *root;
  14287. + struct inode *dir;
  14288. + unsigned int do_plink;
  14289. +
  14290. + TraceEnter();
  14291. +
  14292. + if (unlikely(!(sb->s_flags & MS_RDONLY)
  14293. + && !br_writable(sbr_perm(sb, 0))))
  14294. + Warn("first branch should be rw\n");
  14295. +
  14296. + err = 0;
  14297. + root = sb->s_root;
  14298. + dir = sb->s_root->d_inode;
  14299. + do_plink = au_flag_test(sb, AuFlag_PLINK);
  14300. + bend = sbend(sb);
  14301. + for (bindex = 0; !err && bindex <= bend; bindex++) {
  14302. + struct inode *h_dir;
  14303. + int skip;
  14304. +
  14305. + skip = 0;
  14306. + h_dir = au_h_iptr_i(dir, bindex);
  14307. + br = stobr(sb, bindex);
  14308. + br_wh_read_lock(br);
  14309. + switch (br->br_perm) {
  14310. + case AuBr_RR:
  14311. + case AuBr_RO:
  14312. + case AuBr_RRWH:
  14313. + case AuBr_ROWH:
  14314. + skip = (!br->br_wh && !br->br_plink);
  14315. + break;
  14316. +
  14317. + case AuBr_RWNoLinkWH:
  14318. + skip = !br->br_wh;
  14319. + if (skip) {
  14320. + if (do_plink)
  14321. + skip = !!br->br_plink;
  14322. + else
  14323. + skip = !br->br_plink;
  14324. + }
  14325. + break;
  14326. +
  14327. + case AuBr_RW:
  14328. + skip = !!br->br_wh;
  14329. + if (skip) {
  14330. + if (do_plink)
  14331. + skip = !!br->br_plink;
  14332. + else
  14333. + skip = !br->br_plink;
  14334. + }
  14335. + break;
  14336. +
  14337. + default:
  14338. + BUG();
  14339. + }
  14340. + br_wh_read_unlock(br);
  14341. +
  14342. + if (skip)
  14343. + continue;
  14344. +
  14345. + hdir_lock(h_dir, dir, bindex);
  14346. + br_wh_write_lock(br);
  14347. + err = init_wh(au_h_dptr_i(root, bindex), br,
  14348. + au_nfsmnt(sb, bindex), sb);
  14349. + br_wh_write_unlock(br);
  14350. + hdir_unlock(h_dir, dir, bindex);
  14351. + }
  14352. +
  14353. + TraceErr(err);
  14354. + return err;
  14355. +}
  14356. +
  14357. +int au_do_opts_mount(struct super_block *sb, struct opts *opts)
  14358. +{
  14359. + int err, do_refresh;
  14360. + struct inode *dir;
  14361. + struct opt *opt;
  14362. + unsigned int flags, given;
  14363. + struct opt_xino *opt_xino;
  14364. + aufs_bindex_t bend, bindex;
  14365. +
  14366. + TraceEnter();
  14367. + SiMustWriteLock(sb);
  14368. + DiMustWriteLock(sb->s_root);
  14369. + dir = sb->s_root->d_inode;
  14370. + IiMustWriteLock(dir);
  14371. +
  14372. + err = 0;
  14373. + given = 0;
  14374. + opt_xino = NULL;
  14375. + opt = opts->opt;
  14376. + while (err >= 0 && opt->type != Opt_tail)
  14377. + err = au_do_opt_simple(sb, opt++, /*remount*/0, &given);
  14378. + if (err > 0)
  14379. + err = 0;
  14380. + else if (unlikely(err < 0))
  14381. + goto out;
  14382. +
  14383. + /* disable them temporary */
  14384. + flags = au_flag_test(sb, AuFlag_XINO | AuMask_UDBA | AuFlag_DLGT);
  14385. + au_flag_clr(sb, AuFlag_XINO | AuFlag_DLGT);
  14386. + udba_set(sb, AuFlag_UDBA_REVAL);
  14387. +
  14388. + do_refresh = 0;
  14389. + opt = opts->opt;
  14390. + while (err >= 0 && opt->type != Opt_tail)
  14391. + err = au_do_opt_br(sb, opt++, /*remount*/0, &do_refresh);
  14392. + if (err > 0)
  14393. + err = 0;
  14394. + else if (unlikely(err < 0))
  14395. + goto out;
  14396. +
  14397. + bend = sbend(sb);
  14398. + if (unlikely(bend < 0)) {
  14399. + err = -EINVAL;
  14400. + Err("no branches\n");
  14401. + goto out;
  14402. + }
  14403. +
  14404. + if (flags & AuFlag_XINO)
  14405. + au_flag_set(sb, AuFlag_XINO);
  14406. + opt = opts->opt;
  14407. + while (!err && opt->type != Opt_tail)
  14408. + err = au_do_opt_xino(sb, opt++, /*remount*/0, &opt_xino);
  14409. + if (unlikely(err))
  14410. + goto out;
  14411. +
  14412. + //todo: test this error case.
  14413. + err = verify_opts(sb, /*remount*/0);
  14414. + DEBUG_ON(err);
  14415. + if (unlikely(err))
  14416. + goto out;
  14417. +
  14418. + /* enable xino */
  14419. + if (au_flag_test(sb, AuFlag_XINO) && !opt_xino) {
  14420. + struct file *xino_file = xino_def(sb);
  14421. + err = PTR_ERR(xino_file);
  14422. + if (IS_ERR(xino_file))
  14423. + goto out;
  14424. +
  14425. + err = 0;
  14426. + for (bindex = 0; !err && bindex <= bend; bindex++)
  14427. + err = xino_init(sb, bindex, xino_file,
  14428. + /*do_test*/bindex);
  14429. + fput(xino_file);
  14430. + if (unlikely(err))
  14431. + goto out;
  14432. + }
  14433. +
  14434. + /* restore hinotify */
  14435. + udba_set(sb, flags & AuMask_UDBA);
  14436. + if (flags & AuFlag_UDBA_INOTIFY)
  14437. + au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AUFS_HI_XINO);
  14438. +
  14439. + /* restore dlgt */
  14440. + if (flags & AuFlag_DLGT)
  14441. + au_flag_set(sb, AuFlag_DLGT);
  14442. +
  14443. + out:
  14444. + TraceErr(err);
  14445. + return err;
  14446. +}
  14447. +
  14448. +int au_do_opts_remount(struct super_block *sb, struct opts *opts,
  14449. + int *do_refresh, unsigned int *given)
  14450. +{
  14451. + int err, rerr;
  14452. + struct inode *dir;
  14453. + struct opt_xino *opt_xino;
  14454. + struct opt *opt;
  14455. + unsigned int dlgt;
  14456. +
  14457. + TraceEnter();
  14458. + SiMustWriteLock(sb);
  14459. + DiMustWriteLock(sb->s_root);
  14460. + dir = sb->s_root->d_inode;
  14461. + IiMustWriteLock(dir);
  14462. + //DEBUG_ON(au_flag_test(sb, AuFlag_UDBA_INOTIFY));
  14463. +
  14464. + err = 0;
  14465. + *do_refresh = 0;
  14466. + *given = 0;
  14467. + dlgt = au_flag_test(sb, AuFlag_DLGT);
  14468. + opt_xino = NULL;
  14469. + opt = opts->opt;
  14470. + while (err >= 0 && opt->type != Opt_tail) {
  14471. + err = au_do_opt_simple(sb, opt, /*remount*/1, given);
  14472. +
  14473. + /* disable it temporary */
  14474. + dlgt = au_flag_test(sb, AuFlag_DLGT);
  14475. + au_flag_clr(sb, AuFlag_DLGT);
  14476. +
  14477. + if (!err)
  14478. + err = au_do_opt_br(sb, opt, /*remount*/1, do_refresh);
  14479. + if (!err)
  14480. + err = au_do_opt_xino(sb, opt, /*remount*/1, &opt_xino);
  14481. +
  14482. + /* restore it */
  14483. + au_flag_set(sb, dlgt);
  14484. + opt++;
  14485. + }
  14486. + if (err > 0)
  14487. + err = 0;
  14488. + TraceErr(err);
  14489. +
  14490. + /* go on if err */
  14491. +
  14492. + //todo: test this error case.
  14493. + au_flag_clr(sb, AuFlag_DLGT);
  14494. + rerr = verify_opts(sb, /*remount*/1);
  14495. + au_flag_set(sb, dlgt);
  14496. +
  14497. + /* they are handled by the caller */
  14498. + if (!*do_refresh)
  14499. + *do_refresh = !!((*given & AuMask_UDBA)
  14500. + || au_flag_test(sb, AuFlag_XINO));
  14501. +
  14502. + TraceErr(err);
  14503. + return err;
  14504. +}
  14505. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/opts.h linux-2.6.22.1/fs/aufs/opts.h
  14506. --- linux-2.6.22.1.oorig/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
  14507. +++ linux-2.6.22.1/fs/aufs/opts.h 2007-07-24 14:17:46.000000000 +0200
  14508. @@ -0,0 +1,96 @@
  14509. +/*
  14510. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  14511. + *
  14512. + * This program, aufs is free software; you can redistribute it and/or modify
  14513. + * it under the terms of the GNU General Public License as published by
  14514. + * the Free Software Foundation; either version 2 of the License, or
  14515. + * (at your option) any later version.
  14516. + *
  14517. + * This program is distributed in the hope that it will be useful,
  14518. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14519. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14520. + * GNU General Public License for more details.
  14521. + *
  14522. + * You should have received a copy of the GNU General Public License
  14523. + * along with this program; if not, write to the Free Software
  14524. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  14525. + */
  14526. +
  14527. +/* $Id: opts.h,v 1.13 2007/05/14 06:27:18 sfjro Exp $ */
  14528. +
  14529. +#ifndef __AUFS_OPTS_H__
  14530. +#define __AUFS_OPTS_H__
  14531. +
  14532. +#ifdef __KERNEL__
  14533. +
  14534. +#include <linux/fs.h>
  14535. +#include <linux/namei.h>
  14536. +#include <linux/version.h>
  14537. +#include <linux/aufs_type.h>
  14538. +
  14539. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
  14540. +typedef const char* au_parser_pattern_t;
  14541. +#else
  14542. +typedef char* au_parser_pattern_t;
  14543. +#endif
  14544. +
  14545. +/* ---------------------------------------------------------------------- */
  14546. +
  14547. +struct opt_add {
  14548. + aufs_bindex_t bindex;
  14549. + char *path;
  14550. + int perm;
  14551. + struct nameidata nd;
  14552. +};
  14553. +
  14554. +struct opt_del {
  14555. + char *path;
  14556. + struct dentry *h_root;
  14557. +};
  14558. +
  14559. +struct opt_mod {
  14560. + char *path;
  14561. + int perm;
  14562. + struct dentry *h_root;
  14563. +};
  14564. +
  14565. +struct opt_xino {
  14566. + char *path;
  14567. + struct file *file;
  14568. +};
  14569. +
  14570. +struct opt {
  14571. + int type;
  14572. + union {
  14573. + struct opt_xino xino;
  14574. + struct opt_add add;
  14575. + struct opt_del del;
  14576. + struct opt_mod mod;
  14577. + int dirwh;
  14578. + int rdcache;
  14579. + int deblk;
  14580. + int nhash;
  14581. + int udba;
  14582. + int coo;
  14583. + };
  14584. +};
  14585. +
  14586. +struct opts {
  14587. + struct opt *opt;
  14588. + int max_opt;
  14589. +};
  14590. +
  14591. +/* ---------------------------------------------------------------------- */
  14592. +
  14593. +int br_perm_str(char *p, unsigned int len, int brperm);
  14594. +au_parser_pattern_t udba_str(int udba);
  14595. +void udba_set(struct super_block *sb, unsigned int flg);
  14596. +//au_parser_pattern_t coo_str(int coo);
  14597. +void au_free_opts(struct opts *opts);
  14598. +int au_parse_opts(struct super_block *sb, char *str, struct opts *opts);
  14599. +int au_do_opts_mount(struct super_block *sb, struct opts *opts);
  14600. +int au_do_opts_remount(struct super_block *sb, struct opts *opts,
  14601. + int *do_refresh, unsigned int *given);
  14602. +
  14603. +#endif /* __KERNEL__ */
  14604. +#endif /* __AUFS_OPTS_H__ */
  14605. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/plink.c linux-2.6.22.1/fs/aufs/plink.c
  14606. --- linux-2.6.22.1.oorig/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
  14607. +++ linux-2.6.22.1/fs/aufs/plink.c 2007-07-24 14:17:46.000000000 +0200
  14608. @@ -0,0 +1,331 @@
  14609. +/*
  14610. + * Copyright (C) 2007 Junjiro Okajima
  14611. + *
  14612. + * This program, aufs is free software; you can redistribute it and/or modify
  14613. + * it under the terms of the GNU General Public License as published by
  14614. + * the Free Software Foundation; either version 2 of the License, or
  14615. + * (at your option) any later version.
  14616. + *
  14617. + * This program is distributed in the hope that it will be useful,
  14618. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14619. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14620. + * GNU General Public License for more details.
  14621. + *
  14622. + * You should have received a copy of the GNU General Public License
  14623. + * along with this program; if not, write to the Free Software
  14624. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  14625. + */
  14626. +
  14627. +/* $Id: plink.c,v 1.4 2007/05/14 03:39:10 sfjro Exp $ */
  14628. +
  14629. +#include "aufs.h"
  14630. +
  14631. +struct pseudo_link {
  14632. + struct list_head list;
  14633. + struct inode *inode;
  14634. +};
  14635. +
  14636. +#ifdef CONFIG_AUFS_DEBUG
  14637. +void au_list_plink(struct super_block *sb)
  14638. +{
  14639. + struct aufs_sbinfo *sbinfo;
  14640. + struct list_head *plink_list;
  14641. + struct pseudo_link *plink;
  14642. +
  14643. + TraceEnter();
  14644. + SiMustAnyLock(sb);
  14645. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14646. +
  14647. + sbinfo = stosi(sb);
  14648. + plink_list = &sbinfo->si_plink;
  14649. + spin_lock(&sbinfo->si_plink_lock);
  14650. + list_for_each_entry(plink, plink_list, list)
  14651. + Dbg("%lu\n", plink->inode->i_ino);
  14652. + spin_unlock(&sbinfo->si_plink_lock);
  14653. +}
  14654. +#endif
  14655. +
  14656. +int au_is_plinked(struct super_block *sb, struct inode *inode)
  14657. +{
  14658. + int found;
  14659. + struct aufs_sbinfo *sbinfo;
  14660. + struct list_head *plink_list;
  14661. + struct pseudo_link *plink;
  14662. +
  14663. + LKTRTrace("i%lu\n", inode->i_ino);
  14664. + SiMustAnyLock(sb);
  14665. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14666. +
  14667. + found = 0;
  14668. + sbinfo = stosi(sb);
  14669. + plink_list = &sbinfo->si_plink;
  14670. + spin_lock(&sbinfo->si_plink_lock);
  14671. + list_for_each_entry(plink, plink_list, list)
  14672. + if (plink->inode == inode) {
  14673. + found = 1;
  14674. + break;
  14675. + }
  14676. + spin_unlock(&sbinfo->si_plink_lock);
  14677. + return found;
  14678. +}
  14679. +
  14680. +// 20 is max digits length of ulong 64
  14681. +#define PLINK_NAME_LEN ((20 + 1) * 2)
  14682. +
  14683. +static int plink_name(char *name, int len, struct inode *inode,
  14684. + aufs_bindex_t bindex)
  14685. +{
  14686. + int rlen;
  14687. + struct inode *h_inode;
  14688. +
  14689. + LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex);
  14690. + DEBUG_ON(len != PLINK_NAME_LEN);
  14691. + h_inode = au_h_iptr_i(inode, bindex);
  14692. + DEBUG_ON(!h_inode);
  14693. + rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
  14694. + DEBUG_ON(rlen >= len);
  14695. + return rlen;
  14696. +}
  14697. +
  14698. +struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
  14699. + struct inode *inode)
  14700. +{
  14701. + struct dentry *h_dentry, *h_parent;
  14702. + struct aufs_branch *br;
  14703. + struct inode *h_dir;
  14704. + char tgtname[PLINK_NAME_LEN];
  14705. + int len;
  14706. + struct lkup_args lkup;
  14707. +
  14708. + LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino);
  14709. + br = stobr(sb, bindex);
  14710. + h_parent = br->br_plink;
  14711. + DEBUG_ON(!h_parent);
  14712. + h_dir = h_parent->d_inode;
  14713. + DEBUG_ON(!h_dir);
  14714. +
  14715. + len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
  14716. +
  14717. + // always superio.
  14718. + lkup.nfsmnt = au_do_nfsmnt(br->br_mnt);
  14719. + lkup.dlgt = need_dlgt(sb);
  14720. + hi_lock_whplink(h_dir);
  14721. + h_dentry = sio_lkup_one(tgtname, h_parent, len, &lkup);
  14722. + i_unlock(h_dir);
  14723. + return h_dentry;
  14724. +}
  14725. +
  14726. +static int do_whplink(char *tgt, int len, struct dentry *h_parent,
  14727. + struct dentry *h_dentry, struct vfsmount *nfsmnt,
  14728. + struct super_block *sb)
  14729. +{
  14730. + int err;
  14731. + struct dentry *h_tgt;
  14732. + struct inode *h_dir;
  14733. + struct lkup_args lkup = {
  14734. + .nfsmnt = nfsmnt,
  14735. + .dlgt = need_dlgt(sb)
  14736. + };
  14737. +
  14738. + h_tgt = lkup_one(tgt, h_parent, len, &lkup);
  14739. + err = PTR_ERR(h_tgt);
  14740. + if (IS_ERR(h_tgt))
  14741. + goto out;
  14742. +
  14743. + err = 0;
  14744. + h_dir = h_parent->d_inode;
  14745. + if (unlikely(h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode))
  14746. + err = vfsub_unlink(h_dir, h_tgt, lkup.dlgt);
  14747. + if (!err && !h_tgt->d_inode) {
  14748. + err = vfsub_link(h_dentry, h_dir, h_tgt, lkup.dlgt);
  14749. + //inode->i_nlink++;
  14750. + }
  14751. + dput(h_tgt);
  14752. +
  14753. + out:
  14754. + TraceErr(err);
  14755. + return err;
  14756. +}
  14757. +
  14758. +struct do_whplink_args {
  14759. + int *errp;
  14760. + char *tgt;
  14761. + int len;
  14762. + struct dentry *h_parent;
  14763. + struct dentry *h_dentry;
  14764. + struct vfsmount *nfsmnt;
  14765. + struct super_block *sb;
  14766. +};
  14767. +
  14768. +static void call_do_whplink(void *args)
  14769. +{
  14770. + struct do_whplink_args *a = args;
  14771. + *a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry,
  14772. + a->nfsmnt, a->sb);
  14773. +}
  14774. +
  14775. +static int whplink(struct dentry *h_dentry, struct inode *inode,
  14776. + aufs_bindex_t bindex, struct super_block *sb)
  14777. +{
  14778. + int err, len;
  14779. + struct aufs_branch *br;
  14780. + struct dentry *h_parent;
  14781. + struct inode *h_dir;
  14782. + char tgtname[PLINK_NAME_LEN];
  14783. +
  14784. + LKTRTrace("%.*s\n", DLNPair(h_dentry));
  14785. + br = stobr(inode->i_sb, bindex);
  14786. + h_parent = br->br_plink;
  14787. + DEBUG_ON(!h_parent);
  14788. + h_dir = h_parent->d_inode;
  14789. + DEBUG_ON(!h_dir);
  14790. +
  14791. + len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
  14792. +
  14793. + // always superio.
  14794. + hi_lock_whplink(h_dir);
  14795. + if (!is_au_wkq(current)) {
  14796. + struct do_whplink_args args = {
  14797. + .errp = &err,
  14798. + .tgt = tgtname,
  14799. + .len = len,
  14800. + .h_parent = h_parent,
  14801. + .h_dentry = h_dentry,
  14802. + .nfsmnt = au_do_nfsmnt(br->br_mnt),
  14803. + .sb = sb
  14804. + };
  14805. + au_wkq_wait(call_do_whplink, &args, /*dlgt*/0);
  14806. + } else
  14807. + err = do_whplink(tgtname, len, h_parent, h_dentry,
  14808. + au_do_nfsmnt(br->br_mnt), sb);
  14809. + i_unlock(h_dir);
  14810. +
  14811. + TraceErr(err);
  14812. + return err;
  14813. +}
  14814. +
  14815. +void append_plink(struct super_block *sb, struct inode *inode,
  14816. + struct dentry *h_dentry, aufs_bindex_t bindex)
  14817. +{
  14818. + struct aufs_sbinfo *sbinfo;
  14819. + struct list_head *plink_list;
  14820. + struct pseudo_link *plink;
  14821. + int found, err, cnt;
  14822. +
  14823. + LKTRTrace("i%lu\n", inode->i_ino);
  14824. + SiMustAnyLock(sb);
  14825. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14826. +
  14827. + cnt = 0;
  14828. + found = 0;
  14829. + sbinfo = stosi(sb);
  14830. + plink_list = &sbinfo->si_plink;
  14831. + spin_lock(&sbinfo->si_plink_lock);
  14832. + list_for_each_entry(plink, plink_list, list) {
  14833. + cnt++;
  14834. + if (plink->inode == inode) {
  14835. + found = 1;
  14836. + break;
  14837. + }
  14838. + }
  14839. +
  14840. + err = 0;
  14841. + if (!found) {
  14842. + struct pseudo_link *plink;
  14843. +
  14844. + plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
  14845. + if (plink) {
  14846. + plink->inode = igrab(inode);
  14847. + list_add(&plink->list, plink_list);
  14848. + cnt++;
  14849. + } else
  14850. + err = -ENOMEM;
  14851. + }
  14852. + spin_unlock(&sbinfo->si_plink_lock);
  14853. +
  14854. + if (!err)
  14855. + err = whplink(h_dentry, inode, bindex, sb);
  14856. +
  14857. + if (unlikely(cnt > 100))
  14858. + Warn1("unexpectedly many pseudo links, %d\n", cnt);
  14859. + if (unlikely(err))
  14860. + Warn("err %d, damaged pseudo link. ignored.\n", err);
  14861. +}
  14862. +
  14863. +static void do_put_plink(struct pseudo_link *plink, int do_del)
  14864. +{
  14865. + TraceEnter();
  14866. +
  14867. + iput(plink->inode);
  14868. + if (do_del)
  14869. + list_del(&plink->list);
  14870. + kfree(plink);
  14871. +}
  14872. +
  14873. +void au_put_plink(struct super_block *sb)
  14874. +{
  14875. + struct aufs_sbinfo *sbinfo;
  14876. + struct list_head *plink_list;
  14877. + struct pseudo_link *plink, *tmp;
  14878. +
  14879. + TraceEnter();
  14880. + SiMustWriteLock(sb);
  14881. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14882. +
  14883. + sbinfo = stosi(sb);
  14884. + plink_list = &sbinfo->si_plink;
  14885. + //spin_lock(&sbinfo->si_plink_lock);
  14886. + list_for_each_entry_safe(plink, tmp, plink_list, list)
  14887. + do_put_plink(plink, 0);
  14888. + INIT_LIST_HEAD(plink_list);
  14889. + //spin_unlock(&sbinfo->si_plink_lock);
  14890. +}
  14891. +
  14892. +void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id)
  14893. +{
  14894. + struct aufs_sbinfo *sbinfo;
  14895. + struct list_head *plink_list;
  14896. + struct pseudo_link *plink, *tmp;
  14897. + struct inode *inode;
  14898. + aufs_bindex_t bstart, bend, bindex;
  14899. + int do_put;
  14900. +
  14901. + TraceEnter();
  14902. + SiMustWriteLock(sb);
  14903. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14904. +
  14905. + sbinfo = stosi(sb);
  14906. + plink_list = &sbinfo->si_plink;
  14907. + //spin_lock(&sbinfo->si_plink_lock);
  14908. + list_for_each_entry_safe(plink, tmp, plink_list, list) {
  14909. + do_put = 0;
  14910. + inode = igrab(plink->inode);
  14911. + ii_write_lock_child(inode);
  14912. + bstart = ibstart(inode);
  14913. + bend = ibend(inode);
  14914. + if (bstart >= 0) {
  14915. + for (bindex = bstart; bindex <= bend; bindex++) {
  14916. + if (!au_h_iptr_i(inode, bindex)
  14917. + || itoid_index(inode, bindex) != br_id)
  14918. + continue;
  14919. + set_h_iptr(inode, bindex, NULL, 0);
  14920. + do_put = 1;
  14921. + break;
  14922. + }
  14923. + } else
  14924. + do_put_plink(plink, 1);
  14925. +
  14926. + if (do_put) {
  14927. + for (bindex = bstart; bindex <= bend; bindex++)
  14928. + if (au_h_iptr_i(inode, bindex)) {
  14929. + do_put = 0;
  14930. + break;
  14931. + }
  14932. + if (do_put)
  14933. + do_put_plink(plink, 1);
  14934. + }
  14935. + ii_write_unlock(inode);
  14936. + iput(inode);
  14937. + }
  14938. + //spin_unlock(&sbinfo->si_plink_lock);
  14939. +}
  14940. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/sbinfo.c linux-2.6.22.1/fs/aufs/sbinfo.c
  14941. --- linux-2.6.22.1.oorig/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
  14942. +++ linux-2.6.22.1/fs/aufs/sbinfo.c 2007-07-24 14:17:46.000000000 +0200
  14943. @@ -0,0 +1,173 @@
  14944. +/*
  14945. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  14946. + *
  14947. + * This program, aufs is free software; you can redistribute it and/or modify
  14948. + * it under the terms of the GNU General Public License as published by
  14949. + * the Free Software Foundation; either version 2 of the License, or
  14950. + * (at your option) any later version.
  14951. + *
  14952. + * This program is distributed in the hope that it will be useful,
  14953. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14954. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14955. + * GNU General Public License for more details.
  14956. + *
  14957. + * You should have received a copy of the GNU General Public License
  14958. + * along with this program; if not, write to the Free Software
  14959. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  14960. + */
  14961. +
  14962. +/* $Id: sbinfo.c,v 1.30 2007/05/14 03:39:31 sfjro Exp $ */
  14963. +
  14964. +#include "aufs.h"
  14965. +
  14966. +struct aufs_sbinfo *stosi(struct super_block *sb)
  14967. +{
  14968. + struct aufs_sbinfo *sbinfo;
  14969. + sbinfo = sb->s_fs_info;
  14970. + //DEBUG_ON(sbinfo->si_bend < 0);
  14971. + return sbinfo;
  14972. +}
  14973. +
  14974. +aufs_bindex_t sbend(struct super_block *sb)
  14975. +{
  14976. + SiMustAnyLock(sb);
  14977. + return stosi(sb)->si_bend;
  14978. +}
  14979. +
  14980. +struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex)
  14981. +{
  14982. + SiMustAnyLock(sb);
  14983. + DEBUG_ON(bindex < 0 || sbend(sb) < bindex
  14984. + || !stosi(sb)->si_branch[0 + bindex]);
  14985. + return stosi(sb)->si_branch[0 + bindex];
  14986. +}
  14987. +
  14988. +int au_sigen(struct super_block *sb)
  14989. +{
  14990. + SiMustAnyLock(sb);
  14991. + return stosi(sb)->si_generation;
  14992. +}
  14993. +
  14994. +int au_sigen_inc(struct super_block *sb)
  14995. +{
  14996. + int gen;
  14997. +
  14998. + SiMustWriteLock(sb);
  14999. + gen = ++stosi(sb)->si_generation;
  15000. + au_update_digen(sb->s_root);
  15001. + au_update_iigen(sb->s_root->d_inode);
  15002. + sb->s_root->d_inode->i_version++;
  15003. + return gen;
  15004. +}
  15005. +
  15006. +int find_bindex(struct super_block *sb, struct aufs_branch *br)
  15007. +{
  15008. + aufs_bindex_t bindex, bend;
  15009. +
  15010. + bend = sbend(sb);
  15011. + for (bindex = 0; bindex <= bend; bindex++)
  15012. + if (stobr(sb, bindex) == br)
  15013. + return bindex;
  15014. + return -1;
  15015. +}
  15016. +
  15017. +/* ---------------------------------------------------------------------- */
  15018. +
  15019. +/* dentry and super_block lock. call at entry point */
  15020. +void aufs_read_lock(struct dentry *dentry, int flags)
  15021. +{
  15022. + si_read_lock(dentry->d_sb);
  15023. + if (flags & AUFS_D_WLOCK)
  15024. + di_write_lock_child(dentry);
  15025. + else
  15026. + di_read_lock_child(dentry, flags);
  15027. +}
  15028. +
  15029. +void aufs_read_unlock(struct dentry *dentry, int flags)
  15030. +{
  15031. + if (flags & AUFS_D_WLOCK)
  15032. + di_write_unlock(dentry);
  15033. + else
  15034. + di_read_unlock(dentry, flags);
  15035. + si_read_unlock(dentry->d_sb);
  15036. +}
  15037. +
  15038. +void aufs_write_lock(struct dentry *dentry)
  15039. +{
  15040. + //au_wkq_wait_nwtask();
  15041. + si_write_lock(dentry->d_sb);
  15042. + di_write_lock_child(dentry);
  15043. +}
  15044. +
  15045. +void aufs_write_unlock(struct dentry *dentry)
  15046. +{
  15047. + di_write_unlock(dentry);
  15048. + si_write_unlock(dentry->d_sb);
  15049. + //au_wkq_wait_nwtask();
  15050. +}
  15051. +
  15052. +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir)
  15053. +{
  15054. + DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
  15055. + si_read_lock(d1->d_sb);
  15056. + di_write_lock2_child(d1, d2, isdir);
  15057. +}
  15058. +
  15059. +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
  15060. +{
  15061. + DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
  15062. + di_write_unlock2(d1, d2);
  15063. + si_read_unlock(d1->d_sb);
  15064. +}
  15065. +
  15066. +/* ---------------------------------------------------------------------- */
  15067. +
  15068. +aufs_bindex_t new_br_id(struct super_block *sb)
  15069. +{
  15070. + aufs_bindex_t br_id;
  15071. +
  15072. + TraceEnter();
  15073. + SiMustWriteLock(sb);
  15074. +
  15075. + while (1) {
  15076. + br_id = ++stosi(sb)->si_last_br_id;
  15077. + if (br_id && find_brindex(sb, br_id) < 0)
  15078. + return br_id;
  15079. + }
  15080. +}
  15081. +
  15082. +/* ---------------------------------------------------------------------- */
  15083. +
  15084. +#ifdef CONFIG_AUFS_SYSAUFS
  15085. +static int make_xino(struct seq_file *seq, struct sysaufs_args *args,
  15086. + int *do_size)
  15087. +{
  15088. + int err;
  15089. + struct super_block *sb = args->sb;
  15090. + aufs_bindex_t bindex, bend;
  15091. + struct file *xf;
  15092. + struct inode *xi;
  15093. +
  15094. + TraceEnter();
  15095. + DEBUG_ON(args->index != SysaufsSb_XINO);
  15096. + SiMustReadLock(sb);
  15097. +
  15098. + *do_size = 0;
  15099. + err = seq_printf(seq, "%d %lu\n", sizeof(struct xino),
  15100. + atomic_long_read(&stosi(sb)->si_xino));
  15101. + bend = sbend(sb);
  15102. + for (bindex = 0; !err && bindex <= bend; bindex++) {
  15103. + xf = stobr(sb, bindex)->br_xino;
  15104. + xi = xf->f_dentry->d_inode;
  15105. + err = seq_printf(seq, "%d: %d, %Lux%d %Ld\n",
  15106. + bindex, file_count(xf),
  15107. + (u64)xi->i_blocks, 1 << xi->i_blkbits,
  15108. + i_size_read(xi));
  15109. + }
  15110. + return err;
  15111. +}
  15112. +
  15113. +sysaufs_op au_si_ops[] = {
  15114. + [SysaufsSb_XINO] = make_xino
  15115. +};
  15116. +#endif
  15117. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/super.c linux-2.6.22.1/fs/aufs/super.c
  15118. --- linux-2.6.22.1.oorig/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
  15119. +++ linux-2.6.22.1/fs/aufs/super.c 2007-07-24 14:17:46.000000000 +0200
  15120. @@ -0,0 +1,716 @@
  15121. +/*
  15122. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  15123. + *
  15124. + * This program, aufs is free software; you can redistribute it and/or modify
  15125. + * it under the terms of the GNU General Public License as published by
  15126. + * the Free Software Foundation; either version 2 of the License, or
  15127. + * (at your option) any later version.
  15128. + *
  15129. + * This program is distributed in the hope that it will be useful,
  15130. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15131. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15132. + * GNU General Public License for more details.
  15133. + *
  15134. + * You should have received a copy of the GNU General Public License
  15135. + * along with this program; if not, write to the Free Software
  15136. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15137. + */
  15138. +
  15139. +/* $Id: super.c,v 1.50 2007/05/14 03:39:42 sfjro Exp $ */
  15140. +
  15141. +#include <linux/module.h>
  15142. +#include <linux/seq_file.h>
  15143. +#include <linux/statfs.h>
  15144. +#include "aufs.h"
  15145. +
  15146. +/*
  15147. + * super_operations
  15148. + */
  15149. +static struct inode *aufs_alloc_inode(struct super_block *sb)
  15150. +{
  15151. + struct aufs_icntnr *c;
  15152. +
  15153. + TraceEnter();
  15154. +
  15155. + c = cache_alloc_icntnr();
  15156. + //if (LktrCond) {cache_free_icntnr(c); c = NULL;}
  15157. + if (c) {
  15158. + inode_init_once(&c->vfs_inode);
  15159. + c->vfs_inode.i_version = 1; //sigen(sb);
  15160. + c->iinfo.ii_hinode = NULL;
  15161. + return &c->vfs_inode;
  15162. + }
  15163. + return NULL;
  15164. +}
  15165. +
  15166. +static void aufs_destroy_inode(struct inode *inode)
  15167. +{
  15168. + LKTRTrace("i%lu\n", inode->i_ino);
  15169. + au_iinfo_fin(inode);
  15170. + cache_free_icntnr(container_of(inode, struct aufs_icntnr, vfs_inode));
  15171. +}
  15172. +
  15173. +//todo: how about merge with alloc_inode()?
  15174. +static void aufs_read_inode(struct inode *inode)
  15175. +{
  15176. + int err;
  15177. +
  15178. + LKTRTrace("i%lu\n", inode->i_ino);
  15179. +
  15180. + err = au_iinfo_init(inode);
  15181. + //if (LktrCond) err = -1;
  15182. + if (!err) {
  15183. + inode->i_version++;
  15184. + inode->i_op = &aufs_iop;
  15185. + inode->i_fop = &aufs_file_fop;
  15186. + inode->i_mapping->a_ops = &aufs_aop;
  15187. + return; /* success */
  15188. + }
  15189. +
  15190. + LKTRTrace("intializing inode info failed(%d)\n", err);
  15191. + make_bad_inode(inode);
  15192. +}
  15193. +
  15194. +int au_show_brs(struct seq_file *seq, struct super_block *sb)
  15195. +{
  15196. + int err;
  15197. + aufs_bindex_t bindex, bend;
  15198. + char a[16];
  15199. + struct dentry *root;
  15200. +
  15201. + TraceEnter();
  15202. + SiMustAnyLock(sb);
  15203. + root = sb->s_root;
  15204. + DiMustAnyLock(root);
  15205. +
  15206. + err = 0;
  15207. + bend = sbend(sb);
  15208. + for (bindex = 0; !err && bindex <= bend; bindex++) {
  15209. + err = br_perm_str(a, sizeof(a), sbr_perm(sb, bindex));
  15210. + if (!err)
  15211. + err = seq_path(seq, sbr_mnt(sb, bindex),
  15212. + au_h_dptr_i(root, bindex), au_esc_chars);
  15213. + if (err > 0)
  15214. + err = seq_printf(seq, "=%s", a);
  15215. + if (!err && bindex != bend)
  15216. + err = seq_putc(seq, ':');
  15217. + }
  15218. +
  15219. + TraceErr(err);
  15220. + return err;
  15221. +}
  15222. +
  15223. +static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
  15224. +{
  15225. + int err, n;
  15226. + struct super_block *sb;
  15227. + struct aufs_sbinfo *sbinfo;
  15228. + struct dentry *root;
  15229. + struct file *xino;
  15230. +
  15231. + TraceEnter();
  15232. +
  15233. + sb = mnt->mnt_sb;
  15234. + root = sb->s_root;
  15235. + aufs_read_lock(root, !AUFS_I_RLOCK);
  15236. + if (au_flag_test(sb, AuFlag_XINO)) {
  15237. + err = seq_puts(m, ",xino=");
  15238. + if (unlikely(err))
  15239. + goto out;
  15240. + xino = stobr(sb, 0)->br_xino;
  15241. + err = seq_path(m, xino->f_vfsmnt, xino->f_dentry, au_esc_chars);
  15242. + if (unlikely(err <= 0))
  15243. + goto out;
  15244. + err = 0;
  15245. +
  15246. +#define Deleted "\\040(deleted)"
  15247. + m->count -= sizeof(Deleted) - 1;
  15248. + DEBUG_ON(memcmp(m->buf + m->count, Deleted,
  15249. + sizeof(Deleted) - 1));
  15250. +#undef Deleted
  15251. + } else
  15252. + err = seq_puts(m, ",noxino");
  15253. +
  15254. + n = au_flag_test(sb, AuFlag_PLINK);
  15255. + if (unlikely(!err && (AuDefFlags & AuFlag_PLINK) != n))
  15256. + err = seq_printf(m, ",%splink", n ? "" : "no");
  15257. + n = au_flag_test_udba(sb);
  15258. + if (unlikely(!err && (AuDefFlags & AuMask_UDBA) != n))
  15259. + err = seq_printf(m, ",udba=%s", udba_str(n));
  15260. + n = au_flag_test(sb, AuFlag_ALWAYS_DIROPQ);
  15261. + if (unlikely(!err && (AuDefFlags & AuFlag_ALWAYS_DIROPQ) != n))
  15262. + err = seq_printf(m, ",diropq=%c", n ? 'a' : 'w');
  15263. + n = au_flag_test(sb, AuFlag_DLGT);
  15264. + if (unlikely(!err && (AuDefFlags & AuFlag_DLGT) != n))
  15265. + err = seq_printf(m, ",%sdlgt", n ? "" : "no");
  15266. + n = au_flag_test(sb, AuFlag_WARN_PERM);
  15267. + if (unlikely(!err && (AuDefFlags & AuFlag_WARN_PERM) != n))
  15268. + err = seq_printf(m, ",%swarn_perm", n ? "" : "no");
  15269. +
  15270. + sbinfo = stosi(sb);
  15271. + n = sbinfo->si_dirwh;
  15272. + if (unlikely(!err && n != AUFS_DIRWH_DEF))
  15273. + err = seq_printf(m, ",dirwh=%d", n);
  15274. + n = sbinfo->si_rdcache / HZ;
  15275. + if (unlikely(!err && n != AUFS_RDCACHE_DEF))
  15276. + err = seq_printf(m, ",rdcache=%d", n);
  15277. +#if 0
  15278. + n = au_flag_test_coo(sb);
  15279. + if (unlikely(!err && (AuDefFlags & AuMask_COO) != n))
  15280. + err = seq_printf(m, ",coo=%s", coo_str(n));
  15281. +#endif
  15282. +
  15283. + if (!err && !sysaufs_brs) {
  15284. +#ifdef CONFIG_AUFS_COMPAT
  15285. + err = seq_puts(m, ",dirs=");
  15286. +#else
  15287. + err = seq_puts(m, ",br:");
  15288. +#endif
  15289. + if (!err)
  15290. + err = au_show_brs(m, sb);
  15291. + }
  15292. +
  15293. + out:
  15294. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  15295. + TraceErr(err);
  15296. + if (err)
  15297. + err = -E2BIG;
  15298. + TraceErr(err);
  15299. + return err;
  15300. +}
  15301. +
  15302. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  15303. +#define StatfsLock(d) aufs_read_lock((d)->d_sb->s_root, 0)
  15304. +#define StatfsUnlock(d) aufs_read_unlock((d)->d_sb->s_root, 0)
  15305. +#define StatfsArg(d) au_h_dptr((d)->d_sb->s_root)
  15306. +#define StatfsHInode(d) (StatfsArg(d)->d_inode)
  15307. +#define StatfsSb(d) ((d)->d_sb)
  15308. +static int aufs_statfs(struct dentry *arg, struct kstatfs *buf)
  15309. +#else
  15310. +#define StatfsLock(s) si_read_lock(s)
  15311. +#define StatfsUnlock(s) si_read_unlock(s)
  15312. +#define StatfsArg(s) sbr_sb(s, 0)
  15313. +#define StatfsHInode(s) (StatfsArg(s)->s_root->d_inode)
  15314. +#define StatfsSb(s) (s)
  15315. +static int aufs_statfs(struct super_block *arg, struct kstatfs *buf)
  15316. +#endif
  15317. +{
  15318. + int err;
  15319. +
  15320. + TraceEnter();
  15321. +
  15322. + StatfsLock(arg);
  15323. + err = vfsub_statfs(StatfsArg(arg), buf, need_dlgt(StatfsSb(arg)));
  15324. + //if (LktrCond) err = -1;
  15325. + StatfsUnlock(arg);
  15326. + if (!err) {
  15327. + //buf->f_type = AUFS_SUPER_MAGIC;
  15328. + buf->f_type = 0;
  15329. + buf->f_namelen -= AUFS_WH_PFX_LEN;
  15330. + memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
  15331. + }
  15332. + //buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
  15333. +
  15334. + TraceErr(err);
  15335. + return err;
  15336. +}
  15337. +
  15338. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) || defined(UbuntuEdgy17Umount18)
  15339. +#define UmountBeginSb(mnt) (mnt)->mnt_sb
  15340. +static void aufs_umount_begin(struct vfsmount *arg, int flags)
  15341. +#else
  15342. +#define UmountBeginSb(sb) sb
  15343. +static void aufs_umount_begin(struct super_block *arg)
  15344. +#endif
  15345. +{
  15346. + struct super_block *sb = UmountBeginSb(arg);
  15347. +
  15348. + if (unlikely(!stosi(sb)))
  15349. + return;
  15350. +
  15351. + //au_wkq_wait_nwtask();
  15352. + si_write_lock(sb);
  15353. + if (au_flag_test(sb, AuFlag_PLINK)) {
  15354. + au_put_plink(sb);
  15355. + //kobj_umount(stosi(sb));
  15356. + }
  15357. +#if 0
  15358. + if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
  15359. + shrink_dcache_sb(sb);
  15360. +#endif
  15361. + si_write_unlock(sb);
  15362. +}
  15363. +
  15364. +static void free_sbinfo(struct aufs_sbinfo *sbinfo)
  15365. +{
  15366. + TraceEnter();
  15367. + DEBUG_ON(!sbinfo
  15368. + || !list_empty(&sbinfo->si_plink));
  15369. +
  15370. + free_branches(sbinfo);
  15371. + kfree(sbinfo->si_branch);
  15372. + kfree(sbinfo);
  15373. +}
  15374. +
  15375. +/* final actions when unmounting a file system */
  15376. +static void aufs_put_super(struct super_block *sb)
  15377. +{
  15378. + struct aufs_sbinfo *sbinfo;
  15379. +
  15380. + TraceEnter();
  15381. +
  15382. + sbinfo = stosi(sb);
  15383. + if (unlikely(!sbinfo))
  15384. + return;
  15385. +
  15386. + sysaufs_del(sbinfo);
  15387. +
  15388. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && !defined(UbuntuEdgy17Umount18)
  15389. + // umount_begin() may not be called.
  15390. + aufs_umount_begin(sb);
  15391. +#endif
  15392. + free_sbinfo(sbinfo);
  15393. +}
  15394. +
  15395. +/* ---------------------------------------------------------------------- */
  15396. +
  15397. +/*
  15398. + * refresh directories at remount time.
  15399. + */
  15400. +static int do_refresh_dir(struct dentry *dentry, unsigned int flags)
  15401. +{
  15402. + int err;
  15403. + struct dentry *parent;
  15404. + struct inode *inode;
  15405. +
  15406. + LKTRTrace("%.*s\n", DLNPair(dentry));
  15407. + inode = dentry->d_inode;
  15408. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  15409. +
  15410. + di_write_lock_child(dentry);
  15411. + parent = dget_parent(dentry);
  15412. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  15413. + err = au_refresh_hdentry(dentry, S_IFDIR);
  15414. + if (err >= 0) {
  15415. + err = au_refresh_hinode(inode, dentry);
  15416. + if (!err)
  15417. + au_reset_hinotify(inode, flags);
  15418. + }
  15419. + if (unlikely(err))
  15420. + Err("unrecoverable error %d\n", err);
  15421. + di_read_unlock(parent, AUFS_I_RLOCK);
  15422. + dput(parent);
  15423. + di_write_unlock(dentry);
  15424. +
  15425. + TraceErr(err);
  15426. + return err;
  15427. +}
  15428. +
  15429. +static int test_dir(struct dentry *dentry, void *arg)
  15430. +{
  15431. + return S_ISDIR(dentry->d_inode->i_mode);
  15432. +}
  15433. +
  15434. +static int refresh_dir(struct dentry *root, int sgen)
  15435. +{
  15436. + int err, i, j, ndentry;
  15437. + const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
  15438. + struct au_dcsub_pages dpages;
  15439. + struct au_dpage *dpage;
  15440. + struct dentry **dentries;
  15441. +
  15442. + LKTRTrace("sgen %d\n", sgen);
  15443. + SiMustWriteLock(root->d_sb);
  15444. + DEBUG_ON(au_digen(root) != sgen);
  15445. + DiMustWriteLock(root);
  15446. +
  15447. + err = au_dpages_init(&dpages, GFP_KERNEL);
  15448. + if (unlikely(err))
  15449. + goto out;
  15450. + err = au_dcsub_pages(&dpages, root, test_dir, NULL);
  15451. + if (unlikely(err))
  15452. + goto out_dpages;
  15453. +
  15454. + DiMustNoWaiters(root);
  15455. + IiMustNoWaiters(root->d_inode);
  15456. + di_write_unlock(root);
  15457. + for (i = 0; !err && i < dpages.ndpage; i++) {
  15458. + dpage = dpages.dpages + i;
  15459. + dentries = dpage->dentries;
  15460. + ndentry = dpage->ndentry;
  15461. + for (j = 0; !err && j < ndentry; j++) {
  15462. + struct dentry *d;
  15463. + d = dentries[j];
  15464. + DEBUG_ON(!S_ISDIR(d->d_inode->i_mode)
  15465. + || IS_ROOT(d)
  15466. + || au_digen(d->d_parent) != sgen);
  15467. + if (au_digen(d) != sgen)
  15468. + err = do_refresh_dir(d, flags);
  15469. + }
  15470. + }
  15471. + di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
  15472. +
  15473. + out_dpages:
  15474. + au_dpages_free(&dpages);
  15475. + out:
  15476. + TraceErr(err);
  15477. + return err;
  15478. +}
  15479. +
  15480. +/* stop extra interpretation of errno in mount(8), and strange error messages */
  15481. +static int cvt_err(int err)
  15482. +{
  15483. + TraceErr(err);
  15484. +
  15485. + switch (err) {
  15486. + case -ENOENT:
  15487. + case -ENOTDIR:
  15488. + case -EEXIST:
  15489. + case -EIO:
  15490. + err = -EINVAL;
  15491. + }
  15492. + return err;
  15493. +}
  15494. +
  15495. +/* protected by s_umount */
  15496. +static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
  15497. +{
  15498. + int err, do_refresh;
  15499. + struct dentry *root;
  15500. + struct inode *inode;
  15501. + struct opts opts;
  15502. + unsigned int given, dlgt;
  15503. +
  15504. + //au_debug_on();
  15505. + LKTRTrace("flags 0x%x, data %s, len %d\n",
  15506. + *flags, data ? data : "NULL", data ? strlen(data) : 0);
  15507. +
  15508. + err = 0;
  15509. + if (unlikely(!data || !*data))
  15510. + goto out; /* success */
  15511. +
  15512. + err = -ENOMEM;
  15513. + memset(&opts, 0, sizeof(opts));
  15514. + opts.opt = (void*)__get_free_page(GFP_KERNEL);
  15515. + //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
  15516. + if (unlikely(!opts.opt))
  15517. + goto out;
  15518. + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
  15519. +
  15520. + /* parse it before aufs lock */
  15521. + err = au_parse_opts(sb, data, &opts);
  15522. + //if (LktrCond) {au_free_opts(&opts); err = -1;}
  15523. + if (unlikely(err))
  15524. + goto out_opts;
  15525. +
  15526. + root = sb->s_root;
  15527. + inode = root->d_inode;
  15528. + i_lock(inode);
  15529. + aufs_write_lock(root);
  15530. +
  15531. + //DbgSleep(3);
  15532. +
  15533. + /* au_do_opts() may return an error */
  15534. + do_refresh = 0;
  15535. + given = 0;
  15536. + err = au_do_opts_remount(sb, &opts, &do_refresh, &given);
  15537. + //if (LktrCond) err = -1;
  15538. + au_free_opts(&opts);
  15539. +
  15540. + if (do_refresh) {
  15541. + int rerr;
  15542. + struct aufs_sbinfo *sbinfo;
  15543. +
  15544. + dlgt = au_flag_test(sb, AuFlag_DLGT);
  15545. + au_flag_clr(sb, AuFlag_DLGT);
  15546. + au_sigen_inc(sb);
  15547. + au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
  15548. + sbinfo = stosi(sb);
  15549. + sbinfo->si_failed_refresh_dirs = 0;
  15550. + rerr = refresh_dir(root, au_sigen(sb));
  15551. + if (unlikely(rerr)) {
  15552. + sbinfo->si_failed_refresh_dirs = 1;
  15553. + Warn("Refreshing directories failed, ignores (%d)\n",
  15554. + rerr);
  15555. + }
  15556. + au_cpup_attr_all(inode);
  15557. + au_flag_set(sb, dlgt);
  15558. + }
  15559. +
  15560. + aufs_write_unlock(root);
  15561. + i_unlock(inode);
  15562. + /* braces are added to stop a warning */
  15563. + if (do_refresh) {
  15564. + sysaufs_notify_remount();
  15565. + }
  15566. +
  15567. + out_opts:
  15568. + free_page((unsigned long)opts.opt);
  15569. + out:
  15570. + err = cvt_err(err);
  15571. + TraceErr(err);
  15572. + //au_debug_off();
  15573. + return err;
  15574. +}
  15575. +
  15576. +static struct super_operations aufs_sop = {
  15577. + .alloc_inode = aufs_alloc_inode,
  15578. + .destroy_inode = aufs_destroy_inode,
  15579. + .read_inode = aufs_read_inode,
  15580. + //.dirty_inode = aufs_dirty_inode,
  15581. + //.write_inode = aufs_write_inode,
  15582. + //void (*put_inode) (struct inode *);
  15583. + .drop_inode = generic_delete_inode,
  15584. + //.delete_inode = aufs_delete_inode,
  15585. + //.clear_inode = aufs_clear_inode,
  15586. +
  15587. + .show_options = aufs_show_options,
  15588. + .statfs = aufs_statfs,
  15589. +
  15590. + .put_super = aufs_put_super,
  15591. + //void (*write_super) (struct super_block *);
  15592. + //int (*sync_fs)(struct super_block *sb, int wait);
  15593. + //void (*write_super_lockfs) (struct super_block *);
  15594. + //void (*unlockfs) (struct super_block *);
  15595. + .remount_fs = aufs_remount_fs,
  15596. + // depends upon umount flags. also use put_super() (< 2.6.18)
  15597. + .umount_begin = aufs_umount_begin
  15598. +};
  15599. +
  15600. +/* ---------------------------------------------------------------------- */
  15601. +
  15602. +/*
  15603. + * at first mount time.
  15604. + */
  15605. +
  15606. +static int alloc_sbinfo(struct super_block *sb)
  15607. +{
  15608. + struct aufs_sbinfo *sbinfo;
  15609. +
  15610. + TraceEnter();
  15611. +
  15612. + sbinfo = kmalloc(sizeof(*sbinfo), GFP_KERNEL);
  15613. + //if (LktrCond) {kfree(sbinfo); sbinfo = NULL;}
  15614. + if (unlikely(!sbinfo))
  15615. + goto out;
  15616. + sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_KERNEL);
  15617. + //if (LktrCond) {kfree(sbinfo->si_branch); sbinfo->si_branch = NULL;}
  15618. + if (unlikely(!sbinfo->si_branch)) {
  15619. + kfree(sbinfo);
  15620. + goto out;
  15621. + }
  15622. + rw_init_wlock(&sbinfo->si_rwsem);
  15623. + sbinfo->si_bend = -1;
  15624. + atomic_long_set(&sbinfo->si_xino, AUFS_FIRST_INO);
  15625. + spin_lock_init(&sbinfo->si_plink_lock);
  15626. + INIT_LIST_HEAD(&sbinfo->si_plink);
  15627. + init_lvma(sbinfo);
  15628. + sbinfo->si_generation = 0;
  15629. + sbinfo->si_last_br_id = 0;
  15630. + sbinfo->si_failed_refresh_dirs = 0;
  15631. + sbinfo->si_flags = 0;
  15632. + sbinfo->si_dirwh = AUFS_DIRWH_DEF;
  15633. + sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
  15634. + //atomic_set(&sbinfo->si_hinotify, 0);
  15635. + //init_waitqueue_head(&sbinfo->si_hinotify_wq);
  15636. +
  15637. + sb->s_fs_info = sbinfo;
  15638. + au_flag_set(sb, AuDefFlags);
  15639. +#ifdef ForceInotify
  15640. + udba_set(sb, AuFlag_UDBA_INOTIFY);
  15641. +#endif
  15642. +#ifdef ForceDlgt
  15643. + au_flag_set(sb, AuFlag_DLGT);
  15644. +#endif
  15645. +#ifdef ForceNoPlink
  15646. + au_flag_clr(sb, AuFlag_PLINK);
  15647. +#endif
  15648. + return 0; /* success */
  15649. +
  15650. + out:
  15651. + TraceErr(-ENOMEM);
  15652. + return -ENOMEM;
  15653. +}
  15654. +
  15655. +static int alloc_root(struct super_block *sb)
  15656. +{
  15657. + int err;
  15658. + struct inode *inode;
  15659. + struct dentry *root;
  15660. +
  15661. + TraceEnter();
  15662. +
  15663. + err = -ENOMEM;
  15664. + inode = iget(sb, AUFS_ROOT_INO);
  15665. + //if (LktrCond) {iput(inode); inode = NULL;}
  15666. + if (unlikely(!inode))
  15667. + goto out;
  15668. + err = PTR_ERR(inode);
  15669. + if (IS_ERR(inode))
  15670. + goto out;
  15671. + err = -ENOMEM;
  15672. + if (unlikely(is_bad_inode(inode)))
  15673. + goto out_iput;
  15674. +
  15675. + root = d_alloc_root(inode);
  15676. + //if (LktrCond) {igrab(inode); dput(root); root = NULL;}
  15677. + if (unlikely(!root))
  15678. + goto out_iput;
  15679. + err = PTR_ERR(root);
  15680. + if (IS_ERR(root))
  15681. + goto out_iput;
  15682. +
  15683. + err = au_alloc_dinfo(root);
  15684. + //if (LktrCond){rw_write_unlock(&dtodi(root)->di_rwsem);err=-1;}
  15685. + if (!err) {
  15686. + sb->s_root = root;
  15687. + return 0; /* success */
  15688. + }
  15689. + dput(root);
  15690. + goto out; /* do not iput */
  15691. +
  15692. + out_iput:
  15693. + iput(inode);
  15694. + out:
  15695. + TraceErr(err);
  15696. + return err;
  15697. +
  15698. +}
  15699. +
  15700. +static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
  15701. +{
  15702. + int err;
  15703. + struct dentry *root;
  15704. + struct inode *inode;
  15705. + struct opts opts;
  15706. + char *arg = raw_data;
  15707. +
  15708. + //au_debug_on();
  15709. + if (unlikely(!arg || !*arg)) {
  15710. + err = -EINVAL;
  15711. + Err("no arg\n");
  15712. + goto out;
  15713. + }
  15714. + LKTRTrace("%s, silent %d\n", arg, silent);
  15715. +
  15716. + err = -ENOMEM;
  15717. + memset(&opts, 0, sizeof(opts));
  15718. + opts.opt = (void*)__get_free_page(GFP_KERNEL);
  15719. + //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
  15720. + if (unlikely(!opts.opt))
  15721. + goto out;
  15722. + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
  15723. +
  15724. + err = alloc_sbinfo(sb);
  15725. + //if (LktrCond) {si_write_unlock(sb);free_sbinfo(stosi(sb));err=-1;}
  15726. + if (unlikely(err))
  15727. + goto out_opts;
  15728. + SiMustWriteLock(sb);
  15729. + /* all timestamps always follow the ones on the branch */
  15730. + sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
  15731. + sb->s_op = &aufs_sop;
  15732. + au_init_export_op(sb);
  15733. + //err = kobj_mount(stosi(sb));
  15734. + //if (err)
  15735. + //goto out_info;
  15736. +
  15737. + err = alloc_root(sb);
  15738. + //if (LktrCond) {rw_write_unlock(&dtodi(sb->s_root)->di_rwsem);
  15739. + //dput(sb->s_root);sb->s_root=NULL;err=-1;}
  15740. + if (unlikely(err)) {
  15741. + DEBUG_ON(sb->s_root);
  15742. + si_write_unlock(sb);
  15743. + goto out_info;
  15744. + }
  15745. + root = sb->s_root;
  15746. + DiMustWriteLock(root);
  15747. + inode = root->d_inode;
  15748. + inode->i_nlink = 2;
  15749. +
  15750. + /*
  15751. + * actually we can parse options regardless aufs lock here.
  15752. + * but at remount time, parsing must be done before aufs lock.
  15753. + * so we follow the same rule.
  15754. + */
  15755. + ii_write_lock_parent(inode);
  15756. + aufs_write_unlock(root);
  15757. + err = au_parse_opts(sb, arg, &opts);
  15758. + //if (LktrCond) {au_free_opts(&opts); err = -1;}
  15759. + if (unlikely(err))
  15760. + goto out_root;
  15761. +
  15762. + /* lock vfs_inode first, then aufs. */
  15763. + i_lock(inode);
  15764. + inode->i_op = &aufs_dir_iop;
  15765. + inode->i_fop = &aufs_dir_fop;
  15766. + aufs_write_lock(root);
  15767. +
  15768. + sb->s_maxbytes = 0;
  15769. + err = au_do_opts_mount(sb, &opts);
  15770. + //if (LktrCond) err = -1;
  15771. + au_free_opts(&opts);
  15772. + if (unlikely(err))
  15773. + goto out_unlock;
  15774. + DEBUG_ON(!sb->s_maxbytes);
  15775. +
  15776. + //DbgDentry(root);
  15777. + aufs_write_unlock(root);
  15778. + i_unlock(inode);
  15779. + //DbgSb(sb);
  15780. + goto out_opts; /* success */
  15781. +
  15782. + out_unlock:
  15783. + aufs_write_unlock(root);
  15784. + i_unlock(inode);
  15785. + out_root:
  15786. + dput(root);
  15787. + sb->s_root = NULL;
  15788. + out_info:
  15789. + free_sbinfo(stosi(sb));
  15790. + sb->s_fs_info = NULL;
  15791. + out_opts:
  15792. + free_page((unsigned long)opts.opt);
  15793. + out:
  15794. + TraceErr(err);
  15795. + err = cvt_err(err);
  15796. + TraceErr(err);
  15797. + //au_debug_off();
  15798. + return err;
  15799. +}
  15800. +
  15801. +/* ---------------------------------------------------------------------- */
  15802. +
  15803. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  15804. +static int aufs_get_sb(struct file_system_type *fs_type, int flags,
  15805. + const char *dev_name, void *raw_data,
  15806. + struct vfsmount *mnt)
  15807. +{
  15808. + int err;
  15809. +
  15810. + /* all timestamps always follow the ones on the branch */
  15811. + //mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME;
  15812. + err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
  15813. + if (!err) {
  15814. + struct aufs_sbinfo *sbinfo = stosi(mnt->mnt_sb);
  15815. + sbinfo->si_mnt = mnt;
  15816. + sysaufs_add(sbinfo);
  15817. + }
  15818. + return err;
  15819. +}
  15820. +#else
  15821. +static struct super_block *aufs_get_sb(struct file_system_type *fs_type,
  15822. + int flags, const char *dev_name,
  15823. + void *raw_data)
  15824. +{
  15825. + return get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super);
  15826. +}
  15827. +#endif
  15828. +
  15829. +struct file_system_type aufs_fs_type = {
  15830. + .name = AUFS_FSTYPE,
  15831. + .fs_flags = FS_REVAL_DOT, // for UDBA and NFS branch
  15832. + .get_sb = aufs_get_sb,
  15833. + .kill_sb = generic_shutdown_super,
  15834. + //no need to __module_get() and module_put().
  15835. + .owner = THIS_MODULE,
  15836. +};
  15837. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/super.h linux-2.6.22.1/fs/aufs/super.h
  15838. --- linux-2.6.22.1.oorig/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
  15839. +++ linux-2.6.22.1/fs/aufs/super.h 2007-07-24 14:17:46.000000000 +0200
  15840. @@ -0,0 +1,339 @@
  15841. +/*
  15842. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  15843. + *
  15844. + * This program, aufs is free software; you can redistribute it and/or modify
  15845. + * it under the terms of the GNU General Public License as published by
  15846. + * the Free Software Foundation; either version 2 of the License, or
  15847. + * (at your option) any later version.
  15848. + *
  15849. + * This program is distributed in the hope that it will be useful,
  15850. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15851. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15852. + * GNU General Public License for more details.
  15853. + *
  15854. + * You should have received a copy of the GNU General Public License
  15855. + * along with this program; if not, write to the Free Software
  15856. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15857. + */
  15858. +
  15859. +/* $Id: super.h,v 1.44 2007/05/14 03:39:54 sfjro Exp $ */
  15860. +
  15861. +#ifndef __AUFS_SUPER_H__
  15862. +#define __AUFS_SUPER_H__
  15863. +
  15864. +#ifdef __KERNEL__
  15865. +
  15866. +#include <linux/fs.h>
  15867. +#include <linux/version.h>
  15868. +#include <linux/aufs_type.h>
  15869. +#include "misc.h"
  15870. +#include "sysaufs.h"
  15871. +
  15872. +#ifdef CONFIG_AUFS_SYSAUFS
  15873. +/* entries under sysfs per mount-point */
  15874. +enum {SysaufsSb_XINO, /* SysaufsSb_PLINK, */ SysaufsSb_Last};
  15875. +struct sysaufs_sbinfo {
  15876. + au_subsys_t subsys;
  15877. + struct sysaufs_entry array[SysaufsSb_Last];
  15878. +};
  15879. +extern sysaufs_op au_si_ops[];
  15880. +#else
  15881. +struct sysaufs_sbinfo {};
  15882. +#endif
  15883. +
  15884. +struct aufs_sbinfo {
  15885. + struct aufs_rwsem si_rwsem;
  15886. +
  15887. + /* branch management */
  15888. + /* wrap around attack by superuser? No. */
  15889. + int si_generation;
  15890. +
  15891. + /*
  15892. + * set true when refresh_dirs() at remount time failed.
  15893. + * then try refreshing dirs at access time again.
  15894. + * if it is false, refreshing dirs at access time is unnecesary
  15895. + */
  15896. + unsigned int si_failed_refresh_dirs:1;
  15897. +
  15898. + aufs_bindex_t si_bend;
  15899. + aufs_bindex_t si_last_br_id;
  15900. + struct aufs_branch **si_branch;
  15901. +
  15902. + /* mount flags */
  15903. + unsigned int si_flags;
  15904. +
  15905. + /* external inode number table */
  15906. + atomic_long_t si_xino; // time bomb
  15907. + //struct file *si_xino_bmap;
  15908. +
  15909. + /* readdir cache time, max, in HZ */
  15910. + unsigned long si_rdcache;
  15911. +
  15912. + /*
  15913. + * If the number of whiteouts are larger than si_dirwh, leave all of
  15914. + * them after rename_whtmp to reduce the cost of rmdir(2).
  15915. + * future fsck.aufs or kernel thread will remove them later.
  15916. + * Otherwise, remove all whiteouts and the dir in rmdir(2).
  15917. + */
  15918. + unsigned int si_dirwh;
  15919. +
  15920. + /* pseudo_link list */ // dirty
  15921. + spinlock_t si_plink_lock;
  15922. + struct list_head si_plink;
  15923. +
  15924. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  15925. + /* super_blocks list is not exported */
  15926. + struct list_head si_list;
  15927. + struct vfsmount *si_mnt; /* no get/put */
  15928. +#endif
  15929. +
  15930. + /* sysfs */
  15931. + struct sysaufs_sbinfo si_sysaufs;
  15932. +
  15933. +#ifdef CONFIG_AUFS_HINOTIFY
  15934. + /* hinotify */
  15935. + //atomic_t si_hinotify;
  15936. + //wait_queue_head_t si_hinotify_wq;
  15937. +#endif
  15938. +
  15939. +#ifdef CONFIG_AUFS_ROBR
  15940. + /* locked vma list for mmap() */ // very dirty
  15941. + spinlock_t si_lvma_lock;
  15942. + struct list_head si_lvma;
  15943. +#endif
  15944. +};
  15945. +
  15946. +/* an entry in a xino file */
  15947. +struct xino {
  15948. + ino_t ino;
  15949. + //__u32 h_gen;
  15950. +} __attribute__ ((packed));
  15951. +
  15952. +//#define AuXino_INVALID_HGEN (-1)
  15953. +
  15954. +/* ---------------------------------------------------------------------- */
  15955. +
  15956. +/* Mount flags */
  15957. +#define AuFlag_XINO 1
  15958. +#define AuFlag_ZXINO (1 << 1)
  15959. +#define AuFlag_PLINK (1 << 2)
  15960. +#define AuFlag_UDBA_NONE (1 << 3)
  15961. +#define AuFlag_UDBA_REVAL (1 << 4)
  15962. +#define AuFlag_UDBA_INOTIFY (1 << 5)
  15963. +#define AuFlag_WARN_PERM (1 << 6)
  15964. +#define AuFlag_COO_NONE (1 << 7)
  15965. +#define AuFlag_COO_LEAF (1 << 8)
  15966. +#define AuFlag_COO_ALL (1 << 9)
  15967. +#define AuFlag_ALWAYS_DIROPQ (1 << 10)
  15968. +#define AuFlag_DLGT (1 << 11)
  15969. +
  15970. +#define AuMask_UDBA (AuFlag_UDBA_NONE | AuFlag_UDBA_REVAL \
  15971. + | AuFlag_UDBA_INOTIFY)
  15972. +#define AuMask_COO (AuFlag_COO_NONE | AuFlag_COO_LEAF \
  15973. + | AuFlag_COO_ALL)
  15974. +
  15975. +#ifdef CONFIG_AUFS_COMPAT
  15976. +#define AuDefFlag_DIROPQ AuFlag_ALWAYS_DIROPQ
  15977. +#else
  15978. +#define AuDefFlag_DIROPQ 0
  15979. +#endif
  15980. +
  15981. +#define AuDefFlags_COMM (AuFlag_XINO | AuFlag_UDBA_REVAL | AuFlag_WARN_PERM \
  15982. + | AuFlag_COO_NONE | AuDefFlag_DIROPQ)
  15983. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
  15984. +#define AuDefFlags (AuDefFlags_COMM | AuFlag_PLINK)
  15985. +#else
  15986. +#define AuDefFlags AuDefFlags_COMM
  15987. +#endif
  15988. +
  15989. +/* ---------------------------------------------------------------------- */
  15990. +
  15991. +/* flags for aufs_read_lock()/di_read_lock() */
  15992. +#define AUFS_D_WLOCK 1
  15993. +#define AUFS_I_RLOCK 2
  15994. +#define AUFS_I_WLOCK 4
  15995. +
  15996. +/* ---------------------------------------------------------------------- */
  15997. +
  15998. +/* super.c */
  15999. +int au_show_brs(struct seq_file *seq, struct super_block *sb);
  16000. +
  16001. +/* xino.c */
  16002. +struct file *xino_create(struct super_block *sb, char *fname, int silent,
  16003. + struct dentry *parent);
  16004. +ino_t xino_new_ino(struct super_block *sb);
  16005. +int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino);
  16006. +int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  16007. + struct xino *xino);
  16008. +int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  16009. + struct xino *xino);
  16010. +int xino_init(struct super_block *sb, aufs_bindex_t bindex,
  16011. + struct file *base_file, int do_test);
  16012. +struct opt_xino;
  16013. +int xino_set(struct super_block *sb, struct opt_xino *xino, int remount);
  16014. +int xino_clr(struct super_block *sb);
  16015. +struct file *xino_def(struct super_block *sb);
  16016. +
  16017. +/* sbinfo.c */
  16018. +struct aufs_sbinfo *stosi(struct super_block *sb);
  16019. +aufs_bindex_t sbend(struct super_block *sb);
  16020. +struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex);
  16021. +int au_sigen(struct super_block *sb);
  16022. +int au_sigen_inc(struct super_block *sb);
  16023. +int find_bindex(struct super_block *sb, struct aufs_branch *br);
  16024. +
  16025. +void aufs_read_lock(struct dentry *dentry, int flags);
  16026. +void aufs_read_unlock(struct dentry *dentry, int flags);
  16027. +void aufs_write_lock(struct dentry *dentry);
  16028. +void aufs_write_unlock(struct dentry *dentry);
  16029. +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
  16030. +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
  16031. +
  16032. +aufs_bindex_t new_br_id(struct super_block *sb);
  16033. +
  16034. +/* ---------------------------------------------------------------------- */
  16035. +
  16036. +static inline const char *au_sbtype(struct super_block *sb)
  16037. +{
  16038. + return sb->s_type->name;
  16039. +}
  16040. +
  16041. +static inline int au_is_aufs(struct super_block *sb)
  16042. +{
  16043. + return !strcmp(au_sbtype(sb), AUFS_FSTYPE);
  16044. +}
  16045. +
  16046. +static inline int au_is_nfs(struct super_block *sb)
  16047. +{
  16048. +#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
  16049. + return !strcmp(au_sbtype(sb), "nfs");
  16050. +#else
  16051. + return 0;
  16052. +#endif
  16053. +}
  16054. +
  16055. +static inline int au_is_remote(struct super_block *sb)
  16056. +{
  16057. + return au_is_nfs(sb);
  16058. +}
  16059. +
  16060. +#ifdef CONFIG_AUFS_EXPORT
  16061. +static inline void au_init_export_op(struct super_block *sb)
  16062. +{
  16063. + extern struct export_operations aufs_export_op;
  16064. + sb->s_export_op = &aufs_export_op;
  16065. +}
  16066. +
  16067. +static inline int au_is_nfsd(struct task_struct *tsk)
  16068. +{
  16069. + return (!tsk->mm && !strcmp(tsk->comm, "nfsd"));
  16070. +}
  16071. +
  16072. +static inline void au_nfsd_lockdep_off(void)
  16073. +{
  16074. + /* braces are added to stop a warning */
  16075. + if (au_is_nfsd(current)) {
  16076. + lockdep_off();
  16077. + }
  16078. +}
  16079. +
  16080. +static inline void au_nfsd_lockdep_on(void)
  16081. +{
  16082. + /* braces are added to stop a warning */
  16083. + if (au_is_nfsd(current)) {
  16084. + lockdep_on();
  16085. + }
  16086. +}
  16087. +#else
  16088. +static inline int au_is_nfsd(struct task_struct *tsk)
  16089. +{
  16090. + return 0;
  16091. +}
  16092. +static inline void au_init_export_op(struct super_block *sb)
  16093. +{
  16094. + /* nothing */
  16095. +}
  16096. +#define au_nfsd_lockdep_off() /* */
  16097. +#define au_nfsd_lockdep_on() /* */
  16098. +#endif /* CONFIG_AUFS_EXPORT */
  16099. +
  16100. +static inline void init_lvma(struct aufs_sbinfo *sbinfo)
  16101. +{
  16102. +#ifdef CONFIG_AUFS_ROBR
  16103. + spin_lock_init(&sbinfo->si_lvma_lock);
  16104. + INIT_LIST_HEAD(&sbinfo->si_lvma);
  16105. +#else
  16106. + /* nothing */
  16107. +#endif
  16108. +}
  16109. +
  16110. +/* limited support before 2.6.18 */
  16111. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  16112. +static inline void au_mntget(struct super_block *sb)
  16113. +{
  16114. + mntget(stosi(sb)->si_mnt);
  16115. +}
  16116. +
  16117. +static inline void au_mntput(struct super_block *sb)
  16118. +{
  16119. + mntput(stosi(sb)->si_mnt);
  16120. +}
  16121. +#else
  16122. +static inline void au_mntget(struct super_block *sb)
  16123. +{
  16124. + /* empty */
  16125. +}
  16126. +
  16127. +static inline void au_mntput(struct super_block *sb)
  16128. +{
  16129. + /* empty */
  16130. +}
  16131. +#endif
  16132. +
  16133. +/* ---------------------------------------------------------------------- */
  16134. +
  16135. +static inline void au_flag_set(struct super_block *sb, unsigned int flag)
  16136. +{
  16137. + //SiMustWriteLock(sb);
  16138. + stosi(sb)->si_flags |= flag;
  16139. +}
  16140. +
  16141. +static inline void au_flag_clr(struct super_block *sb, unsigned int flag)
  16142. +{
  16143. + //SiMustWriteLock(sb);
  16144. + stosi(sb)->si_flags &= ~flag;
  16145. +}
  16146. +
  16147. +static inline
  16148. +unsigned int au_flag_test(struct super_block *sb, unsigned int flag)
  16149. +{
  16150. + //SiMustAnyLock(sb);
  16151. + return stosi(sb)->si_flags & flag;
  16152. +}
  16153. +
  16154. +static inline unsigned int au_flag_test_udba(struct super_block *sb)
  16155. +{
  16156. + return au_flag_test(sb, AuMask_UDBA);
  16157. +}
  16158. +
  16159. +static inline unsigned int au_flag_test_coo(struct super_block *sb)
  16160. +{
  16161. + return au_flag_test(sb, AuMask_COO);
  16162. +}
  16163. +
  16164. +/* ---------------------------------------------------------------------- */
  16165. +
  16166. +/* lock superblock. mainly for entry point functions */
  16167. +/*
  16168. + * si_read_lock, si_write_lock,
  16169. + * si_read_unlock, si_write_unlock, si_downgrade_lock
  16170. + */
  16171. +SimpleRwsemFuncs(si, struct super_block *sb, stosi(sb)->si_rwsem);
  16172. +
  16173. +/* to debug easier, do not make them inlined functions */
  16174. +#define SiMustReadLock(sb) RwMustReadLock(&stosi(sb)->si_rwsem)
  16175. +#define SiMustWriteLock(sb) RwMustWriteLock(&stosi(sb)->si_rwsem)
  16176. +#define SiMustAnyLock(sb) RwMustAnyLock(&stosi(sb)->si_rwsem)
  16177. +
  16178. +#endif /* __KERNEL__ */
  16179. +#endif /* __AUFS_SUPER_H__ */
  16180. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/sysaufs.c linux-2.6.22.1/fs/aufs/sysaufs.c
  16181. --- linux-2.6.22.1.oorig/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
  16182. +++ linux-2.6.22.1/fs/aufs/sysaufs.c 2007-07-24 14:17:46.000000000 +0200
  16183. @@ -0,0 +1,620 @@
  16184. +/*
  16185. + * Copyright (C) 2007 Junjiro Okajima
  16186. + *
  16187. + * This program, aufs is free software; you can redistribute it and/or modify
  16188. + * it under the terms of the GNU General Public License as published by
  16189. + * the Free Software Foundation; either version 2 of the License, or
  16190. + * (at your option) any later version.
  16191. + *
  16192. + * This program is distributed in the hope that it will be useful,
  16193. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16194. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16195. + * GNU General Public License for more details.
  16196. + *
  16197. + * You should have received a copy of the GNU General Public License
  16198. + * along with this program; if not, write to the Free Software
  16199. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16200. + */
  16201. +
  16202. +/* $Id: sysaufs.c,v 1.6 2007/05/14 03:40:10 sfjro Exp $ */
  16203. +
  16204. +#include <linux/module.h>
  16205. +#include <linux/seq_file.h>
  16206. +#include <linux/sysfs.h>
  16207. +#include "aufs.h"
  16208. +
  16209. +/* ---------------------------------------------------------------------- */
  16210. +
  16211. +/* super_blocks list is not exported */
  16212. +static DEFINE_MUTEX(aufs_sbilist_mtx);
  16213. +static LIST_HEAD(aufs_sbilist);
  16214. +
  16215. +/* ---------------------------------------------------------------------- */
  16216. +
  16217. +typedef ssize_t (*rwfunc_t)(struct kobject *kobj, char *buf, loff_t offset,
  16218. + size_t sz, struct sysaufs_args *args);
  16219. +static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
  16220. + size_t sz, struct sysaufs_args *args);
  16221. +static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf, loff_t
  16222. + offset, size_t sz, struct sysaufs_args *args);
  16223. +
  16224. +#define GFunc(name, _index, func) \
  16225. +static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
  16226. +{ \
  16227. + struct sysaufs_args args = { \
  16228. + .index = (_index), \
  16229. + .mtx = &aufs_sbilist_mtx, \
  16230. + .sb = NULL \
  16231. + }; \
  16232. + return func(kobj, buf, offset, sz, &args); \
  16233. +}
  16234. +
  16235. +#define GFuncs(name, _index) \
  16236. + GFunc(read_##name, _index, sysaufs_read); \
  16237. + GFunc(write_##name, _index, sysaufs_free_write);
  16238. +
  16239. +static struct super_block *find_sb_locked(struct kobject *kobj)
  16240. +{
  16241. + struct super_block *sb;
  16242. + struct aufs_sbinfo *sbinfo;
  16243. +
  16244. + TraceEnter();
  16245. + MtxMustLock(&aufs_sbilist_mtx);
  16246. +
  16247. + sb = NULL;
  16248. + list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
  16249. + if (&au_subsys_to_kset(sbinfo->si_sysaufs.subsys).kobj != kobj)
  16250. + continue;
  16251. + sb = sbinfo->si_mnt->mnt_sb;
  16252. + si_read_lock(sb);
  16253. + break;
  16254. + }
  16255. + return sb;
  16256. +}
  16257. +
  16258. +static ssize_t sb_func(struct kobject *kobj, char *buf, loff_t offset,
  16259. + size_t sz, struct sysaufs_args *args, rwfunc_t func)
  16260. +{
  16261. + ssize_t err;
  16262. +
  16263. + err = -ENOENT;
  16264. + mutex_lock(&aufs_sbilist_mtx);
  16265. + args->sb = find_sb_locked(kobj);
  16266. + if (args->sb) {
  16267. + err = func(kobj, buf, offset, sz, args);
  16268. + si_read_unlock(args->sb);
  16269. + }
  16270. + mutex_unlock(&aufs_sbilist_mtx);
  16271. + return err;
  16272. +}
  16273. +
  16274. +#define SbFunc(name, _index, func) \
  16275. +static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
  16276. +{ \
  16277. + struct sysaufs_args args = { \
  16278. + .index = (_index), \
  16279. + .mtx = NULL \
  16280. + }; \
  16281. + return sb_func(kobj, buf, offset, sz, &args, func); \
  16282. +}
  16283. +
  16284. +#define SbFuncs(name, index) \
  16285. + SbFunc(read_##name, index, sysaufs_read); \
  16286. + SbFunc(write_##name, index, sysaufs_free_write)
  16287. +
  16288. +static decl_subsys(aufs, NULL, NULL);
  16289. +enum {Brs, Stat, Config, _Last};
  16290. +static struct sysaufs_entry g_array[_Last];
  16291. +GFuncs(brs, Brs);
  16292. +GFuncs(stat, Stat);
  16293. +GFuncs(config, Config);
  16294. +
  16295. +SbFuncs(xino, SysaufsSb_XINO);
  16296. +
  16297. +#define SetEntry(e, _name, init_size, _ops) \
  16298. + do { \
  16299. + (e)->attr.attr.name = #_name; \
  16300. + (e)->attr.attr.owner = THIS_MODULE; \
  16301. + (e)->attr.attr.mode = S_IRUGO | S_IWUSR; \
  16302. + (e)->attr.read = read_##_name; \
  16303. + (e)->attr.write = write_##_name; \
  16304. + (e)->allocated = init_size; \
  16305. + (e)->err = -1; \
  16306. + (e)->ops = _ops; \
  16307. + } while (0)
  16308. +
  16309. +#define Priv(e) (e)->attr.private
  16310. +#define Allocated(e) (e)->allocated
  16311. +#define Len(e) (e)->attr.size
  16312. +#define Name(e) attr_name((e)->attr)
  16313. +
  16314. +/* ---------------------------------------------------------------------- */
  16315. +
  16316. +static void free_entry(struct sysaufs_entry *e)
  16317. +{
  16318. + MtxMustLock(&aufs_sbilist_mtx);
  16319. + DEBUG_ON(!Priv(e));
  16320. +
  16321. + if (Allocated(e) > 0)
  16322. + kfree(Priv(e));
  16323. + else
  16324. + free_pages((unsigned long)Priv(e), -Allocated(e));
  16325. + Priv(e) = NULL;
  16326. + Len(e) = 0;
  16327. +}
  16328. +
  16329. +static void free_entries(void)
  16330. +{
  16331. + static int a[] = {Brs, -1};
  16332. + int *p = a;
  16333. +
  16334. + MtxMustLock(&aufs_sbilist_mtx);
  16335. +
  16336. + while (*p >= 0) {
  16337. + if (Priv(g_array + *p))
  16338. + free_entry(g_array + *p);
  16339. + p++;
  16340. + }
  16341. +}
  16342. +
  16343. +static int alloc_entry(struct sysaufs_entry *e)
  16344. +{
  16345. + MtxMustLock(&aufs_sbilist_mtx);
  16346. + DEBUG_ON(Priv(e));
  16347. + //Dbg("%d\n", Allocated(e));
  16348. +
  16349. + if (Allocated(e) > 0)
  16350. + Priv(e) = kmalloc(Allocated(e), GFP_KERNEL);
  16351. + else
  16352. + Priv(e) = (void*)__get_free_pages(GFP_KERNEL, -Allocated(e));
  16353. + if (Priv(e))
  16354. + return 0;
  16355. + return -ENOMEM;
  16356. +}
  16357. +
  16358. +/* ---------------------------------------------------------------------- */
  16359. +
  16360. +static void unreg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
  16361. + au_subsys_t *parent)
  16362. +{
  16363. + int i;
  16364. +
  16365. + TraceEnter();
  16366. +
  16367. + for (i = 0; i < n; i++, a++)
  16368. + if (!a->err) {
  16369. + sysfs_remove_bin_file
  16370. + (&au_subsys_to_kset(*subsys).kobj, &a->attr);
  16371. + if (Priv(a))
  16372. + free_entry(a);
  16373. + }
  16374. +
  16375. + subsystem_unregister(subsys);
  16376. + subsys_put(parent);
  16377. +}
  16378. +
  16379. +static int reg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
  16380. + au_subsys_t *parent)
  16381. +{
  16382. + int err, i;
  16383. +
  16384. + TraceEnter();
  16385. +
  16386. + subsys_get(parent);
  16387. + kobj_set_kset_s(&au_subsys_to_kset(*subsys), *parent);
  16388. + err = subsystem_register(subsys);
  16389. + if (unlikely(err))
  16390. + goto out;
  16391. +
  16392. + for (i = 0; !err && i < n; i++)
  16393. + err = a[i].err = sysfs_create_bin_file
  16394. + (&au_subsys_to_kset(*subsys).kobj, &a[i].attr);
  16395. + if (unlikely(err))
  16396. + unreg(subsys, a, n, parent);
  16397. +
  16398. + out:
  16399. + TraceErr(err);
  16400. + return err;
  16401. +}
  16402. +
  16403. +/* ---------------------------------------------------------------------- */
  16404. +
  16405. +#define SbSetEntry(index, name, init_size) \
  16406. + SetEntry(sa->array + index, name, init_size, au_si_ops);
  16407. +
  16408. +void sysaufs_add(struct aufs_sbinfo *sbinfo)
  16409. +{
  16410. + int err;
  16411. + struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
  16412. +
  16413. + TraceEnter();
  16414. +
  16415. + mutex_lock(&aufs_sbilist_mtx);
  16416. + list_add_tail(&sbinfo->si_list, &aufs_sbilist);
  16417. + free_entries();
  16418. +
  16419. + memset(sa, 0, sizeof(*sa));
  16420. + SbSetEntry(SysaufsSb_XINO, xino, 128);
  16421. + err = kobject_set_name(&au_subsys_to_kset(sa->subsys).kobj, "%p",
  16422. + sbinfo->si_mnt->mnt_sb);
  16423. + if (!err)
  16424. + err = reg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array),
  16425. + &aufs_subsys);
  16426. + if (unlikely(err))
  16427. + Warn("failed adding sysfs (%d)\n", err);
  16428. +
  16429. + mutex_unlock(&aufs_sbilist_mtx);
  16430. +}
  16431. +
  16432. +void sysaufs_del(struct aufs_sbinfo *sbinfo)
  16433. +{
  16434. + struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
  16435. +
  16436. + TraceEnter();
  16437. +
  16438. + mutex_lock(&aufs_sbilist_mtx);
  16439. + unreg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array), &aufs_subsys);
  16440. + list_del(&sbinfo->si_list);
  16441. + free_entries();
  16442. + mutex_unlock(&aufs_sbilist_mtx);
  16443. +}
  16444. +
  16445. +void sysaufs_notify_remount(void)
  16446. +{
  16447. + mutex_lock(&aufs_sbilist_mtx);
  16448. + free_entries();
  16449. + mutex_unlock(&aufs_sbilist_mtx);
  16450. +}
  16451. +
  16452. +/* ---------------------------------------------------------------------- */
  16453. +
  16454. +static int make_brs(struct seq_file *seq, struct sysaufs_args *args,
  16455. + int *do_size)
  16456. +{
  16457. + int err;
  16458. + struct aufs_sbinfo *sbinfo;
  16459. +
  16460. + TraceEnter();
  16461. + MtxMustLock(&aufs_sbilist_mtx);
  16462. + DEBUG_ON(args->index != Brs);
  16463. +
  16464. + err = 0;
  16465. + list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
  16466. + struct super_block *sb;
  16467. + struct dentry *root;
  16468. + struct vfsmount *mnt;
  16469. +
  16470. + sb = sbinfo->si_mnt->mnt_sb;
  16471. + root = sb->s_root;
  16472. + aufs_read_lock(root, !AUFS_I_RLOCK);
  16473. + mnt = sbinfo->si_mnt;
  16474. + err = seq_escape
  16475. + (seq, mnt->mnt_devname ? mnt->mnt_devname : "none",
  16476. + au_esc_chars);
  16477. + if (!err)
  16478. + err = seq_putc(seq, ' ');
  16479. + if (!err)
  16480. + err = seq_path(seq, mnt, root, au_esc_chars);
  16481. + if (err > 0)
  16482. + err = seq_printf(seq, " %p br:", sb);
  16483. + if (!err)
  16484. + err = au_show_brs(seq, sb);
  16485. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  16486. + if (!err)
  16487. + err = seq_putc(seq, '\n');
  16488. + else
  16489. + break;
  16490. + }
  16491. +
  16492. + TraceErr(err);
  16493. + return err;
  16494. +}
  16495. +
  16496. +static int make_config(struct seq_file *seq, struct sysaufs_args *args,
  16497. + int *do_size)
  16498. +{
  16499. + int err;
  16500. +
  16501. + TraceEnter();
  16502. + DEBUG_ON(args->index != Config);
  16503. +
  16504. +#ifdef CONFIG_AUFS
  16505. + err = seq_puts(seq, "CONFIG_AUFS=y\n");
  16506. +#else
  16507. + err = seq_puts(seq, "CONFIG_AUFS=m\n");
  16508. +#endif
  16509. +
  16510. +#define puts(m, v) \
  16511. + if (!err) err = seq_puts(seq, "CONFIG_AUFS_" #m "=" #v "\n")
  16512. +#define puts_bool(m) puts(m, y)
  16513. +#define puts_mod(m) puts(m, m)
  16514. +
  16515. +#ifdef CONFIG_AUFS_FAKE_DM
  16516. + puts_bool(FAKE_DM);
  16517. +#endif
  16518. +#ifdef CONFIG_AUFS_BRANCH_MAX_127
  16519. + puts_bool(BRANCH_MAX_127);
  16520. +#elif defined(CONFIG_AUFS_BRANCH_MAX_511)
  16521. + puts_bool(BRANCH_MAX_511);
  16522. +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
  16523. + puts_bool(BRANCH_MAX_1023);
  16524. +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
  16525. + puts_bool(BRANCH_MAX_32767);
  16526. +#endif
  16527. + puts_bool(SYSAUFS);
  16528. +#ifdef CONFIG_AUFS_HINOTIFY
  16529. + puts_bool(HINOTIFY);
  16530. +#endif
  16531. +#ifdef CONFIG_AUFS_EXPORT
  16532. + puts_bool(EXPORT);
  16533. +#endif
  16534. +#ifdef CONFIG_AUFS_ROBR
  16535. + puts_bool(ROBR);
  16536. +#endif
  16537. +#ifdef CONFIG_AUFS_DLGT
  16538. + puts_bool(DLGT);
  16539. +#endif
  16540. +#ifdef CONFIG_AUFS_LHASH_PATCH
  16541. + puts_bool(LHASH_PATCH);
  16542. +#endif
  16543. +#ifdef CONFIG_AUFS_KSIZE_PATCH
  16544. + puts_bool(KSIZE_PATCH);
  16545. +#endif
  16546. +#ifdef CONFIG_AUFS_DEBUG
  16547. + puts_bool(DEBUG);
  16548. +#endif
  16549. +#ifdef CONFIG_AUFS_COMPAT
  16550. + puts_bool(COMPAT);
  16551. +#endif
  16552. +
  16553. +#undef puts_bool
  16554. +#undef puts
  16555. +
  16556. + TraceErr(err);
  16557. + return err;
  16558. +}
  16559. +
  16560. +static int make_stat(struct seq_file *seq, struct sysaufs_args *args,
  16561. + int *do_size)
  16562. +{
  16563. + int err, i;
  16564. +
  16565. + TraceEnter();
  16566. + DEBUG_ON(args->index != Stat);
  16567. +
  16568. + *do_size = 0;
  16569. + err = seq_puts(seq, "wkq max_busy:");
  16570. + for (i = 0; !err && i < aufs_nwkq; i++)
  16571. + err = seq_printf(seq, " %u", au_wkq[i].max_busy);
  16572. + if (!err)
  16573. + err = seq_printf(seq, ", %u(generic)\n",
  16574. + au_wkq[aufs_nwkq].max_busy);
  16575. + TraceErr(err);
  16576. + return err;
  16577. +}
  16578. +
  16579. +/* ---------------------------------------------------------------------- */
  16580. +
  16581. +static int make(struct sysaufs_entry *e, struct sysaufs_args *args,
  16582. + int *do_size)
  16583. +
  16584. +{
  16585. + int err;
  16586. + struct seq_file *seq;
  16587. +
  16588. + TraceEnter();
  16589. + DEBUG_ON(Priv(e));
  16590. + MtxMustLock(&aufs_sbilist_mtx);
  16591. +
  16592. + err = -ENOMEM;
  16593. + seq = kzalloc(sizeof(*seq), GFP_KERNEL);
  16594. + if (unlikely(!seq))
  16595. + goto out;
  16596. +
  16597. + Len(e) = 0;
  16598. + while (1) {
  16599. + err = alloc_entry(e);
  16600. + if (unlikely(err))
  16601. + break;
  16602. +
  16603. + //mutex_init(&seq.lock);
  16604. + seq->buf = Priv(e);
  16605. + seq->count = 0;
  16606. + seq->size = Allocated(e);
  16607. + if (unlikely(Allocated(e) <= 0))
  16608. + seq->size = PAGE_SIZE << -Allocated(e);
  16609. +
  16610. + err = e->ops[args->index](seq, args, do_size);
  16611. + if (!err) {
  16612. + Len(e) = seq->count;
  16613. + break; /* success */
  16614. + }
  16615. +
  16616. + free_entry(e);
  16617. + if (Allocated(e) > 0) {
  16618. + Allocated(e) <<= 1;
  16619. + if (unlikely(Allocated(e) >= (int)PAGE_SIZE))
  16620. + Allocated(e) = 0;
  16621. + } else
  16622. + Allocated(e)--;
  16623. + //Dbg("%d\n", Allocated(e));
  16624. + }
  16625. + kfree(seq);
  16626. +
  16627. + out:
  16628. + TraceErr(err);
  16629. + return err;
  16630. +}
  16631. +
  16632. +/* why does sysfs pass my parent kobject? */
  16633. +static struct dentry *find_me(struct dentry *parent, struct sysaufs_entry *e)
  16634. +{
  16635. +#if 1
  16636. + struct dentry *dentry;
  16637. + const char *name = Name(e);
  16638. + const unsigned int len = strlen(name);
  16639. +
  16640. + //Dbg("%.*s\n", DLNPair(parent));
  16641. + spin_lock(&dcache_lock);
  16642. + list_for_each_entry(dentry, &parent->d_subdirs, D_CHILD) {
  16643. + //Dbg("%.*s\n", DLNPair(dentry));
  16644. + if (len == dentry->d_name.len
  16645. + && !strcmp(dentry->d_name.name, name)) {
  16646. + spin_unlock(&dcache_lock);
  16647. + return dentry;
  16648. + }
  16649. + }
  16650. + spin_unlock(&dcache_lock);
  16651. +#endif
  16652. + return NULL;
  16653. +}
  16654. +
  16655. +static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
  16656. + size_t sz, struct sysaufs_args *args)
  16657. +{
  16658. + ssize_t err;
  16659. + loff_t len;
  16660. + struct dentry *d;
  16661. + struct sysaufs_entry *e;
  16662. + int do_size;
  16663. +
  16664. + LKTRTrace("{%d, %p}, offset %Ld, sz %lu\n",
  16665. + args->index, args->sb, offset, (unsigned long)sz);
  16666. +
  16667. + if (unlikely(!sz))
  16668. + return 0;
  16669. +
  16670. + err = 0;
  16671. + d = NULL;
  16672. + e = g_array + args->index;
  16673. + if (args->sb)
  16674. + e = stosi(args->sb)->si_sysaufs.array + args->index;
  16675. +
  16676. + do_size = 1;
  16677. + if (args->mtx)
  16678. + mutex_lock(args->mtx);
  16679. + if (unlikely(!Priv(e))) {
  16680. + err = make(e, args, &do_size);
  16681. + DEBUG_ON(Len(e) > INT_MAX);
  16682. + if (do_size) {
  16683. + d = find_me(kobj->dentry, e);
  16684. + if (d)
  16685. + i_size_write(d->d_inode, Len(e));
  16686. + }
  16687. + }
  16688. +
  16689. + if (!err) {
  16690. + err = len = Len(e) - offset;
  16691. + LKTRTrace("%Ld\n", len);
  16692. + if (len > 0) {
  16693. + if (len > sz)
  16694. + err = sz;
  16695. + memcpy(buf, Priv(e) + offset, err);
  16696. + }
  16697. +
  16698. + if (!do_size)
  16699. + free_entry(e);
  16700. + }
  16701. + if (args->mtx)
  16702. + mutex_unlock(args->mtx);
  16703. +
  16704. + TraceErr(err);
  16705. + return err;
  16706. +}
  16707. +
  16708. +static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf,
  16709. + loff_t offset, size_t sz,
  16710. + struct sysaufs_args *args)
  16711. +{
  16712. + struct dentry *d;
  16713. + int allocated, len;
  16714. + struct sysaufs_entry *e;
  16715. +
  16716. + LKTRTrace("{%d, %p}\n", args->index, args->sb);
  16717. +
  16718. + e = g_array + args->index;
  16719. + if (args->sb)
  16720. + e = stosi(args->sb)->si_sysaufs.array + args->index;
  16721. +
  16722. + if (args->mtx)
  16723. + mutex_lock(args->mtx);
  16724. + if (Priv(e)) {
  16725. + allocated = Allocated(e);
  16726. + if (unlikely(allocated <= 0))
  16727. + allocated = PAGE_SIZE << -allocated;
  16728. + allocated >>= 1;
  16729. + len = Len(e);
  16730. +
  16731. + free_entry(e);
  16732. + if (unlikely(len <= allocated)) {
  16733. + if (Allocated(e) >= 0)
  16734. + Allocated(e) = allocated;
  16735. + else
  16736. + Allocated(e)++;
  16737. + }
  16738. +
  16739. + d = find_me(kobj->dentry, e);
  16740. + if (d && i_size_read(d->d_inode))
  16741. + i_size_write(d->d_inode, 0);
  16742. + }
  16743. + if (args->mtx)
  16744. + mutex_unlock(args->mtx);
  16745. +
  16746. + return sz;
  16747. +}
  16748. +
  16749. +static sysaufs_op g_ops[] = {
  16750. + [Brs] = make_brs,
  16751. + [Stat] = make_stat,
  16752. + [Config] = make_config
  16753. +};
  16754. +
  16755. +/* ---------------------------------------------------------------------- */
  16756. +
  16757. +#define GSetEntry(index, name, init_size) \
  16758. + SetEntry(g_array + index, name, init_size, g_ops)
  16759. +
  16760. +int __init sysaufs_init(void)
  16761. +{
  16762. + int err;
  16763. +
  16764. + GSetEntry(Brs, brs, 128);
  16765. + GSetEntry(Stat, stat, 32);
  16766. + GSetEntry(Config, config, 256);
  16767. + err = reg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
  16768. + TraceErr(err);
  16769. + return err;
  16770. +}
  16771. +
  16772. +void __exit sysaufs_fin(void)
  16773. +{
  16774. + mutex_lock(&aufs_sbilist_mtx);
  16775. + unreg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
  16776. + mutex_unlock(&aufs_sbilist_mtx);
  16777. +}
  16778. +
  16779. +/* ---------------------------------------------------------------------- */
  16780. +
  16781. +#ifdef DbgDlgt
  16782. +int is_branch(struct super_block *h_sb)
  16783. +{
  16784. + int found = 0;
  16785. + struct aufs_sbinfo *sbinfo;
  16786. +
  16787. + //Dbg("here\n");
  16788. + mutex_lock(&aufs_sbilist_mtx);
  16789. + list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
  16790. + aufs_bindex_t bindex, bend;
  16791. + struct super_block *sb;
  16792. +
  16793. + sb = sbinfo->si_mnt->mnt_sb;
  16794. + si_read_lock(sb);
  16795. + bend = sbend(sb);
  16796. + for (bindex = 0; !found && bindex <= bend; bindex++)
  16797. + found = (h_sb == sbr_sb(sb, bindex));
  16798. + si_read_unlock(sb);
  16799. + }
  16800. + mutex_unlock(&aufs_sbilist_mtx);
  16801. + return found;
  16802. +}
  16803. +#endif
  16804. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/sysaufs.h linux-2.6.22.1/fs/aufs/sysaufs.h
  16805. --- linux-2.6.22.1.oorig/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
  16806. +++ linux-2.6.22.1/fs/aufs/sysaufs.h 2007-07-24 14:17:46.000000000 +0200
  16807. @@ -0,0 +1,83 @@
  16808. +/*
  16809. + * Copyright (C) 2007 Junjiro Okajima
  16810. + *
  16811. + * This program, aufs is free software; you can redistribute it and/or modify
  16812. + * it under the terms of the GNU General Public License as published by
  16813. + * the Free Software Foundation; either version 2 of the License, or
  16814. + * (at your option) any later version.
  16815. + *
  16816. + * This program is distributed in the hope that it will be useful,
  16817. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16818. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16819. + * GNU General Public License for more details.
  16820. + *
  16821. + * You should have received a copy of the GNU General Public License
  16822. + * along with this program; if not, write to the Free Software
  16823. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16824. + */
  16825. +
  16826. +/* $Id: sysaufs.h,v 1.3 2007/05/14 06:27:18 sfjro Exp $ */
  16827. +
  16828. +#ifndef __SYSAUFS_H__
  16829. +#define __SYSAUFS_H__
  16830. +
  16831. +#ifdef __KERNEL__
  16832. +
  16833. +#include <linux/seq_file.h>
  16834. +#include <linux/sysfs.h>
  16835. +#include <linux/version.h>
  16836. +
  16837. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
  16838. +typedef struct kset au_subsys_t;
  16839. +#define au_subsys_to_kset(subsys) (subsys)
  16840. +#else
  16841. +typedef struct subsystem au_subsys_t;
  16842. +#define au_subsys_to_kset(subsys) ((subsys).kset)
  16843. +#endif
  16844. +
  16845. +/* ---------------------------------------------------------------------- */
  16846. +
  16847. +/* arguments for an entry under sysfs */
  16848. +struct sysaufs_args {
  16849. + int index;
  16850. + struct mutex *mtx;
  16851. + struct super_block *sb;
  16852. +};
  16853. +
  16854. +typedef int (*sysaufs_op)(struct seq_file *seq, struct sysaufs_args *args,
  16855. + int *do_size);
  16856. +
  16857. +/* an entry under sysfs */
  16858. +struct sysaufs_entry {
  16859. + struct bin_attribute attr;
  16860. + int allocated; /* zero minus means pages */
  16861. + int err;
  16862. + sysaufs_op *ops;
  16863. +};
  16864. +
  16865. +/* ---------------------------------------------------------------------- */
  16866. +
  16867. +struct aufs_sbinfo;
  16868. +#ifdef CONFIG_AUFS_SYSAUFS
  16869. +void sysaufs_add(struct aufs_sbinfo *sbinfo);
  16870. +void sysaufs_del(struct aufs_sbinfo *sbinfo);
  16871. +int __init sysaufs_init(void);
  16872. +void sysaufs_fin(void);
  16873. +void sysaufs_notify_remount(void);
  16874. +#else
  16875. +static inline void sysaufs_add(struct aufs_sbinfo *sbinfo)
  16876. +{
  16877. + /* nothing */
  16878. +}
  16879. +
  16880. +static inline void sysaufs_del(struct aufs_sbinfo *sbinfo)
  16881. +{
  16882. + /* nothing */
  16883. +}
  16884. +#define sysaufs_init() 0
  16885. +#define sysaufs_fin() /* */
  16886. +#define sysaufs_notify_remount() /* */
  16887. +#endif /* CONFIG_AUFS_SYSAUFS */
  16888. +
  16889. +#endif /* __KERNEL__ */
  16890. +#endif /* __SYSAUFS_H__ */
  16891. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/vdir.c linux-2.6.22.1/fs/aufs/vdir.c
  16892. --- linux-2.6.22.1.oorig/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
  16893. +++ linux-2.6.22.1/fs/aufs/vdir.c 2007-07-24 14:17:46.000000000 +0200
  16894. @@ -0,0 +1,802 @@
  16895. +/*
  16896. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  16897. + *
  16898. + * This program, aufs is free software; you can redistribute it and/or modify
  16899. + * it under the terms of the GNU General Public License as published by
  16900. + * the Free Software Foundation; either version 2 of the License, or
  16901. + * (at your option) any later version.
  16902. + *
  16903. + * This program is distributed in the hope that it will be useful,
  16904. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16905. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16906. + * GNU General Public License for more details.
  16907. + *
  16908. + * You should have received a copy of the GNU General Public License
  16909. + * along with this program; if not, write to the Free Software
  16910. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16911. + */
  16912. +
  16913. +/* $Id: vdir.c,v 1.22 2007/05/14 03:38:52 sfjro Exp $ */
  16914. +
  16915. +#include "aufs.h"
  16916. +
  16917. +static int calc_size(int namelen)
  16918. +{
  16919. + int sz;
  16920. +
  16921. + sz = sizeof(struct aufs_de) + namelen;
  16922. + if (sizeof(ino_t) == sizeof(long)) {
  16923. + const int mask = sizeof(ino_t) - 1;
  16924. + if (sz & mask) {
  16925. + sz += sizeof(ino_t);
  16926. + sz &= ~mask;
  16927. + }
  16928. + } else {
  16929. +#if 0 // remove
  16930. + BUG();
  16931. + // this block will be discarded by optimizer.
  16932. + int m;
  16933. + m = sz % sizeof(ino_t);
  16934. + if (m)
  16935. + sz += sizeof(ino_t) - m;
  16936. +#endif
  16937. + }
  16938. +
  16939. + DEBUG_ON(sz % sizeof(ino_t));
  16940. + return sz;
  16941. +}
  16942. +
  16943. +static int set_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
  16944. +{
  16945. + if (calc_size(0) <= deblk_end->p - p->p) {
  16946. + p->de->de_str.len = 0;
  16947. + //smp_mb();
  16948. + return 0;
  16949. + }
  16950. + return -1; // error
  16951. +}
  16952. +
  16953. +/* returns true or false */
  16954. +static int is_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
  16955. +{
  16956. + if (calc_size(0) <= deblk_end->p - p->p)
  16957. + return !p->de->de_str.len;
  16958. + return 1;
  16959. +}
  16960. +
  16961. +static aufs_deblk_t *last_deblk(struct aufs_vdir *vdir)
  16962. +{
  16963. + return vdir->vd_deblk[vdir->vd_nblk - 1];
  16964. +}
  16965. +
  16966. +void nhash_init(struct aufs_nhash *nhash)
  16967. +{
  16968. + int i;
  16969. + for (i = 0; i < AUFS_NHASH_SIZE; i++)
  16970. + INIT_HLIST_HEAD(nhash->heads + i);
  16971. +}
  16972. +
  16973. +struct aufs_nhash *nhash_new(gfp_t gfp)
  16974. +{
  16975. + struct aufs_nhash *nhash;
  16976. +
  16977. + nhash = kmalloc(sizeof(*nhash), gfp);
  16978. + if (nhash) {
  16979. + nhash_init(nhash);
  16980. + return nhash;
  16981. + }
  16982. + return ERR_PTR(-ENOMEM);
  16983. +}
  16984. +
  16985. +void nhash_del(struct aufs_nhash *nhash)
  16986. +{
  16987. + nhash_fin(nhash);
  16988. + kfree(nhash);
  16989. +}
  16990. +
  16991. +void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src)
  16992. +{
  16993. + int i;
  16994. +
  16995. + TraceEnter();
  16996. +
  16997. + //DbgWhlist(src);
  16998. + *dst = *src;
  16999. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17000. + struct hlist_head *h;
  17001. + h = dst->heads + i;
  17002. + if (h->first)
  17003. + h->first->pprev = &h->first;
  17004. + INIT_HLIST_HEAD(src->heads + i);
  17005. + }
  17006. + //DbgWhlist(src);
  17007. + //DbgWhlist(dst);
  17008. + //smp_mb();
  17009. +}
  17010. +
  17011. +/* ---------------------------------------------------------------------- */
  17012. +
  17013. +void nhash_fin(struct aufs_nhash *whlist)
  17014. +{
  17015. + int i;
  17016. + struct hlist_head *head;
  17017. + struct aufs_wh *tpos;
  17018. + struct hlist_node *pos, *n;
  17019. +
  17020. + TraceEnter();
  17021. +
  17022. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17023. + head = whlist->heads + i;
  17024. + hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
  17025. + //hlist_del(pos);
  17026. + kfree(tpos);
  17027. + }
  17028. + }
  17029. +}
  17030. +
  17031. +int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit)
  17032. +{
  17033. + int n, i;
  17034. + struct hlist_head *head;
  17035. + struct aufs_wh *tpos;
  17036. + struct hlist_node *pos;
  17037. +
  17038. + LKTRTrace("limit %d\n", limit);
  17039. + //return 1;
  17040. +
  17041. + n = 0;
  17042. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17043. + head = whlist->heads + i;
  17044. + hlist_for_each_entry(tpos, pos, head, wh_hash)
  17045. + if (tpos->wh_bindex == btgt && ++n > limit)
  17046. + return 1;
  17047. + }
  17048. + return 0;
  17049. +}
  17050. +
  17051. +/* returns found(true) or not */
  17052. +int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen)
  17053. +{
  17054. + struct hlist_head *head;
  17055. + struct aufs_wh *tpos;
  17056. + struct hlist_node *pos;
  17057. + struct aufs_destr *str;
  17058. +
  17059. + LKTRTrace("%.*s\n", namelen, name);
  17060. +
  17061. + head = whlist->heads + au_name_hash(name, namelen);
  17062. + hlist_for_each_entry(tpos, pos, head, wh_hash) {
  17063. + str = &tpos->wh_str;
  17064. + LKTRTrace("%.*s\n", str->len, str->name);
  17065. + if (str->len == namelen && !memcmp(str->name, name, namelen))
  17066. + return 1;
  17067. + }
  17068. + return 0;
  17069. +}
  17070. +
  17071. +int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
  17072. + aufs_bindex_t bindex)
  17073. +{
  17074. + int err;
  17075. + struct aufs_destr *str;
  17076. + struct aufs_wh *wh;
  17077. +
  17078. + LKTRTrace("%.*s\n", namelen, name);
  17079. +
  17080. + err = -ENOMEM;
  17081. + wh = kmalloc(sizeof(*wh) + namelen, GFP_KERNEL);
  17082. + if (unlikely(!wh))
  17083. + goto out;
  17084. + err = 0;
  17085. + wh->wh_bindex = bindex;
  17086. + str = &wh->wh_str;
  17087. + str->len = namelen;
  17088. + memcpy(str->name, name, namelen);
  17089. + hlist_add_head(&wh->wh_hash,
  17090. + whlist->heads + au_name_hash(name, namelen));
  17091. + //smp_mb();
  17092. +
  17093. + out:
  17094. + TraceErr(err);
  17095. + return err;
  17096. +}
  17097. +
  17098. +/* ---------------------------------------------------------------------- */
  17099. +
  17100. +void free_vdir(struct aufs_vdir *vdir)
  17101. +{
  17102. + aufs_deblk_t **deblk;
  17103. +
  17104. + TraceEnter();
  17105. +
  17106. + deblk = vdir->vd_deblk;
  17107. + while (vdir->vd_nblk--) {
  17108. + kfree(*deblk);
  17109. + deblk++;
  17110. + }
  17111. + kfree(vdir->vd_deblk);
  17112. + cache_free_vdir(vdir);
  17113. +}
  17114. +
  17115. +static int append_deblk(struct aufs_vdir *vdir)
  17116. +{
  17117. + int err, sz, i;
  17118. + aufs_deblk_t **o;
  17119. + union aufs_deblk_p p, deblk_end;
  17120. +
  17121. + TraceEnter();
  17122. +
  17123. + err = -ENOMEM;
  17124. + sz = sizeof(*o) * vdir->vd_nblk;
  17125. + o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_KERNEL);
  17126. + if (unlikely(!o))
  17127. + goto out;
  17128. + vdir->vd_deblk = o;
  17129. + p.deblk = kmalloc(sizeof(*p.deblk), GFP_KERNEL);
  17130. + if (p.deblk) {
  17131. + i = vdir->vd_nblk++;
  17132. + vdir->vd_deblk[i] = p.deblk;
  17133. + vdir->vd_last.i = i;
  17134. + vdir->vd_last.p.p = p.p;
  17135. + deblk_end.deblk = p.deblk + 1;
  17136. + err = set_deblk_end(&p, &deblk_end);
  17137. + DEBUG_ON(err);
  17138. + }
  17139. +
  17140. + out:
  17141. + TraceErr(err);
  17142. + return err;
  17143. +}
  17144. +
  17145. +static struct aufs_vdir *alloc_vdir(void)
  17146. +{
  17147. + struct aufs_vdir *vdir;
  17148. + int err;
  17149. +
  17150. + TraceEnter();
  17151. +
  17152. + err = -ENOMEM;
  17153. + vdir = cache_alloc_vdir();
  17154. + if (unlikely(!vdir))
  17155. + goto out;
  17156. + vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_KERNEL);
  17157. + if (unlikely(!vdir->vd_deblk))
  17158. + goto out_free;
  17159. +
  17160. + vdir->vd_nblk = 0;
  17161. + vdir->vd_version = 0;
  17162. + vdir->vd_jiffy = 0;
  17163. + err = append_deblk(vdir);
  17164. + if (!err)
  17165. + return vdir; /* success */
  17166. +
  17167. + kfree(vdir->vd_deblk);
  17168. +
  17169. + out_free:
  17170. + cache_free_vdir(vdir);
  17171. + out:
  17172. + vdir = ERR_PTR(err);
  17173. + TraceErrPtr(vdir);
  17174. + return vdir;
  17175. +}
  17176. +
  17177. +static int reinit_vdir(struct aufs_vdir *vdir)
  17178. +{
  17179. + int err;
  17180. + union aufs_deblk_p p, deblk_end;
  17181. +
  17182. + TraceEnter();
  17183. +
  17184. + while (vdir->vd_nblk > 1) {
  17185. + kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
  17186. + vdir->vd_deblk[vdir->vd_nblk - 1] = NULL;
  17187. + vdir->vd_nblk--;
  17188. + }
  17189. + p.deblk = vdir->vd_deblk[0];
  17190. + deblk_end.deblk = p.deblk + 1;
  17191. + err = set_deblk_end(&p, &deblk_end);
  17192. + DEBUG_ON(err);
  17193. + vdir->vd_version = 0;
  17194. + vdir->vd_jiffy = 0;
  17195. + vdir->vd_last.i = 0;
  17196. + vdir->vd_last.p.deblk = vdir->vd_deblk[0];
  17197. + //smp_mb();
  17198. + //DbgVdir(vdir);
  17199. + return err;
  17200. +}
  17201. +
  17202. +/* ---------------------------------------------------------------------- */
  17203. +
  17204. +static void free_dehlist(struct aufs_nhash *dehlist)
  17205. +{
  17206. + int i;
  17207. + struct hlist_head *head;
  17208. + struct aufs_dehstr *tpos;
  17209. + struct hlist_node *pos, *n;
  17210. +
  17211. + TraceEnter();
  17212. +
  17213. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17214. + head = dehlist->heads + i;
  17215. + hlist_for_each_entry_safe(tpos, pos, n, head, hash) {
  17216. + //hlist_del(pos);
  17217. + cache_free_dehstr(tpos);
  17218. + }
  17219. + }
  17220. +}
  17221. +
  17222. +/* returns found(true) or not */
  17223. +static int test_known(struct aufs_nhash *delist, char *name, int namelen)
  17224. +{
  17225. + struct hlist_head *head;
  17226. + struct aufs_dehstr *tpos;
  17227. + struct hlist_node *pos;
  17228. + struct aufs_destr *str;
  17229. +
  17230. + LKTRTrace("%.*s\n", namelen, name);
  17231. +
  17232. + head = delist->heads + au_name_hash(name, namelen);
  17233. + hlist_for_each_entry(tpos, pos, head, hash) {
  17234. + str = tpos->str;
  17235. + LKTRTrace("%.*s\n", str->len, str->name);
  17236. + if (str->len == namelen && !memcmp(str->name, name, namelen))
  17237. + return 1;
  17238. + }
  17239. + return 0;
  17240. +
  17241. +}
  17242. +
  17243. +static int append_de(struct aufs_vdir *vdir, char *name, int namelen, ino_t ino,
  17244. + unsigned int d_type, struct aufs_nhash *delist)
  17245. +{
  17246. + int err, sz;
  17247. + union aufs_deblk_p p, *room, deblk_end;
  17248. + struct aufs_dehstr *dehstr;
  17249. +
  17250. + LKTRTrace("%.*s %d, i%lu, dt%u\n", namelen, name, namelen, ino, d_type);
  17251. +
  17252. + p.deblk = last_deblk(vdir);
  17253. + deblk_end.deblk = p.deblk + 1;
  17254. + room = &vdir->vd_last.p;
  17255. + DEBUG_ON(room->p < p.p || deblk_end.p <= room->p
  17256. + || !is_deblk_end(room, &deblk_end));
  17257. +
  17258. + sz = calc_size(namelen);
  17259. + if (unlikely(sz > deblk_end.p - room->p)) {
  17260. + err = append_deblk(vdir);
  17261. + if (unlikely(err))
  17262. + goto out;
  17263. + p.deblk = last_deblk(vdir);
  17264. + deblk_end.deblk = p.deblk + 1;
  17265. + //smp_mb();
  17266. + DEBUG_ON(room->p != p.p);
  17267. + }
  17268. +
  17269. + err = -ENOMEM;
  17270. + dehstr = cache_alloc_dehstr();
  17271. + if (unlikely(!dehstr))
  17272. + goto out;
  17273. + dehstr->str = &room->de->de_str;
  17274. + hlist_add_head(&dehstr->hash,
  17275. + delist->heads + au_name_hash(name, namelen));
  17276. +
  17277. + room->de->de_ino = ino;
  17278. + room->de->de_type = d_type;
  17279. + room->de->de_str.len = namelen;
  17280. + memcpy(room->de->de_str.name, name, namelen);
  17281. +
  17282. + err = 0;
  17283. + room->p += sz;
  17284. + if (unlikely(set_deblk_end(room, &deblk_end)))
  17285. + err = append_deblk(vdir);
  17286. + //smp_mb();
  17287. +
  17288. + out:
  17289. + TraceErr(err);
  17290. + return err;
  17291. +}
  17292. +
  17293. +/* ---------------------------------------------------------------------- */
  17294. +
  17295. +struct fillvdir_arg {
  17296. + struct file *file;
  17297. + struct aufs_vdir *vdir;
  17298. + struct aufs_nhash *delist;
  17299. + struct aufs_nhash *whlist;
  17300. + aufs_bindex_t bindex;
  17301. + int err;
  17302. + int called;
  17303. +};
  17304. +
  17305. +static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset,
  17306. + filldir_ino_t h_ino, unsigned int d_type)
  17307. +{
  17308. + struct fillvdir_arg *arg = __arg;
  17309. + char *name = (void*)__name;
  17310. + aufs_bindex_t bindex, bend;
  17311. + struct xino xino;
  17312. + struct super_block *sb;
  17313. +
  17314. + LKTRTrace("%.*s, namelen %d, i%Lu, dt%u\n",
  17315. + namelen, name, namelen, (u64)h_ino, d_type);
  17316. +
  17317. + sb = arg->file->f_dentry->d_sb;
  17318. + bend = arg->bindex;
  17319. + arg->err = 0;
  17320. + arg->called++;
  17321. + //smp_mb();
  17322. + if (namelen <= AUFS_WH_PFX_LEN
  17323. + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
  17324. + for (bindex = 0; bindex < bend; bindex++)
  17325. + if (test_known(arg->delist + bindex, name, namelen)
  17326. + || test_known_wh(arg->whlist + bindex, name,
  17327. + namelen))
  17328. + goto out; /* already exists or whiteouted */
  17329. +
  17330. + arg->err = xino_read(sb, bend, h_ino, &xino);
  17331. + if (!arg->err && !xino.ino) {
  17332. + //struct inode *h_inode;
  17333. + xino.ino = xino_new_ino(sb);
  17334. + if (unlikely(!xino.ino))
  17335. + arg->err = -EIO;
  17336. +#if 0
  17337. + //xino.h_gen = AuXino_INVALID_HGEN;
  17338. + h_inode = ilookup(sbr_sb(sb, bend), h_ino);
  17339. + if (h_inode) {
  17340. + if (!is_bad_inode(h_inode)) {
  17341. + xino.h_gen = h_inode->i_generation;
  17342. + WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
  17343. + }
  17344. + iput(h_inode);
  17345. + }
  17346. +#endif
  17347. + arg->err = xino_write(sb, bend, h_ino, &xino);
  17348. + }
  17349. + if (!arg->err)
  17350. + arg->err = append_de(arg->vdir, name, namelen, xino.ino,
  17351. + d_type, arg->delist + bend);
  17352. + } else {
  17353. + name += AUFS_WH_PFX_LEN;
  17354. + namelen -= AUFS_WH_PFX_LEN;
  17355. + for (bindex = 0; bindex < bend; bindex++)
  17356. + if (test_known_wh(arg->whlist + bend, name, namelen))
  17357. + goto out; /* already whiteouted */
  17358. + arg->err = append_wh(arg->whlist + bend, name, namelen, bend);
  17359. + }
  17360. +
  17361. + out:
  17362. + if (!arg->err)
  17363. + arg->vdir->vd_jiffy = jiffies;
  17364. + //smp_mb();
  17365. + TraceErr(arg->err);
  17366. + return arg->err;
  17367. +}
  17368. +
  17369. +static int read_vdir(struct file *file, int may_read)
  17370. +{
  17371. + int err, do_read, dlgt;
  17372. + struct dentry *dentry;
  17373. + struct inode *inode;
  17374. + struct aufs_vdir *vdir, *allocated;
  17375. + unsigned long expire;
  17376. + struct fillvdir_arg arg;
  17377. + aufs_bindex_t bindex, bend, bstart;
  17378. + struct super_block *sb;
  17379. +
  17380. + dentry = file->f_dentry;
  17381. + LKTRTrace("%.*s, may %d\n", DLNPair(dentry), may_read);
  17382. + FiMustWriteLock(file);
  17383. + inode = dentry->d_inode;
  17384. + IMustLock(inode);
  17385. + IiMustWriteLock(inode);
  17386. + DEBUG_ON(!S_ISDIR(inode->i_mode));
  17387. +
  17388. + err = 0;
  17389. + allocated = NULL;
  17390. + do_read = 0;
  17391. + sb = inode->i_sb;
  17392. + expire = stosi(sb)->si_rdcache;
  17393. + vdir = ivdir(inode);
  17394. + if (!vdir) {
  17395. + DEBUG_ON(fvdir_cache(file));
  17396. + do_read = 1;
  17397. + vdir = alloc_vdir();
  17398. + err = PTR_ERR(vdir);
  17399. + if (IS_ERR(vdir))
  17400. + goto out;
  17401. + err = 0;
  17402. + allocated = vdir;
  17403. + } else if (may_read
  17404. + && (inode->i_version != vdir->vd_version
  17405. + || time_after(jiffies, vdir->vd_jiffy + expire))) {
  17406. + LKTRTrace("iver %lu, vdver %lu, exp %lu\n",
  17407. + inode->i_version, vdir->vd_version,
  17408. + vdir->vd_jiffy + expire);
  17409. + do_read = 1;
  17410. + err = reinit_vdir(vdir);
  17411. + if (unlikely(err))
  17412. + goto out;
  17413. + }
  17414. + //DbgVdir(vdir); goto out;
  17415. +
  17416. + if (!do_read)
  17417. + return 0; /* success */
  17418. +
  17419. + err = -ENOMEM;
  17420. + bend = fbend(file);
  17421. + arg.delist = kmalloc(sizeof(*arg.delist) * (bend + 1), GFP_KERNEL);
  17422. + if (unlikely(!arg.delist))
  17423. + goto out_vdir;
  17424. + arg.whlist = kmalloc(sizeof(*arg.whlist) * (bend + 1), GFP_KERNEL);
  17425. + if (unlikely(!arg.whlist))
  17426. + goto out_delist;
  17427. + err = 0;
  17428. + for (bindex = 0; bindex <= bend; bindex++) {
  17429. + nhash_init(arg.delist + bindex);
  17430. + nhash_init(arg.whlist + bindex);
  17431. + }
  17432. +
  17433. + dlgt = need_dlgt(sb);
  17434. + arg.file = file;
  17435. + arg.vdir = vdir;
  17436. + bstart = fbstart(file);
  17437. + for (bindex = bstart; !err && bindex <= bend; bindex++) {
  17438. + struct file *hf;
  17439. + struct inode *h_inode;
  17440. +
  17441. + hf = au_h_fptr_i(file, bindex);
  17442. + if (!hf)
  17443. + continue;
  17444. +
  17445. + h_inode = hf->f_dentry->d_inode;
  17446. + //hf->f_pos = 0;
  17447. + arg.bindex = bindex;
  17448. + do {
  17449. + arg.err = 0;
  17450. + arg.called = 0;
  17451. + //smp_mb();
  17452. + err = vfsub_readdir(hf, fillvdir, &arg, dlgt);
  17453. + if (err >= 0)
  17454. + err = arg.err;
  17455. + } while (!err && arg.called);
  17456. + }
  17457. +
  17458. + for (bindex = bstart; bindex <= bend; bindex++) {
  17459. + free_dehlist(arg.delist + bindex);
  17460. + nhash_fin(arg.whlist + bindex);
  17461. + }
  17462. + kfree(arg.whlist);
  17463. +
  17464. + out_delist:
  17465. + kfree(arg.delist);
  17466. + out_vdir:
  17467. + if (!err) {
  17468. + //file->f_pos = 0;
  17469. + vdir->vd_version = inode->i_version;
  17470. + vdir->vd_last.i = 0;
  17471. + vdir->vd_last.p.deblk = vdir->vd_deblk[0];
  17472. + if (allocated)
  17473. + set_ivdir(inode, allocated);
  17474. + } else if (allocated)
  17475. + free_vdir(allocated);
  17476. + //DbgVdir(vdir); goto out;
  17477. +
  17478. + out:
  17479. + TraceErr(err);
  17480. + return err;
  17481. +}
  17482. +
  17483. +static int copy_vdir(struct aufs_vdir *tgt, struct aufs_vdir *src)
  17484. +{
  17485. + int err, i, rerr, n;
  17486. +
  17487. + TraceEnter();
  17488. + DEBUG_ON(tgt->vd_nblk != 1);
  17489. + //DbgVdir(tgt);
  17490. +
  17491. + err = -ENOMEM;
  17492. + if (tgt->vd_nblk < src->vd_nblk) {
  17493. + aufs_deblk_t **p;
  17494. + p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk,
  17495. + sizeof(*p) * src->vd_nblk, GFP_KERNEL);
  17496. + if (unlikely(!p))
  17497. + goto out;
  17498. + tgt->vd_deblk = p;
  17499. + }
  17500. +
  17501. + n = tgt->vd_nblk = src->vd_nblk;
  17502. + memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AUFS_DEBLK_SIZE);
  17503. + //tgt->vd_last.i = 0;
  17504. + //tgt->vd_last.p.deblk = tgt->vd_deblk[0];
  17505. + tgt->vd_version = src->vd_version;
  17506. + tgt->vd_jiffy = src->vd_jiffy;
  17507. +
  17508. + for (i = 1; i < n; i++) {
  17509. + tgt->vd_deblk[i] = kmalloc(AUFS_DEBLK_SIZE, GFP_KERNEL);
  17510. + if (tgt->vd_deblk[i])
  17511. + memcpy(tgt->vd_deblk[i], src->vd_deblk[i],
  17512. + AUFS_DEBLK_SIZE);
  17513. + else
  17514. + goto out;
  17515. + }
  17516. + //smp_mb();
  17517. + //DbgVdir(tgt);
  17518. + return 0; /* success */
  17519. +
  17520. + out:
  17521. + rerr = reinit_vdir(tgt);
  17522. + BUG_ON(rerr);
  17523. + TraceErr(err);
  17524. + return err;
  17525. +}
  17526. +
  17527. +int au_init_vdir(struct file *file)
  17528. +{
  17529. + int err;
  17530. + struct dentry *dentry;
  17531. + struct inode *inode;
  17532. + struct aufs_vdir *vdir_cache, *allocated;
  17533. +
  17534. + dentry = file->f_dentry;
  17535. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  17536. + FiMustWriteLock(file);
  17537. + inode = dentry->d_inode;
  17538. + IiMustWriteLock(inode);
  17539. + DEBUG_ON(!S_ISDIR(inode->i_mode));
  17540. +
  17541. + err = read_vdir(file, !file->f_pos);
  17542. + if (unlikely(err))
  17543. + goto out;
  17544. + //DbgVdir(ivdir(inode)); goto out;
  17545. +
  17546. + allocated = NULL;
  17547. + vdir_cache = fvdir_cache(file);
  17548. + if (!vdir_cache) {
  17549. + vdir_cache = alloc_vdir();
  17550. + err = PTR_ERR(vdir_cache);
  17551. + if (IS_ERR(vdir_cache))
  17552. + goto out;
  17553. + allocated = vdir_cache;
  17554. + } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
  17555. + err = reinit_vdir(vdir_cache);
  17556. + if (unlikely(err))
  17557. + goto out;
  17558. + } else
  17559. + return 0; /* success */
  17560. + //err = 0; DbgVdir(vdir_cache); goto out;
  17561. +
  17562. + err = copy_vdir(vdir_cache, ivdir(inode));
  17563. + if (!err) {
  17564. + file->f_version = inode->i_version;
  17565. + if (allocated)
  17566. + set_fvdir_cache(file, allocated);
  17567. + } else if (allocated)
  17568. + free_vdir(allocated);
  17569. +
  17570. + out:
  17571. + TraceErr(err);
  17572. + return err;
  17573. +}
  17574. +
  17575. +static loff_t calc_offset(struct aufs_vdir *vdir)
  17576. +{
  17577. + loff_t offset;
  17578. + union aufs_deblk_p p;
  17579. +
  17580. + p.deblk = vdir->vd_deblk[vdir->vd_last.i];
  17581. + offset = vdir->vd_last.p.p - p.p;
  17582. + offset += sizeof(*p.deblk) * vdir->vd_last.i;
  17583. + return offset;
  17584. +}
  17585. +
  17586. +/* returns true or false */
  17587. +static int seek_vdir(struct file *file)
  17588. +{
  17589. + int valid, i, n;
  17590. + struct dentry *dentry;
  17591. + struct aufs_vdir *vdir_cache;
  17592. + loff_t offset;
  17593. + union aufs_deblk_p p, deblk_end;
  17594. +
  17595. + dentry = file->f_dentry;
  17596. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  17597. + vdir_cache = fvdir_cache(file);
  17598. + DEBUG_ON(!vdir_cache);
  17599. + //DbgVdir(vdir_cache);
  17600. +
  17601. + valid = 1;
  17602. + offset = calc_offset(vdir_cache);
  17603. + LKTRTrace("offset %Ld\n", offset);
  17604. + if (file->f_pos == offset)
  17605. + goto out;
  17606. +
  17607. + vdir_cache->vd_last.i = 0;
  17608. + vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
  17609. + if (!file->f_pos)
  17610. + goto out;
  17611. +
  17612. + valid = 0;
  17613. + i = file->f_pos / AUFS_DEBLK_SIZE;
  17614. + LKTRTrace("i %d\n", i);
  17615. + if (i >= vdir_cache->vd_nblk)
  17616. + goto out;
  17617. +
  17618. + n = vdir_cache->vd_nblk;
  17619. + //DbgVdir(vdir_cache);
  17620. + for (; i < n; i++) {
  17621. + p.deblk = vdir_cache->vd_deblk[i];
  17622. + deblk_end.deblk = p.deblk + 1;
  17623. + offset = i * AUFS_DEBLK_SIZE;
  17624. + while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
  17625. + int l;
  17626. + l = calc_size(p.de->de_str.len);
  17627. + offset += l;
  17628. + p.p += l;
  17629. + }
  17630. + if (!is_deblk_end(&p, &deblk_end)) {
  17631. + valid = 1;
  17632. + vdir_cache->vd_last.i = i;
  17633. + vdir_cache->vd_last.p = p;
  17634. + break;
  17635. + }
  17636. + }
  17637. +
  17638. + out:
  17639. + //smp_mb();
  17640. + //DbgVdir(vdir_cache);
  17641. + TraceErr(!valid);
  17642. + return valid;
  17643. +}
  17644. +
  17645. +int au_fill_de(struct file *file, void *dirent, filldir_t filldir)
  17646. +{
  17647. + int err, l;
  17648. + struct dentry *dentry;
  17649. + struct aufs_vdir *vdir_cache;
  17650. + struct aufs_de *de;
  17651. + union aufs_deblk_p deblk_end;
  17652. +
  17653. + dentry = file->f_dentry;
  17654. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  17655. + vdir_cache = fvdir_cache(file);
  17656. + DEBUG_ON(!vdir_cache);
  17657. + //DbgVdir(vdir_cache);
  17658. +
  17659. + if (!seek_vdir(file))
  17660. + return 0;
  17661. +
  17662. + while (1) {
  17663. + deblk_end.deblk
  17664. + = vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1;
  17665. + while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
  17666. + de = vdir_cache->vd_last.p.de;
  17667. + LKTRTrace("%.*s, off%Ld, i%lu, dt%d\n",
  17668. + de->de_str.len, de->de_str.name,
  17669. + file->f_pos, de->de_ino, de->de_type);
  17670. + err = filldir(dirent, de->de_str.name, de->de_str.len,
  17671. + file->f_pos, de->de_ino, de->de_type);
  17672. + if (unlikely(err)) {
  17673. + TraceErr(err);
  17674. + //return err;
  17675. + //todo: ignore the error caused by udba.
  17676. + return 0;
  17677. + }
  17678. +
  17679. + l = calc_size(de->de_str.len);
  17680. + vdir_cache->vd_last.p.p += l;
  17681. + file->f_pos += l;
  17682. + }
  17683. + if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) {
  17684. + vdir_cache->vd_last.i++;
  17685. + vdir_cache->vd_last.p.deblk
  17686. + = vdir_cache->vd_deblk[vdir_cache->vd_last.i];
  17687. + file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk)
  17688. + * vdir_cache->vd_last.i;
  17689. + continue;
  17690. + }
  17691. + break;
  17692. + }
  17693. +
  17694. + //smp_mb();
  17695. + return 0;
  17696. +}
  17697. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/vfsub.c linux-2.6.22.1/fs/aufs/vfsub.c
  17698. --- linux-2.6.22.1.oorig/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
  17699. +++ linux-2.6.22.1/fs/aufs/vfsub.c 2007-07-24 14:17:46.000000000 +0200
  17700. @@ -0,0 +1,665 @@
  17701. +/*
  17702. + * Copyright (C) 2007 Junjiro Okajima
  17703. + *
  17704. + * This program, aufs is free software; you can redistribute it and/or modify
  17705. + * it under the terms of the GNU General Public License as published by
  17706. + * the Free Software Foundation; either version 2 of the License, or
  17707. + * (at your option) any later version.
  17708. + *
  17709. + * This program is distributed in the hope that it will be useful,
  17710. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17711. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17712. + * GNU General Public License for more details.
  17713. + *
  17714. + * You should have received a copy of the GNU General Public License
  17715. + * along with this program; if not, write to the Free Software
  17716. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17717. + */
  17718. +
  17719. +/* $Id: vfsub.c,v 1.5 2007/04/23 00:55:06 sfjro Exp $ */
  17720. +// I'm going to slightly mad
  17721. +
  17722. +#include "aufs.h"
  17723. +
  17724. +/* ---------------------------------------------------------------------- */
  17725. +
  17726. +#ifdef CONFIG_AUFS_DLGT
  17727. +struct permission_args {
  17728. + int *errp;
  17729. + struct inode *inode;
  17730. + int mask;
  17731. + struct nameidata *nd;
  17732. +};
  17733. +
  17734. +static void call_permission(void *args)
  17735. +{
  17736. + struct permission_args *a = args;
  17737. + *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
  17738. +}
  17739. +
  17740. +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
  17741. + int dlgt)
  17742. +{
  17743. + if (!dlgt)
  17744. + return do_vfsub_permission(inode, mask, nd);
  17745. + else {
  17746. + int err;
  17747. + struct permission_args args = {
  17748. + .errp = &err,
  17749. + .inode = inode,
  17750. + .mask = mask,
  17751. + .nd = nd
  17752. + };
  17753. + au_wkq_wait(call_permission, &args, /*dlgt*/1);
  17754. + return err;
  17755. + }
  17756. +}
  17757. +
  17758. +/* ---------------------------------------------------------------------- */
  17759. +
  17760. +struct create_args {
  17761. + int *errp;
  17762. + struct inode *dir;
  17763. + struct dentry *dentry;
  17764. + int mode;
  17765. + struct nameidata *nd;
  17766. +};
  17767. +
  17768. +static void call_create(void *args)
  17769. +{
  17770. + struct create_args *a = args;
  17771. + *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
  17772. +}
  17773. +
  17774. +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  17775. + struct nameidata *nd, int dlgt)
  17776. +{
  17777. + if (!dlgt)
  17778. + return do_vfsub_create(dir, dentry, mode, nd);
  17779. + else {
  17780. + int err;
  17781. + struct create_args args = {
  17782. + .errp = &err,
  17783. + .dir = dir,
  17784. + .dentry = dentry,
  17785. + .mode = mode,
  17786. + .nd = nd
  17787. + };
  17788. + au_wkq_wait(call_create, &args, /*dlgt*/1);
  17789. + return err;
  17790. + }
  17791. +}
  17792. +
  17793. +struct symlink_args {
  17794. + int *errp;
  17795. + struct inode *dir;
  17796. + struct dentry *dentry;
  17797. + const char *symname;
  17798. + int mode;
  17799. +};
  17800. +
  17801. +static void call_symlink(void *args)
  17802. +{
  17803. + struct symlink_args *a = args;
  17804. + *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
  17805. +}
  17806. +
  17807. +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
  17808. + int mode, int dlgt)
  17809. +{
  17810. + if (!dlgt)
  17811. + return do_vfsub_symlink(dir, dentry, symname, mode);
  17812. + else {
  17813. + int err;
  17814. + struct symlink_args args = {
  17815. + .errp = &err,
  17816. + .dir = dir,
  17817. + .dentry = dentry,
  17818. + .symname = symname,
  17819. + .mode = mode
  17820. + };
  17821. + au_wkq_wait(call_symlink, &args, /*dlgt*/1);
  17822. + return err;
  17823. + }
  17824. +}
  17825. +
  17826. +struct mknod_args {
  17827. + int *errp;
  17828. + struct inode *dir;
  17829. + struct dentry *dentry;
  17830. + int mode;
  17831. + dev_t dev;
  17832. +};
  17833. +
  17834. +static void call_mknod(void *args)
  17835. +{
  17836. + struct mknod_args *a = args;
  17837. + *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
  17838. +}
  17839. +
  17840. +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
  17841. + int dlgt)
  17842. +{
  17843. + if (!dlgt)
  17844. + return do_vfsub_mknod(dir, dentry, mode, dev);
  17845. + else {
  17846. + int err;
  17847. + struct mknod_args args = {
  17848. + .errp = &err,
  17849. + .dir = dir,
  17850. + .dentry = dentry,
  17851. + .mode = mode,
  17852. + .dev = dev
  17853. + };
  17854. + au_wkq_wait(call_mknod, &args, /*dlgt*/1);
  17855. + return err;
  17856. + }
  17857. +}
  17858. +
  17859. +struct mkdir_args {
  17860. + int *errp;
  17861. + struct inode *dir;
  17862. + struct dentry *dentry;
  17863. + int mode;
  17864. +};
  17865. +
  17866. +static void call_mkdir(void *args)
  17867. +{
  17868. + struct mkdir_args *a = args;
  17869. + *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
  17870. +}
  17871. +
  17872. +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt)
  17873. +{
  17874. + if (!dlgt)
  17875. + return do_vfsub_mkdir(dir, dentry, mode);
  17876. + else {
  17877. + int err;
  17878. + struct mkdir_args args = {
  17879. + .errp = &err,
  17880. + .dir = dir,
  17881. + .dentry = dentry,
  17882. + .mode = mode
  17883. + };
  17884. + au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
  17885. + return err;
  17886. + }
  17887. +}
  17888. +
  17889. +/* ---------------------------------------------------------------------- */
  17890. +
  17891. +struct link_args {
  17892. + int *errp;
  17893. + struct inode *dir;
  17894. + struct dentry *src_dentry, *dentry;
  17895. +};
  17896. +
  17897. +static void call_link(void *args)
  17898. +{
  17899. + struct link_args *a = args;
  17900. + *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
  17901. +}
  17902. +
  17903. +int vfsub_link(struct dentry *src_dentry, struct inode *dir,
  17904. + struct dentry *dentry, int dlgt)
  17905. +{
  17906. + if (!dlgt)
  17907. + return do_vfsub_link(src_dentry, dir, dentry);
  17908. + else {
  17909. + int err;
  17910. + struct link_args args = {
  17911. + .errp = &err,
  17912. + .src_dentry = src_dentry,
  17913. + .dir = dir,
  17914. + .dentry = dentry
  17915. + };
  17916. + au_wkq_wait(call_link, &args, /*dlgt*/1);
  17917. + return err;
  17918. + }
  17919. +}
  17920. +
  17921. +struct rename_args {
  17922. + int *errp;
  17923. + struct inode *src_dir, *dir;
  17924. + struct dentry *src_dentry, *dentry;
  17925. +};
  17926. +
  17927. +static void call_rename(void *args)
  17928. +{
  17929. + struct rename_args *a = args;
  17930. + *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
  17931. + a->dentry);
  17932. +}
  17933. +
  17934. +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  17935. + struct inode *dir, struct dentry *dentry, int dlgt)
  17936. +{
  17937. + if (!dlgt)
  17938. + return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
  17939. + else {
  17940. + int err;
  17941. + struct rename_args args = {
  17942. + .errp = &err,
  17943. + .src_dir = src_dir,
  17944. + .src_dentry = src_dentry,
  17945. + .dir = dir,
  17946. + .dentry = dentry
  17947. + };
  17948. + au_wkq_wait(call_rename, &args, /*dlgt*/1);
  17949. + return err;
  17950. + }
  17951. +}
  17952. +
  17953. +struct rmdir_args {
  17954. + int *errp;
  17955. + struct inode *dir;
  17956. + struct dentry *dentry;
  17957. +};
  17958. +
  17959. +static void call_rmdir(void *args)
  17960. +{
  17961. + struct rmdir_args *a = args;
  17962. + *a->errp = do_vfsub_rmdir(a->dir, a->dentry);
  17963. +}
  17964. +
  17965. +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
  17966. +{
  17967. + if (!dlgt)
  17968. + return do_vfsub_rmdir(dir, dentry);
  17969. + else {
  17970. + int err;
  17971. + struct rmdir_args args = {
  17972. + .errp = &err,
  17973. + .dir = dir,
  17974. + .dentry = dentry
  17975. + };
  17976. + au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
  17977. + return err;
  17978. + }
  17979. +}
  17980. +
  17981. +/* ---------------------------------------------------------------------- */
  17982. +
  17983. +struct read_args {
  17984. + ssize_t *errp;
  17985. + struct file *file;
  17986. + union {
  17987. + void *kbuf;
  17988. + char __user *ubuf;
  17989. + };
  17990. + size_t count;
  17991. + loff_t *ppos;
  17992. +};
  17993. +
  17994. +static void call_read_k(void *args)
  17995. +{
  17996. + struct read_args *a = args;
  17997. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  17998. + DLNPair(a->file->f_dentry), (unsigned long)a->count,
  17999. + *a->ppos);
  18000. + *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
  18001. +}
  18002. +
  18003. +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18004. + loff_t *ppos, int dlgt)
  18005. +{
  18006. + if (!dlgt)
  18007. + return do_vfsub_read_u(file, ubuf, count, ppos);
  18008. + else {
  18009. + ssize_t err, read;
  18010. + struct read_args args = {
  18011. + .errp = &err,
  18012. + .file = file,
  18013. + .count = count,
  18014. + .ppos = ppos
  18015. + };
  18016. +
  18017. + if (unlikely(!count))
  18018. + return 0;
  18019. +
  18020. + /*
  18021. + * workaround an application bug.
  18022. + * generally, read(2) or write(2) may return the value shorter
  18023. + * than requested. But many applications don't support it,
  18024. + * for example bash.
  18025. + */
  18026. + err = -ENOMEM;
  18027. + if (args.count > PAGE_SIZE)
  18028. + args.count = PAGE_SIZE;
  18029. + args.kbuf = kmalloc(args.count, GFP_KERNEL);
  18030. + if (unlikely(!args.kbuf))
  18031. + goto out;
  18032. +
  18033. + read = 0;
  18034. + do {
  18035. + au_wkq_wait(call_read_k, &args, /*dlgt*/1);
  18036. + if (unlikely(err > 0
  18037. + && copy_to_user(ubuf, args.kbuf, err))) {
  18038. + err = -EFAULT;
  18039. + goto out_free;
  18040. + } else if (!err)
  18041. + break;
  18042. + else if (unlikely(err < 0))
  18043. + goto out_free;
  18044. + count -= err;
  18045. + /* do not read too much because of file i/o pointer */
  18046. + if (unlikely(count < args.count))
  18047. + args.count = count;
  18048. + ubuf += err;
  18049. + read += err;
  18050. + } while (count);
  18051. + smp_mb();
  18052. + err = read;
  18053. +
  18054. + out_free:
  18055. + kfree(args.kbuf);
  18056. + out:
  18057. + return err;
  18058. + }
  18059. +}
  18060. +
  18061. +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18062. + int dlgt)
  18063. +{
  18064. + if (!dlgt)
  18065. + return do_vfsub_read_k(file, kbuf, count, ppos);
  18066. + else {
  18067. + ssize_t err;
  18068. + struct read_args args = {
  18069. + .errp = &err,
  18070. + .file = file,
  18071. + .count = count,
  18072. + .ppos = ppos
  18073. + };
  18074. + args.kbuf = kbuf;
  18075. + au_wkq_wait(call_read_k, &args, /*dlgt*/1);
  18076. + return err;
  18077. + }
  18078. +}
  18079. +
  18080. +struct write_args {
  18081. + ssize_t *errp;
  18082. + struct file *file;
  18083. + union {
  18084. + void *kbuf;
  18085. + const char __user *ubuf;
  18086. + };
  18087. + void *buf;
  18088. + size_t count;
  18089. + loff_t *ppos;
  18090. +};
  18091. +
  18092. +static void call_write_k(void *args)
  18093. +{
  18094. + struct write_args *a = args;
  18095. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  18096. + DLNPair(a->file->f_dentry), (unsigned long)a->count,
  18097. + *a->ppos);
  18098. + *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
  18099. +}
  18100. +
  18101. +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
  18102. + loff_t *ppos, int dlgt)
  18103. +{
  18104. + if (!dlgt)
  18105. + return do_vfsub_write_u(file, ubuf, count, ppos);
  18106. + else {
  18107. + ssize_t err, written;
  18108. + struct write_args args = {
  18109. + .errp = &err,
  18110. + .file = file,
  18111. + .count = count,
  18112. + .ppos = ppos
  18113. + };
  18114. +
  18115. + if (unlikely(!count))
  18116. + return 0;
  18117. +
  18118. + /*
  18119. + * workaround an application bug.
  18120. + * generally, read(2) or write(2) may return the value shorter
  18121. + * than requested. But many applications don't support it,
  18122. + * for example bash.
  18123. + */
  18124. + err = -ENOMEM;
  18125. + if (args.count > PAGE_SIZE)
  18126. + args.count = PAGE_SIZE;
  18127. + args.kbuf = kmalloc(args.count, GFP_KERNEL);
  18128. + if (unlikely(!args.kbuf))
  18129. + goto out;
  18130. +
  18131. + written = 0;
  18132. + do {
  18133. + if (unlikely(copy_from_user(args.kbuf, ubuf, args.count))) {
  18134. + err = -EFAULT;
  18135. + goto out_free;
  18136. + }
  18137. +
  18138. + au_wkq_wait(call_write_k, &args, /*dlgt*/1);
  18139. + if (err > 0) {
  18140. + count -= err;
  18141. + if (count < args.count)
  18142. + args.count = count;
  18143. + ubuf += err;
  18144. + written += err;
  18145. + } else if (!err)
  18146. + break;
  18147. + else if (unlikely(err < 0))
  18148. + goto out_free;
  18149. + } while (count);
  18150. + err = written;
  18151. +
  18152. + out_free:
  18153. + kfree(args.kbuf);
  18154. + out:
  18155. + return err;
  18156. + }
  18157. +}
  18158. +
  18159. +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18160. + int dlgt)
  18161. +{
  18162. + if (!dlgt)
  18163. + return do_vfsub_write_k(file, kbuf, count, ppos);
  18164. + else {
  18165. + ssize_t err;
  18166. + struct write_args args = {
  18167. + .errp = &err,
  18168. + .file = file,
  18169. + .count = count,
  18170. + .ppos = ppos
  18171. + };
  18172. + args.kbuf = kbuf;
  18173. + au_wkq_wait(call_write_k, &args, /*dlgt*/1);
  18174. + return err;
  18175. + }
  18176. +}
  18177. +
  18178. +struct readdir_args {
  18179. + int *errp;
  18180. + struct file *file;
  18181. + filldir_t filldir;
  18182. + void *arg;
  18183. +};
  18184. +
  18185. +static void call_readdir(void *args)
  18186. +{
  18187. + struct readdir_args *a = args;
  18188. + *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
  18189. +}
  18190. +
  18191. +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
  18192. +{
  18193. + if (!dlgt)
  18194. + return do_vfsub_readdir(file, filldir, arg);
  18195. + else {
  18196. + int err;
  18197. + struct readdir_args args = {
  18198. + .errp = &err,
  18199. + .file = file,
  18200. + .filldir = filldir,
  18201. + .arg = arg
  18202. + };
  18203. + au_wkq_wait(call_readdir, &args, /*dlgt*/1);
  18204. + return err;
  18205. + }
  18206. +}
  18207. +#endif /* CONFIG_AUFS_DLGT */
  18208. +
  18209. +/* ---------------------------------------------------------------------- */
  18210. +
  18211. +struct notify_change_args {
  18212. + int *errp;
  18213. + struct dentry *h_dentry;
  18214. + struct iattr *ia;
  18215. +};
  18216. +
  18217. +static void call_notify_change(void *args)
  18218. +{
  18219. + struct notify_change_args *a = args;
  18220. + struct inode *h_inode;
  18221. +
  18222. + LKTRTrace("%.*s, ia_valid 0x%x\n",
  18223. + DLNPair(a->h_dentry), a->ia->ia_valid);
  18224. + h_inode = a->h_dentry->d_inode;
  18225. + IMustLock(h_inode);
  18226. +
  18227. + *a->errp = -EPERM;
  18228. + if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
  18229. + lockdep_off();
  18230. + *a->errp = notify_change(a->h_dentry, a->ia);
  18231. + lockdep_on();
  18232. + }
  18233. + TraceErr(*a->errp);
  18234. +}
  18235. +
  18236. +int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt)
  18237. +{
  18238. + int err;
  18239. + struct notify_change_args args = {
  18240. + .errp = &err,
  18241. + .h_dentry = dentry,
  18242. + .ia = ia
  18243. + };
  18244. +
  18245. +#ifndef CONFIG_AUFS_DLGT
  18246. + call_notify_change(&args);
  18247. +#else
  18248. + if (!dlgt)
  18249. + call_notify_change(&args);
  18250. + else
  18251. + au_wkq_wait(call_notify_change, &args, /*dlgt*/1);
  18252. +#endif
  18253. +
  18254. + TraceErr(err);
  18255. + return err;
  18256. +}
  18257. +
  18258. +/* ---------------------------------------------------------------------- */
  18259. +
  18260. +struct unlink_args {
  18261. + int *errp;
  18262. + struct inode *dir;
  18263. + struct dentry *dentry;
  18264. +};
  18265. +
  18266. +static void call_unlink(void *args)
  18267. +{
  18268. + struct unlink_args *a = args;
  18269. + struct inode *h_inode;
  18270. + const int stop_sillyrename = (au_is_nfs(a->dentry->d_sb)
  18271. + && atomic_read(&a->dentry->d_count) == 1);
  18272. +
  18273. + LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
  18274. + DLNPair(a->dentry), stop_sillyrename,
  18275. + atomic_read(&a->dentry->d_count));
  18276. + IMustLock(a->dir);
  18277. +
  18278. + if (!stop_sillyrename)
  18279. + dget(a->dentry);
  18280. + h_inode = a->dentry->d_inode;
  18281. + if (h_inode)
  18282. + atomic_inc(&h_inode->i_count);
  18283. +#if 0 // partial testing
  18284. + {
  18285. + struct qstr *name = &a->dentry->d_name;
  18286. + if (name->len == sizeof(AUFS_XINO_FNAME) - 1
  18287. + && !strncmp(name->name, AUFS_XINO_FNAME, name->len)) {
  18288. + lockdep_off();
  18289. + *a->errp = vfs_unlink(a->dir, a->dentry);
  18290. + lockdep_on();
  18291. + } else
  18292. + err = -1;
  18293. + }
  18294. +#else
  18295. + // vfs_unlink() locks inode
  18296. + lockdep_off();
  18297. + *a->errp = vfs_unlink(a->dir, a->dentry);
  18298. + lockdep_on();
  18299. +#endif
  18300. +
  18301. + if (!stop_sillyrename)
  18302. + dput(a->dentry);
  18303. + if (h_inode)
  18304. + iput(h_inode);
  18305. +
  18306. + TraceErr(*a->errp);
  18307. +}
  18308. +
  18309. +/*
  18310. + * @dir: must be locked.
  18311. + * @dentry: target dentry.
  18312. + */
  18313. +int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt)
  18314. +{
  18315. + int err;
  18316. + struct unlink_args args = {
  18317. + .errp = &err,
  18318. + .dir = dir,
  18319. + .dentry = dentry
  18320. + };
  18321. +
  18322. +#ifndef CONFIG_AUFS_DLGT
  18323. + call_unlink(&args);
  18324. +#else
  18325. + if (!dlgt)
  18326. + call_unlink(&args);
  18327. + else
  18328. + au_wkq_wait(call_unlink, &args, /*dlgt*/1);
  18329. +#endif
  18330. + return err;
  18331. +}
  18332. +
  18333. +/* ---------------------------------------------------------------------- */
  18334. +
  18335. +struct statfs_args {
  18336. + int *errp;
  18337. + void *arg;
  18338. + struct kstatfs *buf;
  18339. +};
  18340. +
  18341. +static void call_statfs(void *args)
  18342. +{
  18343. + struct statfs_args *a = args;
  18344. + *a->errp = vfs_statfs(a->arg, a->buf);
  18345. +}
  18346. +
  18347. +int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
  18348. +{
  18349. + int err;
  18350. + struct statfs_args args = {
  18351. + .errp = &err,
  18352. + .arg = arg,
  18353. + .buf = buf
  18354. + };
  18355. +
  18356. +#ifndef CONFIG_AUFS_DLGT
  18357. + call_statfs(&args);
  18358. +#else
  18359. + if (!dlgt)
  18360. + call_statfs(&args);
  18361. + else
  18362. + au_wkq_wait(call_statfs, &args, /*dlgt*/1);
  18363. +#endif
  18364. + return err;
  18365. +}
  18366. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/vfsub.h linux-2.6.22.1/fs/aufs/vfsub.h
  18367. --- linux-2.6.22.1.oorig/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
  18368. +++ linux-2.6.22.1/fs/aufs/vfsub.h 2007-07-24 14:17:46.000000000 +0200
  18369. @@ -0,0 +1,427 @@
  18370. +/*
  18371. + * Copyright (C) 2007 Junjiro Okajima
  18372. + *
  18373. + * This program, aufs is free software; you can redistribute it and/or modify
  18374. + * it under the terms of the GNU General Public License as published by
  18375. + * the Free Software Foundation; either version 2 of the License, or
  18376. + * (at your option) any later version.
  18377. + *
  18378. + * This program is distributed in the hope that it will be useful,
  18379. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18380. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18381. + * GNU General Public License for more details.
  18382. + *
  18383. + * You should have received a copy of the GNU General Public License
  18384. + * along with this program; if not, write to the Free Software
  18385. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18386. + */
  18387. +
  18388. +/* $Id: vfsub.h,v 1.8 2007/05/14 03:39:10 sfjro Exp $ */
  18389. +
  18390. +#ifndef __AUFS_VFSUB_H__
  18391. +#define __AUFS_VFSUB_H__
  18392. +
  18393. +#ifdef __KERNEL__
  18394. +
  18395. +#include <linux/fs.h>
  18396. +#include <asm/uaccess.h>
  18397. +#include "wkq.h"
  18398. +
  18399. +/* ---------------------------------------------------------------------- */
  18400. +
  18401. +/* simple abstractions, for future use */
  18402. +static inline
  18403. +int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)
  18404. +{
  18405. + LKTRTrace("i%lu, mask 0x%x, nd %p\n", inode->i_ino, mask, nd);
  18406. +#if 0
  18407. +#else
  18408. + return permission(inode, mask, nd);
  18409. +#endif
  18410. +}
  18411. +
  18412. +static inline
  18413. +struct file *vfsub_filp_open(const char *path, int oflags, int mode)
  18414. +{
  18415. + struct file *err;
  18416. +
  18417. + LKTRTrace("%s\n", path);
  18418. +
  18419. + lockdep_off();
  18420. + err = filp_open(path, oflags, mode);
  18421. + lockdep_on();
  18422. + return err;
  18423. +}
  18424. +
  18425. +static inline
  18426. +int vfsub_path_lookup(const char *name, unsigned int flags,
  18427. + struct nameidata *nd)
  18428. +{
  18429. + int err;
  18430. +
  18431. + LKTRTrace("%s\n", name);
  18432. +
  18433. + //lockdep_off();
  18434. + err = path_lookup(name, flags, nd);
  18435. + //lockdep_on();
  18436. + return err;
  18437. +}
  18438. +
  18439. +/* ---------------------------------------------------------------------- */
  18440. +
  18441. +static inline
  18442. +int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  18443. + struct nameidata *nd)
  18444. +{
  18445. + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
  18446. +#if 0
  18447. +#else
  18448. + return vfs_create(dir, dentry, mode, nd);
  18449. +#endif
  18450. +}
  18451. +
  18452. +static inline
  18453. +int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
  18454. + const char *symname, int mode)
  18455. +{
  18456. + LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
  18457. + dir->i_ino, DLNPair(dentry), symname, mode);
  18458. +#if 0
  18459. +#else
  18460. + return vfs_symlink(dir, dentry, symname, mode);
  18461. +#endif
  18462. +}
  18463. +
  18464. +static inline
  18465. +int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
  18466. + dev_t dev)
  18467. +{
  18468. + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
  18469. +#if 0
  18470. +#else
  18471. + return vfs_mknod(dir, dentry, mode, dev);
  18472. +#endif
  18473. +}
  18474. +
  18475. +static inline
  18476. +int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
  18477. + struct dentry *dentry)
  18478. +{
  18479. + int err;
  18480. +
  18481. + LKTRTrace("%.*s, i%lu, %.*s\n",
  18482. + DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
  18483. +
  18484. + lockdep_off();
  18485. +#if 0
  18486. +#else
  18487. + err = vfs_link(src_dentry, dir, dentry);
  18488. +#endif
  18489. + lockdep_on();
  18490. + return err;
  18491. +}
  18492. +
  18493. +static inline
  18494. +int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  18495. + struct inode *dir, struct dentry *dentry)
  18496. +{
  18497. + int err;
  18498. +
  18499. + LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
  18500. + src_dir->i_ino, DLNPair(src_dentry),
  18501. + dir->i_ino, DLNPair(dentry));
  18502. +
  18503. + lockdep_off();
  18504. +#if 0
  18505. +#else
  18506. + err = vfs_rename(src_dir, src_dentry, dir, dentry);
  18507. +#endif
  18508. + lockdep_on();
  18509. + return err;
  18510. +}
  18511. +
  18512. +static inline
  18513. +int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  18514. +{
  18515. + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
  18516. +#if 0
  18517. +#else
  18518. + return vfs_mkdir(dir, dentry, mode);
  18519. +#endif
  18520. +}
  18521. +
  18522. +static inline int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
  18523. +{
  18524. + int err;
  18525. +
  18526. + LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  18527. +
  18528. + lockdep_off();
  18529. +#if 0
  18530. +#else
  18531. + err = vfs_rmdir(dir, dentry);
  18532. +#endif
  18533. + lockdep_on();
  18534. + return err;
  18535. +}
  18536. +
  18537. +/* ---------------------------------------------------------------------- */
  18538. +
  18539. +static inline
  18540. +ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18541. + loff_t *ppos)
  18542. +{
  18543. + ssize_t err;
  18544. +
  18545. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  18546. + DLNPair(file->f_dentry), (unsigned long)count, *ppos);
  18547. +
  18548. + /* nfs uses some locks */
  18549. + lockdep_off();
  18550. +#if 0
  18551. +#else
  18552. + err = vfs_read(file, ubuf, count, ppos);
  18553. +#endif
  18554. + lockdep_on();
  18555. + return err;
  18556. +}
  18557. +
  18558. +// kernel_read() ??
  18559. +static inline
  18560. +ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
  18561. + loff_t *ppos)
  18562. +{
  18563. + ssize_t err;
  18564. + mm_segment_t oldfs;
  18565. +
  18566. + oldfs = get_fs();
  18567. + set_fs(KERNEL_DS);
  18568. + err = do_vfsub_read_u(file, (char __user*)kbuf, count, ppos);
  18569. + set_fs(oldfs);
  18570. + return err;
  18571. +}
  18572. +
  18573. +static inline
  18574. +ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
  18575. + size_t count, loff_t *ppos)
  18576. +{
  18577. + ssize_t err;
  18578. +
  18579. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  18580. + DLNPair(file->f_dentry), (unsigned long)count, *ppos);
  18581. +
  18582. + lockdep_off();
  18583. +#if 0
  18584. +#else
  18585. + err = vfs_write(file, ubuf, count, ppos);
  18586. +#endif
  18587. + lockdep_on();
  18588. + return err;
  18589. +}
  18590. +
  18591. +static inline
  18592. +ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
  18593. + loff_t *ppos)
  18594. +{
  18595. + ssize_t err;
  18596. + mm_segment_t oldfs;
  18597. +
  18598. + oldfs = get_fs();
  18599. + set_fs(KERNEL_DS);
  18600. + err = do_vfsub_write_u(file, (const char __user*)kbuf, count, ppos);
  18601. + set_fs(oldfs);
  18602. + return err;
  18603. +}
  18604. +
  18605. +static inline
  18606. +int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
  18607. +{
  18608. + int err;
  18609. +
  18610. + LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
  18611. +
  18612. + lockdep_off();
  18613. +#if 0
  18614. +#else
  18615. + err = vfs_readdir(file, filldir, arg);
  18616. +#endif
  18617. + lockdep_on();
  18618. + return err;
  18619. +}
  18620. +
  18621. +/* ---------------------------------------------------------------------- */
  18622. +
  18623. +static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
  18624. +{
  18625. + loff_t err;
  18626. +
  18627. + LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
  18628. +
  18629. + lockdep_off();
  18630. +#if 0
  18631. +#else
  18632. + err = vfs_llseek(file, offset, origin);
  18633. +#endif
  18634. + lockdep_on();
  18635. + return err;
  18636. +}
  18637. +
  18638. +/* ---------------------------------------------------------------------- */
  18639. +
  18640. +#ifdef CONFIG_AUFS_DLGT
  18641. +static inline int need_dlgt(struct super_block *sb)
  18642. +{
  18643. + return (au_flag_test(sb, AuFlag_DLGT) && !is_au_wkq(current));
  18644. +}
  18645. +
  18646. +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
  18647. + int dlgt);
  18648. +
  18649. +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  18650. + struct nameidata *nd, int dlgt);
  18651. +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
  18652. + int mode, int dlgt);
  18653. +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
  18654. + int dlgt);
  18655. +int vfsub_link(struct dentry *src_dentry, struct inode *dir,
  18656. + struct dentry *dentry, int dlgt);
  18657. +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  18658. + struct inode *dir, struct dentry *dentry, int dlgt);
  18659. +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt);
  18660. +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt);
  18661. +
  18662. +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18663. + loff_t *ppos, int dlgt);
  18664. +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18665. + int dlgt);
  18666. +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
  18667. + loff_t *ppos, int dlgt);
  18668. +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18669. + int dlgt);
  18670. +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt);
  18671. +
  18672. +#else
  18673. +
  18674. +static inline int need_dlgt(struct super_block *sb)
  18675. +{
  18676. + return 0;
  18677. +}
  18678. +
  18679. +static inline
  18680. +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
  18681. + int dlgt)
  18682. +{
  18683. + return do_vfsub_permission(inode, mask, nd);
  18684. +}
  18685. +
  18686. +static inline
  18687. +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  18688. + struct nameidata *nd, int dlgt)
  18689. +{
  18690. + return do_vfsub_create(dir, dentry, mode, nd);
  18691. +}
  18692. +
  18693. +static inline
  18694. +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
  18695. + int mode, int dlgt)
  18696. +{
  18697. + return do_vfsub_symlink(dir, dentry, symname, mode);
  18698. +}
  18699. +
  18700. +static inline
  18701. +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
  18702. + int dlgt)
  18703. +{
  18704. + return do_vfsub_mknod(dir, dentry, mode, dev);
  18705. +}
  18706. +
  18707. +static inline
  18708. +int vfsub_link(struct dentry *src_dentry, struct inode *dir,
  18709. + struct dentry *dentry, int dlgt)
  18710. +{
  18711. + return do_vfsub_link(src_dentry, dir, dentry);
  18712. +}
  18713. +
  18714. +static inline
  18715. +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  18716. + struct inode *dir, struct dentry *dentry, int dlgt)
  18717. +{
  18718. + return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
  18719. +}
  18720. +
  18721. +static inline
  18722. +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
  18723. + int dlgt)
  18724. +{
  18725. + return do_vfsub_mkdir(dir, dentry, mode);
  18726. +}
  18727. +
  18728. +static inline
  18729. +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
  18730. +{
  18731. + return do_vfsub_rmdir(dir, dentry);
  18732. +}
  18733. +
  18734. +static inline
  18735. +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18736. + loff_t *ppos, int dlgt)
  18737. +{
  18738. + return do_vfsub_read_u(file, ubuf, count, ppos);
  18739. +}
  18740. +
  18741. +static inline
  18742. +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18743. + int dlgt)
  18744. +{
  18745. + return do_vfsub_read_k(file, kbuf, count, ppos);
  18746. +}
  18747. +
  18748. +static inline
  18749. +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
  18750. + loff_t *ppos, int dlgt)
  18751. +{
  18752. + return do_vfsub_write_u(file, ubuf, count, ppos);
  18753. +}
  18754. +
  18755. +static inline
  18756. +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18757. + int dlgt)
  18758. +{
  18759. + return do_vfsub_write_k(file, kbuf, count, ppos);
  18760. +}
  18761. +
  18762. +static inline
  18763. +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
  18764. +{
  18765. + return do_vfsub_readdir(file, filldir, arg);
  18766. +}
  18767. +#endif /* CONFIG_AUFS_DLGT */
  18768. +
  18769. +/* ---------------------------------------------------------------------- */
  18770. +
  18771. +static inline
  18772. +struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2)
  18773. +{
  18774. + struct dentry *d;
  18775. +
  18776. + lockdep_off();
  18777. + d = lock_rename(d1, d2);
  18778. + lockdep_on();
  18779. + return d;
  18780. +}
  18781. +
  18782. +static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2)
  18783. +{
  18784. + lockdep_off();
  18785. + unlock_rename(d1, d2);
  18786. + lockdep_on();
  18787. +}
  18788. +
  18789. +/* ---------------------------------------------------------------------- */
  18790. +
  18791. +int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt);
  18792. +int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt);
  18793. +int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt);
  18794. +
  18795. +#endif /* __KERNEL__ */
  18796. +#endif /* __AUFS_VFSUB_H__ */
  18797. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/whout.c linux-2.6.22.1/fs/aufs/whout.c
  18798. --- linux-2.6.22.1.oorig/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
  18799. +++ linux-2.6.22.1/fs/aufs/whout.c 2007-07-24 14:17:46.000000000 +0200
  18800. @@ -0,0 +1,933 @@
  18801. +/*
  18802. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  18803. + *
  18804. + * This program, aufs is free software; you can redistribute it and/or modify
  18805. + * it under the terms of the GNU General Public License as published by
  18806. + * the Free Software Foundation; either version 2 of the License, or
  18807. + * (at your option) any later version.
  18808. + *
  18809. + * This program is distributed in the hope that it will be useful,
  18810. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18811. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18812. + * GNU General Public License for more details.
  18813. + *
  18814. + * You should have received a copy of the GNU General Public License
  18815. + * along with this program; if not, write to the Free Software
  18816. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18817. + */
  18818. +
  18819. +/* $Id: whout.c,v 1.14 2007/05/14 03:40:40 sfjro Exp $ */
  18820. +
  18821. +#include <linux/fs.h>
  18822. +#include <linux/namei.h>
  18823. +#include <linux/random.h>
  18824. +#include <linux/security.h>
  18825. +#include "aufs.h"
  18826. +
  18827. +#define WH_MASK S_IRUGO
  18828. +
  18829. +/* If a directory contains this file, then it is opaque. We start with the
  18830. + * .wh. flag so that it is blocked by lookup.
  18831. + */
  18832. +static struct qstr diropq_name = {
  18833. + .name = AUFS_WH_DIROPQ,
  18834. + .len = sizeof(AUFS_WH_DIROPQ) - 1
  18835. +};
  18836. +
  18837. +/*
  18838. + * generate whiteout name, which is NOT terminated by NULL.
  18839. + * @name: original d_name.name
  18840. + * @len: original d_name.len
  18841. + * @wh: whiteout qstr
  18842. + * returns zero when succeeds, otherwise error.
  18843. + * succeeded value as wh->name should be freed by au_free_whname().
  18844. + */
  18845. +int au_alloc_whname(const char *name, int len, struct qstr *wh)
  18846. +{
  18847. + char *p;
  18848. +
  18849. + DEBUG_ON(!name || !len || !wh);
  18850. +
  18851. + if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
  18852. + return -ENAMETOOLONG;
  18853. +
  18854. + wh->len = len + AUFS_WH_PFX_LEN;
  18855. + wh->name = p = kmalloc(wh->len, GFP_KERNEL);
  18856. + //if (LktrCond) {kfree(p); wh->name = p = NULL;}
  18857. + if (p) {
  18858. + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
  18859. + memcpy(p + AUFS_WH_PFX_LEN, name, len);
  18860. + //smp_mb();
  18861. + return 0;
  18862. + }
  18863. + return -ENOMEM;
  18864. +}
  18865. +
  18866. +void au_free_whname(struct qstr *wh)
  18867. +{
  18868. + DEBUG_ON(!wh || !wh->name);
  18869. + kfree(wh->name);
  18870. +#ifdef CONFIG_AUFS_DEBUG
  18871. + wh->name = NULL;
  18872. +#endif
  18873. +}
  18874. +
  18875. +/* ---------------------------------------------------------------------- */
  18876. +
  18877. +/*
  18878. + * test if the @wh_name exists under @hidden_parent.
  18879. + * @try_sio specifies the necessary of super-io.
  18880. + */
  18881. +int is_wh(struct dentry *hidden_parent, struct qstr *wh_name, int try_sio,
  18882. + struct lkup_args *lkup)
  18883. +{
  18884. + int err;
  18885. + struct dentry *wh_dentry;
  18886. + struct inode *hidden_dir;
  18887. +
  18888. + LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n", DLNPair(hidden_parent),
  18889. + wh_name->len, wh_name->name, lkup->nfsmnt, lkup->dlgt);
  18890. + hidden_dir = hidden_parent->d_inode;
  18891. + DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
  18892. + IMustLock(hidden_dir);
  18893. +
  18894. + if (!try_sio)
  18895. + wh_dentry = lkup_one(wh_name->name, hidden_parent,
  18896. + wh_name->len, lkup);
  18897. + else
  18898. + wh_dentry = sio_lkup_one(wh_name->name, hidden_parent,
  18899. + wh_name->len, lkup);
  18900. + //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
  18901. + err = PTR_ERR(wh_dentry);
  18902. + if (IS_ERR(wh_dentry))
  18903. + goto out;
  18904. +
  18905. + err = 0;
  18906. + if (!wh_dentry->d_inode)
  18907. + goto out_wh; /* success */
  18908. +
  18909. + err = 1;
  18910. + if (S_ISREG(wh_dentry->d_inode->i_mode))
  18911. + goto out_wh; /* success */
  18912. +
  18913. + err = -EIO;
  18914. + IOErr("%.*s Invalid whiteout entry type 0%o.\n",
  18915. + DLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
  18916. +
  18917. + out_wh:
  18918. + dput(wh_dentry);
  18919. + out:
  18920. + TraceErr(err);
  18921. + return err;
  18922. +}
  18923. +
  18924. +/*
  18925. + * test if the @hidden_dentry sets opaque or not.
  18926. + */
  18927. +int is_diropq(struct dentry *hidden_dentry, struct lkup_args *lkup)
  18928. +{
  18929. + int err;
  18930. + struct inode *hidden_dir;
  18931. +
  18932. + LKTRTrace("dentry %.*s\n", DLNPair(hidden_dentry));
  18933. + hidden_dir = hidden_dentry->d_inode;
  18934. + DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
  18935. + IMustLock(hidden_dir);
  18936. +
  18937. + err = is_wh(hidden_dentry, &diropq_name, /*try_sio*/1, lkup);
  18938. + TraceErr(err);
  18939. + return err;
  18940. +}
  18941. +
  18942. +/*
  18943. + * returns a negative dentry whose name is unique and temporary.
  18944. + */
  18945. +struct dentry *lkup_whtmp(struct dentry *hidden_parent, struct qstr *prefix,
  18946. + struct lkup_args *lkup)
  18947. +{
  18948. +#define HEX_LEN 4
  18949. + struct dentry *dentry;
  18950. + int len, i;
  18951. + char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
  18952. + + HEX_LEN + 1], *name, *p;
  18953. + static unsigned char cnt;
  18954. +
  18955. + LKTRTrace("hp %.*s, prefix %.*s\n",
  18956. + DLNPair(hidden_parent), prefix->len, prefix->name);
  18957. + DEBUG_ON(!hidden_parent->d_inode);
  18958. + IMustLock(hidden_parent->d_inode);
  18959. +
  18960. + name = defname;
  18961. + len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
  18962. + if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
  18963. + dentry = ERR_PTR(-ENAMETOOLONG);
  18964. + if (unlikely(len >= PATH_MAX))
  18965. + goto out;
  18966. + dentry = ERR_PTR(-ENOMEM);
  18967. + name = kmalloc(len + 1, GFP_KERNEL);
  18968. + //if (LktrCond) {kfree(name); name = NULL;}
  18969. + if (unlikely(!name))
  18970. + goto out;
  18971. + }
  18972. +
  18973. + // doubly whiteout-ed
  18974. + memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
  18975. + p = name + AUFS_WH_PFX_LEN * 2;
  18976. + memcpy(p, prefix->name, prefix->len);
  18977. + p += prefix->len;
  18978. + *p++ = '.';
  18979. + DEBUG_ON(name + len + 1 - p <= HEX_LEN);
  18980. +
  18981. + for (i = 0; i < 3; i++) {
  18982. + sprintf(p, "%.*d", HEX_LEN, cnt++);
  18983. + dentry = sio_lkup_one(name, hidden_parent, len, lkup);
  18984. + //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
  18985. + if (unlikely(IS_ERR(dentry) || !dentry->d_inode))
  18986. + goto out_name;
  18987. + dput(dentry);
  18988. + }
  18989. + //Warn("could not get random name\n");
  18990. + dentry = ERR_PTR(-EEXIST);
  18991. + Dbg("%.*s\n", len, name);
  18992. + BUG();
  18993. +
  18994. + out_name:
  18995. + if (unlikely(name != defname))
  18996. + kfree(name);
  18997. + out:
  18998. + TraceErrPtr(dentry);
  18999. + return dentry;
  19000. +#undef HEX_LEN
  19001. +}
  19002. +
  19003. +/*
  19004. + * rename the @dentry of @bindex to the whiteouted temporary name.
  19005. + */
  19006. +int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex)
  19007. +{
  19008. + int err;
  19009. + struct inode *hidden_dir;
  19010. + struct dentry *hidden_dentry, *hidden_parent, *tmp_dentry;
  19011. + struct super_block *sb;
  19012. + struct lkup_args lkup;
  19013. +
  19014. + LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
  19015. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  19016. + DEBUG_ON(!hidden_dentry || !hidden_dentry->d_inode);
  19017. + hidden_parent = hidden_dentry->d_parent;
  19018. + hidden_dir = hidden_parent->d_inode;
  19019. + IMustLock(hidden_dir);
  19020. +
  19021. + sb = dentry->d_sb;
  19022. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  19023. + lkup.dlgt = need_dlgt(sb);
  19024. + tmp_dentry = lkup_whtmp(hidden_parent, &hidden_dentry->d_name, &lkup);
  19025. + //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
  19026. + err = PTR_ERR(tmp_dentry);
  19027. + if (!IS_ERR(tmp_dentry)) {
  19028. + /* under the same dir, no need to lock_rename() */
  19029. + err = vfsub_rename(hidden_dir, hidden_dentry,
  19030. + hidden_dir, tmp_dentry, lkup.dlgt);
  19031. + //if (LktrCond) err = -1; //unavailable
  19032. + TraceErr(err);
  19033. + dput(tmp_dentry);
  19034. + }
  19035. +
  19036. + TraceErr(err);
  19037. + return err;
  19038. +}
  19039. +
  19040. +/* ---------------------------------------------------------------------- */
  19041. +
  19042. +int au_unlink_wh_dentry(struct inode *hidden_dir, struct dentry *wh_dentry,
  19043. + struct dentry *dentry, int dlgt)
  19044. +{
  19045. + int err;
  19046. +
  19047. + LKTRTrace("hi%lu, wh %.*s, d %p\n", hidden_dir->i_ino,
  19048. + DLNPair(wh_dentry), dentry);
  19049. + DEBUG_ON((dentry && dbwh(dentry) == -1)
  19050. + || !wh_dentry->d_inode
  19051. + || !S_ISREG(wh_dentry->d_inode->i_mode));
  19052. + IMustLock(hidden_dir);
  19053. +
  19054. + err = vfsub_unlink(hidden_dir, wh_dentry, dlgt);
  19055. + //if (LktrCond) err = -1; // unavailable
  19056. + if (!err && dentry)
  19057. + set_dbwh(dentry, -1);
  19058. +
  19059. + TraceErr(err);
  19060. + return err;
  19061. +}
  19062. +
  19063. +static int unlink_wh_name(struct dentry *hidden_parent, struct qstr *wh,
  19064. + struct lkup_args *lkup)
  19065. +{
  19066. + int err;
  19067. + struct inode *hidden_dir;
  19068. + struct dentry *hidden_dentry;
  19069. +
  19070. + LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(wh));
  19071. + hidden_dir = hidden_parent->d_inode;
  19072. + IMustLock(hidden_dir);
  19073. +
  19074. + // au_test_perm() is already done
  19075. + hidden_dentry = lkup_one(wh->name, hidden_parent, wh->len, lkup);
  19076. + //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
  19077. + if (!IS_ERR(hidden_dentry)) {
  19078. + err = 0;
  19079. + if (hidden_dentry->d_inode)
  19080. + err = vfsub_unlink(hidden_dir, hidden_dentry,
  19081. + lkup->dlgt);
  19082. + dput(hidden_dentry);
  19083. + } else
  19084. + err = PTR_ERR(hidden_dentry);
  19085. +
  19086. + TraceErr(err);
  19087. + return err;
  19088. +}
  19089. +
  19090. +/* ---------------------------------------------------------------------- */
  19091. +
  19092. +static void clean_wh(struct inode *h_dir, struct dentry *wh)
  19093. +{
  19094. + TraceEnter();
  19095. + if (wh->d_inode) {
  19096. + int err = vfsub_unlink(h_dir, wh, /*dlgt*/0);
  19097. + if (unlikely(err))
  19098. + Warn("failed unlink %.*s (%d), ignored.\n",
  19099. + DLNPair(wh), err);
  19100. + }
  19101. +}
  19102. +
  19103. +static void clean_plink(struct inode *h_dir, struct dentry *plink)
  19104. +{
  19105. + TraceEnter();
  19106. + if (plink->d_inode) {
  19107. + int err = vfsub_rmdir(h_dir, plink, /*dlgt*/0);
  19108. + if (unlikely(err))
  19109. + Warn("failed rmdir %.*s (%d), ignored.\n",
  19110. + DLNPair(plink), err);
  19111. + }
  19112. +}
  19113. +
  19114. +static int test_linkable(struct inode *h_dir)
  19115. +{
  19116. + if (h_dir->i_op && h_dir->i_op->link)
  19117. + return 0;
  19118. + return -ENOSYS;
  19119. +}
  19120. +
  19121. +static int plink_dir(struct inode *h_dir, struct dentry *plink)
  19122. +{
  19123. + int err;
  19124. +
  19125. + err = -EEXIST;
  19126. + if (!plink->d_inode) {
  19127. + int mode = S_IRWXU;
  19128. + if (unlikely(au_is_nfs(plink->d_sb)))
  19129. + mode |= S_IXUGO;
  19130. + err = vfsub_mkdir(h_dir, plink, mode, /*dlgt*/0);
  19131. + } else if (S_ISDIR(plink->d_inode->i_mode))
  19132. + err = 0;
  19133. + else
  19134. + Err("unknown %.*s exists\n", DLNPair(plink));
  19135. +
  19136. + return err;
  19137. +}
  19138. +
  19139. +/*
  19140. + * initialize the whiteout base file/dir for @br.
  19141. + */
  19142. +int init_wh(struct dentry *h_root, struct aufs_branch *br,
  19143. + struct vfsmount *nfsmnt, struct super_block *sb)
  19144. +{
  19145. + int err;
  19146. + struct dentry *wh, *plink;
  19147. + struct inode *h_dir;
  19148. + static struct qstr base_name[] = {
  19149. + {.name = AUFS_WH_BASENAME, .len = sizeof(AUFS_WH_BASENAME) - 1},
  19150. + {.name = AUFS_WH_PLINKDIR, .len = sizeof(AUFS_WH_PLINKDIR) - 1}
  19151. + };
  19152. + struct lkup_args lkup = {
  19153. + .nfsmnt = nfsmnt,
  19154. + .dlgt = 0 // always no dlgt
  19155. + };
  19156. + const int do_plink = au_flag_test(sb, AuFlag_PLINK);
  19157. +
  19158. + LKTRTrace("nfsmnt %p\n", nfsmnt);
  19159. + BrWhMustWriteLock(br);
  19160. + SiMustWriteLock(sb);
  19161. + h_dir = h_root->d_inode;
  19162. + IMustLock(h_dir);
  19163. +
  19164. + // doubly whiteouted
  19165. + wh = lkup_wh(h_root, base_name + 0, &lkup);
  19166. + //if (LktrCond) {dput(wh); wh = ERR_PTR(-1);}
  19167. + err = PTR_ERR(wh);
  19168. + if (IS_ERR(wh))
  19169. + goto out;
  19170. + DEBUG_ON(br->br_wh && br->br_wh != wh);
  19171. +
  19172. + plink = lkup_wh(h_root, base_name + 1, &lkup);
  19173. + err = PTR_ERR(plink);
  19174. + if (IS_ERR(plink))
  19175. + goto out_dput_wh;
  19176. + DEBUG_ON(br->br_plink && br->br_plink != plink);
  19177. +
  19178. + dput(br->br_wh);
  19179. + dput(br->br_plink);
  19180. + br->br_wh = br->br_plink = NULL;
  19181. +
  19182. + err = 0;
  19183. + switch (br->br_perm) {
  19184. + case AuBr_RR:
  19185. + case AuBr_RO:
  19186. + case AuBr_RRWH:
  19187. + case AuBr_ROWH:
  19188. + clean_wh(h_dir, wh);
  19189. + clean_plink(h_dir, plink);
  19190. + break;
  19191. +
  19192. + case AuBr_RWNoLinkWH:
  19193. + clean_wh(h_dir, wh);
  19194. + if (do_plink) {
  19195. + err = test_linkable(h_dir);
  19196. + if (unlikely(err))
  19197. + goto out_nolink;
  19198. +
  19199. + err = plink_dir(h_dir, plink);
  19200. + if (unlikely(err))
  19201. + goto out_err;
  19202. + br->br_plink = dget(plink);
  19203. + } else
  19204. + clean_plink(h_dir, plink);
  19205. + break;
  19206. +
  19207. + case AuBr_RW:
  19208. + /*
  19209. + * for the moment, aufs supports the branch filesystem
  19210. + * which does not support link(2).
  19211. + * testing on FAT which does not support i_op->setattr() fully either,
  19212. + * copyup failed.
  19213. + * finally, such filesystem will not be used as the writable branch.
  19214. + */
  19215. + err = test_linkable(h_dir);
  19216. + if (unlikely(err))
  19217. + goto out_nolink;
  19218. +
  19219. + err = -EEXIST;
  19220. + if (!wh->d_inode)
  19221. + err = vfsub_create(h_dir, wh, WH_MASK, NULL, /*dlgt*/0);
  19222. + else if (S_ISREG(wh->d_inode->i_mode))
  19223. + err = 0;
  19224. + else
  19225. + Err("unknown %.*s/%.*s exists\n",
  19226. + DLNPair(h_root), DLNPair(wh));
  19227. + if (unlikely(err))
  19228. + goto out_err;
  19229. +
  19230. + if (do_plink) {
  19231. + err = plink_dir(h_dir, plink);
  19232. + if (unlikely(err))
  19233. + goto out_err;
  19234. + br->br_plink = dget(plink);
  19235. + } else
  19236. + clean_plink(h_dir, plink);
  19237. + br->br_wh = dget(wh);
  19238. + break;
  19239. +
  19240. + default:
  19241. + BUG();
  19242. + }
  19243. +
  19244. + out_dput:
  19245. + dput(plink);
  19246. + out_dput_wh:
  19247. + dput(wh);
  19248. + out:
  19249. + TraceErr(err);
  19250. + return err;
  19251. + out_nolink:
  19252. + Err("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
  19253. + DLNPair(h_root));
  19254. + goto out_dput;
  19255. + out_err:
  19256. + Err("an error(%d) on the writable branch %.*s(%s)\n",
  19257. + err, DLNPair(h_root), au_sbtype(h_root->d_sb));
  19258. + goto out_dput;
  19259. +}
  19260. +
  19261. +struct reinit_br_wh {
  19262. + struct super_block *sb;
  19263. + struct aufs_branch *br;
  19264. +};
  19265. +
  19266. +static void reinit_br_wh(void *arg)
  19267. +{
  19268. + int err;
  19269. + struct reinit_br_wh *a = arg;
  19270. + struct inode *hidden_dir, *dir;
  19271. + struct dentry *hidden_root;
  19272. + aufs_bindex_t bindex;
  19273. +
  19274. + TraceEnter();
  19275. + DEBUG_ON(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
  19276. +
  19277. + err = 0;
  19278. + /* big lock */
  19279. + si_write_lock(a->sb);
  19280. + if (unlikely(!br_writable(a->br->br_perm)))
  19281. + goto out;
  19282. + bindex = find_brindex(a->sb, a->br->br_id);
  19283. + if (unlikely(bindex < 0))
  19284. + goto out;
  19285. +
  19286. + dir = a->sb->s_root->d_inode;
  19287. + hidden_root = a->br->br_wh->d_parent;
  19288. + hidden_dir = hidden_root->d_inode;
  19289. + DEBUG_ON(!hidden_dir->i_op || !hidden_dir->i_op->link);
  19290. + hdir_lock(hidden_dir, dir, bindex);
  19291. + br_wh_write_lock(a->br);
  19292. + err = vfsub_unlink(hidden_dir, a->br->br_wh, /*dlgt*/0);
  19293. + //if (LktrCond) err = -1;
  19294. + dput(a->br->br_wh);
  19295. + a->br->br_wh = NULL;
  19296. + if (!err)
  19297. + err = init_wh(hidden_root, a->br, au_do_nfsmnt(a->br->br_mnt),
  19298. + a->sb);
  19299. + br_wh_write_unlock(a->br);
  19300. + hdir_unlock(hidden_dir, dir, bindex);
  19301. +
  19302. + out:
  19303. + atomic_dec(&a->br->br_wh_running);
  19304. + br_put(a->br);
  19305. + si_write_unlock(a->sb);
  19306. + au_mntput(a->sb);
  19307. + kfree(arg);
  19308. + if (unlikely(err))
  19309. + IOErr("err %d\n", err);
  19310. +}
  19311. +
  19312. +static void kick_reinit_br_wh(struct super_block *sb, struct aufs_branch *br)
  19313. +{
  19314. + int do_dec;
  19315. + struct reinit_br_wh *arg;
  19316. +
  19317. + do_dec = 1;
  19318. + if (atomic_inc_return(&br->br_wh_running) != 1)
  19319. + goto out;
  19320. +
  19321. + // ignore ENOMEM
  19322. + arg = kmalloc(sizeof(*arg), GFP_KERNEL);
  19323. + if (arg) {
  19324. + // dec(wh_running), kfree(arg) and br_put() in reinit function
  19325. + arg->sb = sb;
  19326. + arg->br = br;
  19327. + br_get(br);
  19328. + /* prohibit umount */
  19329. + au_mntget(sb);
  19330. + au_wkq_nowait(reinit_br_wh, arg, /*dlgt*/0);
  19331. + do_dec = 0;
  19332. + }
  19333. +
  19334. + out:
  19335. + if (do_dec)
  19336. + atomic_dec(&br->br_wh_running);
  19337. +}
  19338. +
  19339. +/*
  19340. + * create the whiteoute @wh.
  19341. + */
  19342. +static int link_or_create_wh(struct dentry *wh, struct super_block *sb,
  19343. + aufs_bindex_t bindex)
  19344. +{
  19345. + int err, dlgt;
  19346. + struct aufs_branch *br;
  19347. + struct dentry *hidden_parent;
  19348. + struct inode *hidden_dir;
  19349. +
  19350. + LKTRTrace("%.*s\n", DLNPair(wh));
  19351. + SiMustReadLock(sb);
  19352. + hidden_parent = wh->d_parent;
  19353. + hidden_dir = hidden_parent->d_inode;
  19354. + IMustLock(hidden_dir);
  19355. +
  19356. + dlgt = need_dlgt(sb);
  19357. + br = stobr(sb, bindex);
  19358. + br_wh_read_lock(br);
  19359. + if (br->br_wh) {
  19360. + err = vfsub_link(br->br_wh, hidden_dir, wh, dlgt);
  19361. + if (!err || err != -EMLINK)
  19362. + goto out;
  19363. +
  19364. + // link count full. re-initialize br_wh.
  19365. + kick_reinit_br_wh(sb, br);
  19366. + }
  19367. +
  19368. + // return this error in this context
  19369. + err = vfsub_create(hidden_dir, wh, WH_MASK, NULL, dlgt);
  19370. +
  19371. + out:
  19372. + br_wh_read_unlock(br);
  19373. + TraceErr(err);
  19374. + return err;
  19375. +}
  19376. +
  19377. +/* ---------------------------------------------------------------------- */
  19378. +
  19379. +/*
  19380. + * create or remove the diropq.
  19381. + */
  19382. +static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19383. + int do_create, int dlgt)
  19384. +{
  19385. + struct dentry *opq_dentry, *hidden_dentry;
  19386. + struct inode *hidden_dir;
  19387. + int err;
  19388. + struct super_block *sb;
  19389. + struct lkup_args lkup;
  19390. +
  19391. + LKTRTrace("%.*s, bindex %d, do_create %d\n", DLNPair(dentry),
  19392. + bindex, do_create);
  19393. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  19394. + DEBUG_ON(!hidden_dentry);
  19395. + hidden_dir = hidden_dentry->d_inode;
  19396. + DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
  19397. + IMustLock(hidden_dir);
  19398. +
  19399. + // already checked by au_test_perm().
  19400. + sb = dentry->d_sb;
  19401. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  19402. + lkup.dlgt = dlgt;
  19403. + opq_dentry = lkup_one(diropq_name.name, hidden_dentry, diropq_name.len,
  19404. + &lkup);
  19405. + //if (LktrCond) {dput(opq_dentry); opq_dentry = ERR_PTR(-1);}
  19406. + if (IS_ERR(opq_dentry))
  19407. + goto out;
  19408. +
  19409. + if (do_create) {
  19410. + DEBUG_ON(opq_dentry->d_inode);
  19411. + err = link_or_create_wh(opq_dentry, sb, bindex);
  19412. + //if (LktrCond) {vfs_unlink(hidden_dir, opq_dentry); err = -1;}
  19413. + if (!err) {
  19414. + set_dbdiropq(dentry, bindex);
  19415. + goto out; /* success */
  19416. + }
  19417. + } else {
  19418. + DEBUG_ON(/* !S_ISDIR(dentry->d_inode->i_mode)
  19419. + * || */!opq_dentry->d_inode);
  19420. + err = vfsub_unlink(hidden_dir, opq_dentry, lkup.dlgt);
  19421. + //if (LktrCond) err = -1;
  19422. + if (!err)
  19423. + set_dbdiropq(dentry, -1);
  19424. + }
  19425. + dput(opq_dentry);
  19426. + opq_dentry = ERR_PTR(err);
  19427. +
  19428. + out:
  19429. + TraceErrPtr(opq_dentry);
  19430. + return opq_dentry;
  19431. +}
  19432. +
  19433. +struct do_diropq_args {
  19434. + struct dentry **errp;
  19435. + struct dentry *dentry;
  19436. + aufs_bindex_t bindex;
  19437. + int do_create, dlgt;
  19438. +};
  19439. +
  19440. +static void call_do_diropq(void *args)
  19441. +{
  19442. + struct do_diropq_args *a = args;
  19443. + *a->errp = do_diropq(a->dentry, a->bindex, a->do_create, a->dlgt);
  19444. +}
  19445. +
  19446. +struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19447. + int do_create, int dlgt)
  19448. +{
  19449. + struct dentry *diropq, *hidden_dentry;
  19450. +
  19451. + LKTRTrace("%.*s, bindex %d, do_create %d\n",
  19452. + DLNPair(dentry), bindex, do_create);
  19453. +
  19454. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  19455. + if (!au_test_perm(hidden_dentry->d_inode, MAY_EXEC | MAY_WRITE, dlgt))
  19456. + diropq = do_diropq(dentry, bindex, do_create, dlgt);
  19457. + else {
  19458. + struct do_diropq_args args = {
  19459. + .errp = &diropq,
  19460. + .dentry = dentry,
  19461. + .bindex = bindex,
  19462. + .do_create = do_create,
  19463. + .dlgt = dlgt
  19464. + };
  19465. + au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
  19466. + }
  19467. +
  19468. + TraceErrPtr(diropq);
  19469. + return diropq;
  19470. +}
  19471. +
  19472. +/* ---------------------------------------------------------------------- */
  19473. +
  19474. +/*
  19475. + * lookup whiteout dentry.
  19476. + * @hidden_parent: hidden parent dentry which must exist and be locked
  19477. + * @base_name: name of dentry which will be whiteouted
  19478. + * returns dentry for whiteout.
  19479. + */
  19480. +struct dentry *lkup_wh(struct dentry *hidden_parent, struct qstr *base_name,
  19481. + struct lkup_args *lkup)
  19482. +{
  19483. + int err;
  19484. + struct qstr wh_name;
  19485. + struct dentry *wh_dentry;
  19486. +
  19487. + LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(base_name));
  19488. + IMustLock(hidden_parent->d_inode);
  19489. +
  19490. + err = au_alloc_whname(base_name->name, base_name->len, &wh_name);
  19491. + //if (LktrCond) {au_free_whname(&wh_name); err = -1;}
  19492. + wh_dentry = ERR_PTR(err);
  19493. + if (!err) {
  19494. + // do not superio.
  19495. + wh_dentry = lkup_one(wh_name.name, hidden_parent, wh_name.len,
  19496. + lkup);
  19497. + au_free_whname(&wh_name);
  19498. + }
  19499. + TraceErrPtr(wh_dentry);
  19500. + return wh_dentry;
  19501. +}
  19502. +
  19503. +/*
  19504. + * link/create a whiteout for @dentry on @bindex.
  19505. + */
  19506. +struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
  19507. + struct dentry *hidden_parent,
  19508. + struct lkup_args *lkup)
  19509. +{
  19510. + struct dentry *wh_dentry;
  19511. + int err;
  19512. + struct super_block *sb;
  19513. +
  19514. + LKTRTrace("%.*s/%.*s on b%d\n", DLNPair(hidden_parent),
  19515. + DLNPair(dentry), bindex);
  19516. +
  19517. + sb = dentry->d_sb;
  19518. + wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, lkup);
  19519. + //au_nfsmnt(sb, bindex), need_dlgt(sb));
  19520. + //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
  19521. + if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
  19522. + IMustLock(hidden_parent->d_inode);
  19523. + err = link_or_create_wh(wh_dentry, sb, bindex);
  19524. + if (!err)
  19525. + set_dbwh(dentry, bindex);
  19526. + else {
  19527. + dput(wh_dentry);
  19528. + wh_dentry = ERR_PTR(err);
  19529. + }
  19530. + }
  19531. +
  19532. + TraceErrPtr(wh_dentry);
  19533. + return wh_dentry;
  19534. +}
  19535. +
  19536. +/* ---------------------------------------------------------------------- */
  19537. +
  19538. +/* Delete all whiteouts in this directory in branch bindex. */
  19539. +static int del_wh_children(struct aufs_nhash *whlist,
  19540. + struct dentry *hidden_parent, aufs_bindex_t bindex,
  19541. + struct lkup_args *lkup)
  19542. +{
  19543. + int err, i;
  19544. + struct qstr wh_name;
  19545. + char *p;
  19546. + struct inode *hidden_dir;
  19547. + struct hlist_head *head;
  19548. + struct aufs_wh *tpos;
  19549. + struct hlist_node *pos;
  19550. + struct aufs_destr *str;
  19551. +
  19552. + LKTRTrace("%.*s\n", DLNPair(hidden_parent));
  19553. + hidden_dir = hidden_parent->d_inode;
  19554. + IMustLock(hidden_dir);
  19555. + DEBUG_ON(IS_RDONLY(hidden_dir));
  19556. + //SiMustReadLock(??);
  19557. +
  19558. + err = -ENOMEM;
  19559. + wh_name.name = p = __getname();
  19560. + //if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
  19561. + if (unlikely(!wh_name.name))
  19562. + goto out;
  19563. + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
  19564. + p += AUFS_WH_PFX_LEN;
  19565. +
  19566. + // already checked by au_test_perm().
  19567. + err = 0;
  19568. + for (i = 0; !err && i < AUFS_NHASH_SIZE; i++) {
  19569. + head = whlist->heads + i;
  19570. + hlist_for_each_entry(tpos, pos, head, wh_hash) {
  19571. + if (tpos->wh_bindex != bindex)
  19572. + continue;
  19573. + str = &tpos->wh_str;
  19574. + if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
  19575. + memcpy(p, str->name, str->len);
  19576. + wh_name.len = AUFS_WH_PFX_LEN + str->len;
  19577. + err = unlink_wh_name(hidden_parent, &wh_name,
  19578. + lkup);
  19579. + //if (LktrCond) err = -1;
  19580. + if (!err)
  19581. + continue;
  19582. + break;
  19583. + }
  19584. + IOErr("whiteout name too long %.*s\n",
  19585. + str->len, str->name);
  19586. + err = -EIO;
  19587. + break;
  19588. + }
  19589. + }
  19590. + __putname(wh_name.name);
  19591. +
  19592. + out:
  19593. + TraceErr(err);
  19594. + return err;
  19595. +}
  19596. +
  19597. +struct del_wh_children_args {
  19598. + int *errp;
  19599. + struct aufs_nhash *whlist;
  19600. + struct dentry *hidden_parent;
  19601. + aufs_bindex_t bindex;
  19602. + struct lkup_args *lkup;
  19603. +};
  19604. +
  19605. +static void call_del_wh_children(void *args)
  19606. +{
  19607. + struct del_wh_children_args *a = args;
  19608. + *a->errp = del_wh_children(a->whlist, a->hidden_parent, a->bindex,
  19609. + a->lkup);
  19610. +}
  19611. +
  19612. +/* ---------------------------------------------------------------------- */
  19613. +
  19614. +/*
  19615. + * rmdir the whiteouted temporary named dir @hidden_dentry.
  19616. + * @whlist: whiteouted children.
  19617. + */
  19618. +int rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
  19619. + aufs_bindex_t bindex, struct inode *dir, struct inode *inode)
  19620. +{
  19621. + int err;
  19622. + struct inode *hidden_inode, *hidden_dir;
  19623. + struct lkup_args lkup;
  19624. + struct super_block *sb;
  19625. +
  19626. + LKTRTrace("hd %.*s, b%d, i%lu\n",
  19627. + DLNPair(hidden_dentry), bindex, dir->i_ino);
  19628. + IMustLock(dir);
  19629. + IiMustAnyLock(dir);
  19630. + hidden_dir = hidden_dentry->d_parent->d_inode;
  19631. + IMustLock(hidden_dir);
  19632. +
  19633. + sb = inode->i_sb;
  19634. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  19635. + lkup.dlgt = need_dlgt(sb);
  19636. + hidden_inode = hidden_dentry->d_inode;
  19637. + DEBUG_ON(hidden_inode != au_h_iptr_i(inode, bindex));
  19638. + hdir2_lock(hidden_inode, inode, bindex);
  19639. + if (!au_test_perm(hidden_inode, MAY_EXEC | MAY_WRITE, lkup.dlgt))
  19640. + err = del_wh_children(whlist, hidden_dentry, bindex, &lkup);
  19641. + else {
  19642. + // ugly
  19643. + int dlgt = lkup.dlgt;
  19644. + struct del_wh_children_args args = {
  19645. + .errp = &err,
  19646. + .whlist = whlist,
  19647. + .hidden_parent = hidden_dentry,
  19648. + .bindex = bindex,
  19649. + .lkup = &lkup
  19650. + };
  19651. +
  19652. + lkup.dlgt = 0;
  19653. + au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
  19654. + lkup.dlgt = dlgt;
  19655. + }
  19656. + hdir_unlock(hidden_inode, inode, bindex);
  19657. +
  19658. + if (!err) {
  19659. + err = vfsub_rmdir(hidden_dir, hidden_dentry, lkup.dlgt);
  19660. + //d_drop(hidden_dentry);
  19661. + //if (LktrCond) err = -1;
  19662. + }
  19663. +
  19664. + if (!err) {
  19665. + if (ibstart(dir) == bindex) {
  19666. + au_cpup_attr_timesizes(dir);
  19667. + //au_cpup_attr_nlink(dir);
  19668. + dir->i_nlink--;
  19669. + }
  19670. + return 0; /* success */
  19671. + }
  19672. +
  19673. + Warn("failed removing %.*s(%d), ignored\n",
  19674. + DLNPair(hidden_dentry), err);
  19675. + return err;
  19676. +}
  19677. +
  19678. +static void do_rmdir_whtmp(void *arg)
  19679. +{
  19680. + int err;
  19681. + struct rmdir_whtmp_arg *a = arg;
  19682. + struct super_block *sb;
  19683. +
  19684. + LKTRTrace("%.*s, b%d, dir i%lu\n",
  19685. + DLNPair(a->h_dentry), a->bindex, a->dir->i_ino);
  19686. +
  19687. + i_lock(a->dir);
  19688. + sb = a->dir->i_sb;
  19689. + si_read_lock(sb);
  19690. + err = test_ro(sb, a->bindex, NULL);
  19691. + if (!err) {
  19692. + struct inode *hidden_dir = a->h_dentry->d_parent->d_inode;
  19693. +
  19694. + ii_write_lock_child(a->inode);
  19695. + ii_write_lock_parent(a->dir);
  19696. + hdir_lock(hidden_dir, a->dir, a->bindex);
  19697. + err = rmdir_whtmp(a->h_dentry, &a->whlist, a->bindex,
  19698. + a->dir, a->inode);
  19699. + hdir_unlock(hidden_dir, a->dir, a->bindex);
  19700. + ii_write_unlock(a->dir);
  19701. + ii_write_unlock(a->inode);
  19702. + }
  19703. + dput(a->h_dentry);
  19704. + nhash_fin(&a->whlist);
  19705. + iput(a->inode);
  19706. + si_read_unlock(sb);
  19707. + au_mntput(sb);
  19708. + i_unlock(a->dir);
  19709. + iput(a->dir);
  19710. + kfree(arg);
  19711. + if (unlikely(err))
  19712. + IOErr("err %d\n", err);
  19713. +}
  19714. +
  19715. +void kick_rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
  19716. + aufs_bindex_t bindex, struct inode *dir,
  19717. + struct inode *inode, struct rmdir_whtmp_arg *arg)
  19718. +{
  19719. + LKTRTrace("%.*s\n", DLNPair(hidden_dentry));
  19720. + IMustLock(dir);
  19721. +
  19722. + // all post-process will be done in do_rmdir_whtmp().
  19723. + arg->h_dentry = dget(hidden_dentry);
  19724. + nhash_init(&arg->whlist);
  19725. + nhash_move(&arg->whlist, whlist);
  19726. + arg->bindex = bindex;
  19727. + arg->dir = igrab(dir);
  19728. + arg->inode = igrab(inode);
  19729. + /* prohibit umount */
  19730. + au_mntget(dir->i_sb);
  19731. +
  19732. + au_wkq_nowait(do_rmdir_whtmp, arg, /*dlgt*/0);
  19733. +}
  19734. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/whout.h linux-2.6.22.1/fs/aufs/whout.h
  19735. --- linux-2.6.22.1.oorig/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
  19736. +++ linux-2.6.22.1/fs/aufs/whout.h 2007-07-24 14:17:46.000000000 +0200
  19737. @@ -0,0 +1,87 @@
  19738. +/*
  19739. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  19740. + *
  19741. + * This program, aufs is free software; you can redistribute it and/or modify
  19742. + * it under the terms of the GNU General Public License as published by
  19743. + * the Free Software Foundation; either version 2 of the License, or
  19744. + * (at your option) any later version.
  19745. + *
  19746. + * This program is distributed in the hope that it will be useful,
  19747. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19748. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19749. + * GNU General Public License for more details.
  19750. + *
  19751. + * You should have received a copy of the GNU General Public License
  19752. + * along with this program; if not, write to the Free Software
  19753. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19754. + */
  19755. +
  19756. +/* $Id: whout.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
  19757. +
  19758. +#ifndef __AUFS_WHOUT_H__
  19759. +#define __AUFS_WHOUT_H__
  19760. +
  19761. +#ifdef __KERNEL__
  19762. +
  19763. +#include <linux/fs.h>
  19764. +#include <linux/aufs_type.h>
  19765. +
  19766. +int au_alloc_whname(const char *name, int len, struct qstr *wh);
  19767. +void au_free_whname(struct qstr *wh);
  19768. +
  19769. +struct lkup_args;
  19770. +int is_wh(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
  19771. + struct lkup_args *lkup);
  19772. +int is_diropq(struct dentry *h_dentry, struct lkup_args *lkup);
  19773. +
  19774. +struct dentry *lkup_whtmp(struct dentry *h_parent, struct qstr *prefix,
  19775. + struct lkup_args *lkup);
  19776. +int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex);
  19777. +int au_unlink_wh_dentry(struct inode *h_dir, struct dentry *wh_dentry,
  19778. + struct dentry *dentry, int dlgt);
  19779. +
  19780. +struct aufs_branch;
  19781. +int init_wh(struct dentry *h_parent, struct aufs_branch *br,
  19782. + struct vfsmount *nfsmnt, struct super_block *sb);
  19783. +
  19784. +struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19785. + int do_create, int dlgt);
  19786. +
  19787. +struct dentry *lkup_wh(struct dentry *h_parent, struct qstr *base_name,
  19788. + struct lkup_args *lkup);
  19789. +struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
  19790. + struct dentry *h_parent,
  19791. + struct lkup_args *lkup);
  19792. +
  19793. +/* real rmdir the whiteout-ed dir */
  19794. +struct rmdir_whtmp_arg {
  19795. + struct dentry *h_dentry;
  19796. + struct aufs_nhash whlist;
  19797. + aufs_bindex_t bindex;
  19798. + struct inode *dir, *inode;
  19799. +};
  19800. +
  19801. +struct aufs_nhash;
  19802. +int rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
  19803. + aufs_bindex_t bindex, struct inode *dir, struct inode *inode);
  19804. +void kick_rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
  19805. + aufs_bindex_t bindex, struct inode *dir,
  19806. + struct inode *inode, struct rmdir_whtmp_arg *arg);
  19807. +
  19808. +/* ---------------------------------------------------------------------- */
  19809. +
  19810. +static inline
  19811. +struct dentry *create_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19812. + int dlgt)
  19813. +{
  19814. + return sio_diropq(dentry, bindex, 1, dlgt);
  19815. +}
  19816. +
  19817. +static inline
  19818. +int remove_diropq(struct dentry *dentry, aufs_bindex_t bindex, int dlgt)
  19819. +{
  19820. + return PTR_ERR(sio_diropq(dentry, bindex, 0, dlgt));
  19821. +}
  19822. +
  19823. +#endif /* __KERNEL__ */
  19824. +#endif /* __AUFS_WHOUT_H__ */
  19825. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/wkq.c linux-2.6.22.1/fs/aufs/wkq.c
  19826. --- linux-2.6.22.1.oorig/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
  19827. +++ linux-2.6.22.1/fs/aufs/wkq.c 2007-07-24 14:17:46.000000000 +0200
  19828. @@ -0,0 +1,283 @@
  19829. +/*
  19830. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  19831. + *
  19832. + * This program, aufs is free software; you can redistribute it and/or modify
  19833. + * it under the terms of the GNU General Public License as published by
  19834. + * the Free Software Foundation; either version 2 of the License, or
  19835. + * (at your option) any later version.
  19836. + *
  19837. + * This program is distributed in the hope that it will be useful,
  19838. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19839. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19840. + * GNU General Public License for more details.
  19841. + *
  19842. + * You should have received a copy of the GNU General Public License
  19843. + * along with this program; if not, write to the Free Software
  19844. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19845. + */
  19846. +
  19847. +/* $Id: wkq.c,v 1.14 2007/05/14 03:39:10 sfjro Exp $ */
  19848. +
  19849. +#include <linux/module.h>
  19850. +#include "aufs.h"
  19851. +
  19852. +struct au_wkq *au_wkq;
  19853. +
  19854. +struct au_cred {
  19855. +#ifdef CONFIG_AUFS_DLGT
  19856. + uid_t fsuid;
  19857. + gid_t fsgid;
  19858. + kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
  19859. + //unsigned keep_capabilities:1;
  19860. + //struct user_struct *user;
  19861. + //struct fs_struct *fs;
  19862. + //struct nsproxy *nsproxy;
  19863. +#endif
  19864. +};
  19865. +
  19866. +struct au_wkinfo {
  19867. + struct work_struct wk;
  19868. +
  19869. + unsigned int wait:1;
  19870. + unsigned int dlgt:1;
  19871. + struct au_cred cred;
  19872. +
  19873. + au_wkq_func_t func;
  19874. + void *args;
  19875. +
  19876. + atomic_t *busyp;
  19877. + struct completion *comp;
  19878. +};
  19879. +
  19880. +/* ---------------------------------------------------------------------- */
  19881. +
  19882. +#ifdef CONFIG_AUFS_DLGT
  19883. +static void cred_store(struct au_cred *cred)
  19884. +{
  19885. + cred->fsuid = current->fsuid;
  19886. + cred->fsgid = current->fsgid;
  19887. + cred->cap_effective = current->cap_effective;
  19888. + cred->cap_inheritable = current->cap_inheritable;
  19889. + cred->cap_permitted = current->cap_permitted;
  19890. +}
  19891. +
  19892. +static void cred_revert(struct au_cred *cred)
  19893. +{
  19894. + DEBUG_ON(!is_au_wkq(current));
  19895. + current->fsuid = cred->fsuid;
  19896. + current->fsgid = cred->fsgid;
  19897. + current->cap_effective = cred->cap_effective;
  19898. + current->cap_inheritable = cred->cap_inheritable;
  19899. + current->cap_permitted = cred->cap_permitted;
  19900. +}
  19901. +
  19902. +static void cred_switch(struct au_cred *old, struct au_cred *new)
  19903. +{
  19904. + cred_store(old);
  19905. + cred_revert(new);
  19906. +}
  19907. +#endif
  19908. +
  19909. +/* ---------------------------------------------------------------------- */
  19910. +
  19911. +static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
  19912. +{
  19913. +#ifdef CONFIG_AUFS_SYSAUFS
  19914. + unsigned int new, old;
  19915. +
  19916. + do {
  19917. + new = atomic_read(wkinfo->busyp);
  19918. + old = wkq->max_busy;
  19919. + if (new <= old)
  19920. + break;
  19921. + } while (cmpxchg(&wkq->max_busy, old, new) == old);
  19922. +#endif
  19923. +}
  19924. +
  19925. +static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
  19926. +{
  19927. + wkinfo->busyp = &wkq->busy;
  19928. + update_busy(wkq, wkinfo);
  19929. + if (wkinfo->wait)
  19930. + return !queue_work(wkq->q, &wkinfo->wk);
  19931. + else
  19932. + return !schedule_work(&wkinfo->wk);
  19933. +}
  19934. +
  19935. +static void do_wkq(struct au_wkinfo *wkinfo)
  19936. +{
  19937. + unsigned int idle, n;
  19938. + int i, idle_idx;
  19939. +
  19940. + TraceEnter();
  19941. +
  19942. + while (1) {
  19943. + if (wkinfo->wait) {
  19944. + idle_idx = 0;
  19945. + idle = UINT_MAX;
  19946. + for (i = 0; i < aufs_nwkq; i++) {
  19947. + n = atomic_inc_return(&au_wkq[i].busy);
  19948. + if (n == 1 && !enqueue(au_wkq + i, wkinfo))
  19949. + return; /* success */
  19950. +
  19951. + if (n < idle) {
  19952. + idle_idx = i;
  19953. + idle = n;
  19954. + }
  19955. + atomic_dec(&au_wkq[i].busy);
  19956. + }
  19957. + } else
  19958. + idle_idx = aufs_nwkq;
  19959. +
  19960. + atomic_inc(&au_wkq[idle_idx].busy);
  19961. + if (!enqueue(au_wkq + idle_idx, wkinfo))
  19962. + return; /* success */
  19963. +
  19964. + /* impossible? */
  19965. + Warn1("failed to queue_work()\n");
  19966. + yield();
  19967. + }
  19968. +}
  19969. +
  19970. +static AuWkqFunc(wkq_func, wk)
  19971. +{
  19972. + struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
  19973. +
  19974. + LKTRTrace("wkinfo{%u, %u, %p, %p, %p}\n",
  19975. + wkinfo->wait, wkinfo->dlgt, wkinfo->func, wkinfo->busyp,
  19976. + wkinfo->comp);
  19977. +#ifdef CONFIG_AUFS_DLGT
  19978. + if (!wkinfo->dlgt)
  19979. + wkinfo->func(wkinfo->args);
  19980. + else {
  19981. + struct au_cred cred;
  19982. + cred_switch(&cred, &wkinfo->cred);
  19983. + wkinfo->func(wkinfo->args);
  19984. + cred_revert(&cred);
  19985. + }
  19986. +#else
  19987. + wkinfo->func(wkinfo->args);
  19988. +#endif
  19989. + atomic_dec(wkinfo->busyp);
  19990. + if (wkinfo->wait)
  19991. + complete(wkinfo->comp);
  19992. + else {
  19993. + kfree(wkinfo);
  19994. + module_put(THIS_MODULE);
  19995. + }
  19996. +}
  19997. +
  19998. +void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait)
  19999. +{
  20000. + DECLARE_COMPLETION_ONSTACK(comp);
  20001. + struct au_wkinfo _wkinfo = {
  20002. + .wait = 1,
  20003. + .dlgt = !!dlgt,
  20004. + .func = func,
  20005. + .args = args,
  20006. + .comp = &comp
  20007. + }, *wkinfo = &_wkinfo;
  20008. +
  20009. + LKTRTrace("dlgt %d, do_wait %d\n", dlgt, do_wait);
  20010. + DEBUG_ON(is_au_wkq(current));
  20011. +
  20012. + if (unlikely(!do_wait)) {
  20013. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  20014. + /*
  20015. + * never fail.
  20016. + * wkq_func() must free this wkinfo.
  20017. + * it highly depends upon the implementation of workqueue.
  20018. + */
  20019. + wait_event(wq, (wkinfo = kmalloc(sizeof(*wkinfo), GFP_KERNEL)));
  20020. + wkinfo->wait = 0;
  20021. + wkinfo->dlgt = !!dlgt;
  20022. + wkinfo->func = func;
  20023. + wkinfo->args = args;
  20024. + wkinfo->comp = NULL;
  20025. + __module_get(THIS_MODULE);
  20026. + }
  20027. +
  20028. + AuInitWkq(&wkinfo->wk, wkq_func);
  20029. +#ifdef CONFIG_AUFS_DLGT
  20030. + if (dlgt)
  20031. + cred_store(&wkinfo->cred);
  20032. +#endif
  20033. + do_wkq(wkinfo);
  20034. + if (do_wait)
  20035. + wait_for_completion(wkinfo->comp);
  20036. +}
  20037. +
  20038. +#if 0
  20039. +void au_wkq_wait_nwtask(void)
  20040. +{
  20041. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  20042. + wait_event(wq, !atomic_read(&au_wkq[aufs_nwkq].busy));
  20043. +}
  20044. +#endif
  20045. +
  20046. +void au_wkq_fin(void)
  20047. +{
  20048. + int i;
  20049. +
  20050. + TraceEnter();
  20051. +
  20052. + for (i = 0; i < aufs_nwkq; i++)
  20053. + if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
  20054. + destroy_workqueue(au_wkq[i].q);
  20055. + kfree(au_wkq);
  20056. +}
  20057. +
  20058. +int __init au_wkq_init(void)
  20059. +{
  20060. + int err, i;
  20061. + struct au_wkq *nowaitq;
  20062. +
  20063. + LKTRTrace("%d\n", aufs_nwkq);
  20064. +
  20065. + /* '+1' is for accounting of nowait queue */
  20066. + err = -ENOMEM;
  20067. + au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_KERNEL);
  20068. + if (unlikely(!au_wkq))
  20069. + goto out;
  20070. +
  20071. + err = 0;
  20072. + for (i = 0; i < aufs_nwkq; i++) {
  20073. + au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
  20074. + if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
  20075. + atomic_set(&au_wkq[i].busy, 0);
  20076. + au_wkq[i].max_busy = 0;
  20077. + continue;
  20078. + }
  20079. +
  20080. + err = PTR_ERR(au_wkq[i].q);
  20081. + au_wkq_fin();
  20082. + break;
  20083. + }
  20084. +
  20085. + /* nowait accounting */
  20086. + nowaitq = au_wkq + aufs_nwkq;
  20087. + atomic_set(&nowaitq->busy, 0);
  20088. + nowaitq->max_busy = 0;
  20089. + nowaitq->q = NULL;
  20090. +
  20091. +#if 0 // test accouting
  20092. + if (!err) {
  20093. + static void f(void *args) {
  20094. + DbgSleep(1);
  20095. + }
  20096. + int i;
  20097. + //au_debug_on();
  20098. + LKTRTrace("f %p\n", f);
  20099. + for (i = 0; i < 10; i++)
  20100. + au_wkq_nowait(f, NULL, 0);
  20101. + for (i = 0; i < aufs_nwkq; i++)
  20102. + au_wkq_wait(f, NULL, 0);
  20103. + DbgSleep(11);
  20104. + //au_debug_off();
  20105. + }
  20106. +#endif
  20107. +
  20108. + out:
  20109. + TraceErr(err);
  20110. + return err;
  20111. +}
  20112. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/wkq.h linux-2.6.22.1/fs/aufs/wkq.h
  20113. --- linux-2.6.22.1.oorig/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
  20114. +++ linux-2.6.22.1/fs/aufs/wkq.h 2007-07-24 14:17:46.000000000 +0200
  20115. @@ -0,0 +1,81 @@
  20116. +/*
  20117. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  20118. + *
  20119. + * This program, aufs is free software; you can redistribute it and/or modify
  20120. + * it under the terms of the GNU General Public License as published by
  20121. + * the Free Software Foundation; either version 2 of the License, or
  20122. + * (at your option) any later version.
  20123. + *
  20124. + * This program is distributed in the hope that it will be useful,
  20125. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20126. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20127. + * GNU General Public License for more details.
  20128. + *
  20129. + * You should have received a copy of the GNU General Public License
  20130. + * along with this program; if not, write to the Free Software
  20131. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20132. + */
  20133. +
  20134. +/* $Id: wkq.h,v 1.9 2007/05/14 03:39:10 sfjro Exp $ */
  20135. +
  20136. +#ifndef __AUFS_WKQ_H__
  20137. +#define __AUFS_WKQ_H__
  20138. +
  20139. +#ifdef __KERNEL__
  20140. +
  20141. +#include <linux/sched.h>
  20142. +#include <linux/version.h>
  20143. +#include <linux/workqueue.h>
  20144. +
  20145. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  20146. +#define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work)
  20147. +#endif
  20148. +
  20149. +/* ---------------------------------------------------------------------- */
  20150. +
  20151. +/* internal workqueue named AUFS_WKQ_NAME */
  20152. +struct au_wkq {
  20153. + struct workqueue_struct *q;
  20154. +
  20155. + /* accounting */
  20156. + atomic_t busy;
  20157. + unsigned int max_busy;
  20158. +} ;//__attribute__ ((aligned));
  20159. +
  20160. +typedef void (*au_wkq_func_t)(void *args);
  20161. +
  20162. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
  20163. +#define AuInitWkq(wk, func) INIT_WORK(wk, func)
  20164. +#define AuWkqFunc(name, arg) void name(struct work_struct *arg)
  20165. +#else
  20166. +typedef void (*work_func_t)(void *arg);
  20167. +#define AuInitWkq(wk, func) INIT_WORK(wk, func, wk)
  20168. +#define AuWkqFunc(name, arg) void name(void *arg)
  20169. +#endif
  20170. +
  20171. +extern struct au_wkq *au_wkq;
  20172. +
  20173. +void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait);
  20174. +//void au_wkq_wait_nwtask(void);
  20175. +int __init au_wkq_init(void);
  20176. +void au_wkq_fin(void);
  20177. +
  20178. +/* ---------------------------------------------------------------------- */
  20179. +
  20180. +static inline int is_au_wkq(struct task_struct *tsk)
  20181. +{
  20182. + return (!tsk->mm && !strcmp(current->comm, AUFS_WKQ_NAME));
  20183. +}
  20184. +
  20185. +static inline void au_wkq_wait(au_wkq_func_t func, void *args, int dlgt)
  20186. +{
  20187. + au_wkq_run(func, args, dlgt, /*do_wait*/1);
  20188. +}
  20189. +
  20190. +static inline void au_wkq_nowait(au_wkq_func_t func, void *args, int dlgt)
  20191. +{
  20192. + au_wkq_run(func, args, dlgt, /*do_wait*/0);
  20193. +}
  20194. +
  20195. +#endif /* __KERNEL__ */
  20196. +#endif /* __AUFS_WKQ_H__ */
  20197. diff -rduNp linux-2.6.22.1.oorig/fs/aufs/xino.c linux-2.6.22.1/fs/aufs/xino.c
  20198. --- linux-2.6.22.1.oorig/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
  20199. +++ linux-2.6.22.1/fs/aufs/xino.c 2007-07-24 14:17:46.000000000 +0200
  20200. @@ -0,0 +1,644 @@
  20201. +/*
  20202. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  20203. + *
  20204. + * This program, aufs is free software; you can redistribute it and/or modify
  20205. + * it under the terms of the GNU General Public License as published by
  20206. + * the Free Software Foundation; either version 2 of the License, or
  20207. + * (at your option) any later version.
  20208. + *
  20209. + * This program is distributed in the hope that it will be useful,
  20210. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20211. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20212. + * GNU General Public License for more details.
  20213. + *
  20214. + * You should have received a copy of the GNU General Public License
  20215. + * along with this program; if not, write to the Free Software
  20216. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20217. + */
  20218. +
  20219. +/* $Id: xino.c,v 1.27 2007/05/14 03:39:10 sfjro Exp $ */
  20220. +
  20221. +//#include <linux/fs.h>
  20222. +#include <linux/fsnotify.h>
  20223. +#include <asm/uaccess.h>
  20224. +#include "aufs.h"
  20225. +
  20226. +static readf_t find_readf(struct file *h_file)
  20227. +{
  20228. + const struct file_operations *fop = h_file->f_op;
  20229. +
  20230. + if (fop) {
  20231. + if (fop->read)
  20232. + return fop->read;
  20233. + if (fop->aio_read)
  20234. + return do_sync_read;
  20235. + }
  20236. + return ERR_PTR(-ENOSYS);
  20237. +}
  20238. +
  20239. +static writef_t find_writef(struct file *h_file)
  20240. +{
  20241. + const struct file_operations *fop = h_file->f_op;
  20242. +
  20243. + if (fop) {
  20244. + if (fop->write)
  20245. + return fop->write;
  20246. + if (fop->aio_write)
  20247. + return do_sync_write;
  20248. + }
  20249. + return ERR_PTR(-ENOSYS);
  20250. +}
  20251. +
  20252. +/* ---------------------------------------------------------------------- */
  20253. +
  20254. +static ssize_t xino_fread(readf_t func, struct file *file, void *buf,
  20255. + size_t size, loff_t *pos)
  20256. +{
  20257. + ssize_t err;
  20258. + mm_segment_t oldfs;
  20259. +
  20260. + LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
  20261. + DLNPair(file->f_dentry), (unsigned long)size, *pos);
  20262. +
  20263. + oldfs = get_fs();
  20264. + set_fs(KERNEL_DS);
  20265. + do {
  20266. + err = func(file, (char __user*)buf, size, pos);
  20267. + } while (err == -EAGAIN || err == -EINTR);
  20268. + set_fs(oldfs);
  20269. +
  20270. +#if 0
  20271. + if (err > 0)
  20272. + fsnotify_access(file->f_dentry);
  20273. +#endif
  20274. +
  20275. + TraceErr(err);
  20276. + return err;
  20277. +}
  20278. +
  20279. +/* ---------------------------------------------------------------------- */
  20280. +
  20281. +static ssize_t do_xino_fwrite(writef_t func, struct file *file, void *buf,
  20282. + size_t size, loff_t *pos)
  20283. +{
  20284. + ssize_t err;
  20285. + mm_segment_t oldfs;
  20286. +
  20287. + lockdep_off();
  20288. + oldfs = get_fs();
  20289. + set_fs(KERNEL_DS);
  20290. + do {
  20291. + err = func(file, (const char __user*)buf, size, pos);
  20292. + } while (err == -EAGAIN || err == -EINTR);
  20293. + set_fs(oldfs);
  20294. + lockdep_on();
  20295. +
  20296. +#if 0
  20297. + if (err > 0)
  20298. + fsnotify_modify(file->f_dentry);
  20299. +#endif
  20300. +
  20301. + TraceErr(err);
  20302. + return err;
  20303. +}
  20304. +
  20305. +struct do_xino_fwrite_args {
  20306. + ssize_t *errp;
  20307. + writef_t func;
  20308. + struct file *file;
  20309. + void *buf;
  20310. + size_t size;
  20311. + loff_t *pos;
  20312. +};
  20313. +
  20314. +static void call_do_xino_fwrite(void *args)
  20315. +{
  20316. + struct do_xino_fwrite_args *a = args;
  20317. + *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
  20318. +}
  20319. +
  20320. +static ssize_t xino_fwrite(writef_t func, struct file *file, void *buf,
  20321. + size_t size, loff_t *pos)
  20322. +{
  20323. + ssize_t err;
  20324. +
  20325. + LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
  20326. + DLNPair(file->f_dentry), (unsigned long)size, *pos);
  20327. +
  20328. + // signal block and no wkq?
  20329. + /*
  20330. + * it breaks RLIMIT_FSIZE and normal user's limit,
  20331. + * users should care about quota and real 'filesystem full.'
  20332. + */
  20333. + if (!is_au_wkq(current)) {
  20334. + struct do_xino_fwrite_args args = {
  20335. + .errp = &err,
  20336. + .func = func,
  20337. + .file = file,
  20338. + .buf = buf,
  20339. + .size = size,
  20340. + .pos = pos
  20341. + };
  20342. + au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
  20343. + } else
  20344. + err = do_xino_fwrite(func, file, buf, size, pos);
  20345. +
  20346. + TraceErr(err);
  20347. + return err;
  20348. +}
  20349. +
  20350. +/* ---------------------------------------------------------------------- */
  20351. +
  20352. +/*
  20353. + * write @ino to the xinofile for the specified branch{@sb, @bindex}
  20354. + * at the position of @_ino.
  20355. + * when @ino is zero, it is written to the xinofile and means no entry.
  20356. + */
  20357. +int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  20358. + struct xino *xino)
  20359. +{
  20360. + struct aufs_branch *br;
  20361. + loff_t pos;
  20362. + ssize_t sz;
  20363. +
  20364. + LKTRTrace("b%d, hi%lu, i%lu\n", bindex, h_ino, xino->ino);
  20365. + //DEBUG_ON(!xino->ino /* || !xino->h_gen */);
  20366. + //WARN_ON(bindex == 0 && h_ino == 31);
  20367. +
  20368. + if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
  20369. + return 0;
  20370. +
  20371. + br = stobr(sb, bindex);
  20372. + DEBUG_ON(!br || !br->br_xino);
  20373. + pos = h_ino * sizeof(*xino);
  20374. + sz = xino_fwrite(br->br_xino_write, br->br_xino, xino, sizeof(*xino),
  20375. + &pos);
  20376. + //if (LktrCond) sz = 1;
  20377. + if (sz == sizeof(*xino))
  20378. + return 0; /* success */
  20379. +
  20380. + IOErr("write failed (%ld)\n", (long)sz);
  20381. + return -EIO;
  20382. +}
  20383. +
  20384. +int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino)
  20385. +{
  20386. + struct xino xino = {
  20387. + .ino = 0
  20388. + };
  20389. + return xino_write(sb, bindex, h_ino, &xino);
  20390. +}
  20391. +
  20392. +// why is not atomic_long_inc_return defined?
  20393. +static DEFINE_SPINLOCK(alir_lock);
  20394. +static long atomic_long_inc_return(atomic_long_t *a)
  20395. +{
  20396. + long l;
  20397. +
  20398. + spin_lock(&alir_lock);
  20399. + atomic_long_inc(a);
  20400. + l = atomic_long_read(a);
  20401. + spin_unlock(&alir_lock);
  20402. + return l;
  20403. +}
  20404. +
  20405. +ino_t xino_new_ino(struct super_block *sb)
  20406. +{
  20407. + ino_t ino;
  20408. +
  20409. + TraceEnter();
  20410. + ino = atomic_long_inc_return(&stosi(sb)->si_xino);
  20411. + BUILD_BUG_ON(AUFS_FIRST_INO < AUFS_ROOT_INO);
  20412. + if (ino >= AUFS_ROOT_INO)
  20413. + return ino;
  20414. + else {
  20415. + atomic_long_dec(&stosi(sb)->si_xino);
  20416. + IOErr1("inode number overflow\n");
  20417. + return 0;
  20418. + }
  20419. +}
  20420. +
  20421. +/*
  20422. + * read @ino from xinofile for the specified branch{@sb, @bindex}
  20423. + * at the position of @h_ino.
  20424. + * if @ino does not exist and @do_new is true, get new one.
  20425. + */
  20426. +int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  20427. + struct xino *xino)
  20428. +{
  20429. + int err;
  20430. + struct aufs_branch *br;
  20431. + struct file *file;
  20432. + loff_t pos;
  20433. + ssize_t sz;
  20434. +
  20435. + LKTRTrace("b%d, hi%lu\n", bindex, h_ino);
  20436. +
  20437. + err = 0;
  20438. + xino->ino = 0;
  20439. + if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
  20440. + return 0; /* no ino */
  20441. +
  20442. + br = stobr(sb, bindex);
  20443. + file = br->br_xino;
  20444. + DEBUG_ON(!file);
  20445. + pos = h_ino * sizeof(*xino);
  20446. + if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xino))
  20447. + return 0; /* no ino */
  20448. +
  20449. + sz = xino_fread(br->br_xino_read, file, xino, sizeof(*xino), &pos);
  20450. + if (sz == sizeof(*xino))
  20451. + return 0; /* success */
  20452. +
  20453. + err = sz;
  20454. + if (unlikely(sz >= 0)) {
  20455. + err = -EIO;
  20456. + IOErr("xino read error (%ld)\n", (long)sz);
  20457. + }
  20458. +
  20459. + TraceErr(err);
  20460. + return err;
  20461. +}
  20462. +
  20463. +/* ---------------------------------------------------------------------- */
  20464. +
  20465. +struct file *xino_create(struct super_block *sb, char *fname, int silent,
  20466. + struct dentry *parent)
  20467. +{
  20468. + struct file *file;
  20469. + int err;
  20470. + struct dentry *hidden_parent;
  20471. + struct inode *hidden_dir;
  20472. + //const int udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
  20473. +
  20474. + LKTRTrace("%s\n", fname);
  20475. + //DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
  20476. +
  20477. + // LSM may detect it
  20478. + // use sio?
  20479. + file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
  20480. + S_IRUGO | S_IWUGO);
  20481. + //file = ERR_PTR(-1);
  20482. + if (IS_ERR(file)) {
  20483. + if (!silent)
  20484. + Err("open %s(%ld)\n", fname, PTR_ERR(file));
  20485. + return file;
  20486. + }
  20487. +#if 0
  20488. + if (unlikely(udba && parent))
  20489. + au_direval_dec(parent);
  20490. +#endif
  20491. +
  20492. + /* keep file count */
  20493. + hidden_parent = dget_parent(file->f_dentry);
  20494. + hidden_dir = hidden_parent->d_inode;
  20495. + hi_lock_parent(hidden_dir);
  20496. + err = vfsub_unlink(hidden_dir, file->f_dentry, /*dlgt*/0);
  20497. +#if 0
  20498. + if (unlikely(!err && udba && parent))
  20499. + au_direval_dec(parent);
  20500. +#endif
  20501. + i_unlock(hidden_dir);
  20502. + dput(hidden_parent);
  20503. + if (unlikely(err)) {
  20504. + if (!silent)
  20505. + Err("unlink %s(%d)\n", fname, err);
  20506. + goto out;
  20507. + }
  20508. + if (sb != file->f_dentry->d_sb)
  20509. + return file; /* success */
  20510. +
  20511. + if (!silent)
  20512. + Err("%s must be outside\n", fname);
  20513. + err = -EINVAL;
  20514. +
  20515. + out:
  20516. + fput(file);
  20517. + file = ERR_PTR(err);
  20518. + return file;
  20519. +}
  20520. +
  20521. +/*
  20522. + * find another branch who is on the same filesystem of the specified
  20523. + * branch{@btgt}. search until @bend.
  20524. + */
  20525. +static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
  20526. + aufs_bindex_t bend)
  20527. +{
  20528. + aufs_bindex_t bindex;
  20529. + struct super_block *tgt_sb = sbr_sb(sb, btgt);
  20530. +
  20531. + for (bindex = 0; bindex <= bend; bindex++)
  20532. + if (unlikely(btgt != bindex && tgt_sb == sbr_sb(sb, bindex)))
  20533. + return bindex;
  20534. + return -1;
  20535. +}
  20536. +
  20537. +/*
  20538. + * create a new xinofile at the same place/path as @base_file.
  20539. + */
  20540. +static struct file *xino_create2(struct file *base_file)
  20541. +{
  20542. + struct file *file;
  20543. + int err;
  20544. + struct dentry *base, *dentry, *parent;
  20545. + struct inode *dir;
  20546. + struct qstr *name;
  20547. + struct lkup_args lkup = {
  20548. + .nfsmnt = NULL,
  20549. + .dlgt = 0
  20550. + };
  20551. +
  20552. + base = base_file->f_dentry;
  20553. + LKTRTrace("%.*s\n", DLNPair(base));
  20554. + parent = dget_parent(base);
  20555. + dir = parent->d_inode;
  20556. + IMustLock(dir);
  20557. +
  20558. + file = ERR_PTR(-EINVAL);
  20559. + if (unlikely(au_is_nfs(parent->d_sb)))
  20560. + goto out;
  20561. +
  20562. + // do not superio, nor NFS.
  20563. + name = &base->d_name;
  20564. + dentry = lkup_one(name->name, parent, name->len, &lkup);
  20565. + //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
  20566. + if (IS_ERR(dentry)) {
  20567. + file = (void*)dentry;
  20568. + Err("%.*s lookup err %ld\n", LNPair(name), PTR_ERR(dentry));
  20569. + goto out;
  20570. + }
  20571. + err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, /*dlgt*/0);
  20572. + //if (LktrCond) {vfs_unlink(dir, dentry); err = -1;}
  20573. + if (unlikely(err)) {
  20574. + file = ERR_PTR(err);
  20575. + Err("%.*s create err %d\n", LNPair(name), err);
  20576. + goto out_dput;
  20577. + }
  20578. + file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
  20579. + O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
  20580. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20581. + if (IS_ERR(file)) {
  20582. + Err("%.*s open err %ld\n", LNPair(name), PTR_ERR(file));
  20583. + goto out_dput;
  20584. + }
  20585. + err = vfsub_unlink(dir, dentry, /*dlgt*/0);
  20586. + //if (LktrCond) err = -1;
  20587. + if (!err)
  20588. + goto out_dput; /* success */
  20589. +
  20590. + Err("%.*s unlink err %d\n", LNPair(name), err);
  20591. + fput(file);
  20592. + file = ERR_PTR(err);
  20593. +
  20594. + out_dput:
  20595. + dput(dentry);
  20596. + out:
  20597. + dput(parent);
  20598. + TraceErrPtr(file);
  20599. + return file;
  20600. +}
  20601. +
  20602. +/*
  20603. + * initialize the xinofile for the specified branch{@sb, @bindex}
  20604. + * at the place/path where @base_file indicates.
  20605. + * test whether another branch is on the same filesystem or not,
  20606. + * if @do_test is true.
  20607. + */
  20608. +int xino_init(struct super_block *sb, aufs_bindex_t bindex,
  20609. + struct file *base_file, int do_test)
  20610. +{
  20611. + int err;
  20612. + struct aufs_branch *br;
  20613. + aufs_bindex_t bshared, bend;
  20614. + struct file *file;
  20615. + struct inode *inode, *hidden_inode;
  20616. + struct xino xino;
  20617. +
  20618. + LKTRTrace("b%d, base_file %p, do_test %d\n",
  20619. + bindex, base_file, do_test);
  20620. + SiMustWriteLock(sb);
  20621. + DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
  20622. + br = stobr(sb, bindex);
  20623. + DEBUG_ON(br->br_xino);
  20624. +
  20625. + file = NULL;
  20626. + bshared = -1;
  20627. + bend = sbend(sb);
  20628. + if (do_test)
  20629. + bshared = is_sb_shared(sb, bindex, bend);
  20630. + if (unlikely(bshared >= 0)) {
  20631. + struct aufs_branch *shared_br = stobr(sb, bshared);
  20632. + if (shared_br->br_xino) {
  20633. + file = shared_br->br_xino;
  20634. + get_file(file);
  20635. + }
  20636. + }
  20637. +
  20638. + if (!file) {
  20639. + struct dentry *parent = dget_parent(base_file->f_dentry);
  20640. + struct inode *dir = parent->d_inode;
  20641. +
  20642. + hi_lock_parent(dir);
  20643. + file = xino_create2(base_file);
  20644. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20645. + i_unlock(dir);
  20646. + dput(parent);
  20647. + err = PTR_ERR(file);
  20648. + if (IS_ERR(file))
  20649. + goto out;
  20650. + }
  20651. + br->br_xino_read = find_readf(file);
  20652. + err = PTR_ERR(br->br_xino_read);
  20653. + if (IS_ERR(br->br_xino_read))
  20654. + goto out_put;
  20655. + br->br_xino_write = find_writef(file);
  20656. + err = PTR_ERR(br->br_xino_write);
  20657. + if (IS_ERR(br->br_xino_write))
  20658. + goto out_put;
  20659. + br->br_xino = file;
  20660. +
  20661. + inode = sb->s_root->d_inode;
  20662. + hidden_inode = au_h_iptr_i(inode, bindex);
  20663. + xino.ino = inode->i_ino;
  20664. + //xino.h_gen = hidden_inode->i_generation;
  20665. + //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
  20666. + err = xino_write(sb, bindex, hidden_inode->i_ino, &xino);
  20667. + //if (LktrCond) err = -1;
  20668. + if (!err)
  20669. + return 0; /* success */
  20670. +
  20671. + br->br_xino = NULL;
  20672. +
  20673. + out_put:
  20674. + fput(file);
  20675. + out:
  20676. + TraceErr(err);
  20677. + return err;
  20678. +}
  20679. +
  20680. +/*
  20681. + * set xino mount option.
  20682. + */
  20683. +int xino_set(struct super_block *sb, struct opt_xino *xino, int remount)
  20684. +{
  20685. + int err, sparse;
  20686. + aufs_bindex_t bindex, bend;
  20687. + struct aufs_branch *br;
  20688. + struct dentry *parent;
  20689. + struct qstr *name;
  20690. + struct file *cur_xino;
  20691. + struct inode *dir;
  20692. +
  20693. + LKTRTrace("%s\n", xino->path);
  20694. +
  20695. + err = 0;
  20696. + name = &xino->file->f_dentry->d_name;
  20697. + parent = dget_parent(xino->file->f_dentry);
  20698. + dir = parent->d_inode;
  20699. + cur_xino = stobr(sb, 0)->br_xino;
  20700. + if (remount
  20701. + && cur_xino
  20702. + && cur_xino->f_dentry->d_parent == parent
  20703. + && name->len == cur_xino->f_dentry->d_name.len
  20704. + && !memcmp(name->name, cur_xino->f_dentry->d_name.name, name->len))
  20705. + goto out;
  20706. +
  20707. + au_flag_set(sb, AuFlag_XINO);
  20708. + bend = sbend(sb);
  20709. + for (bindex = bend; bindex >= 0; bindex--) {
  20710. + br = stobr(sb, bindex);
  20711. + if (unlikely(br->br_xino && file_count(br->br_xino) > 1)) {
  20712. + fput(br->br_xino);
  20713. + br->br_xino = NULL;
  20714. + }
  20715. + }
  20716. +
  20717. + for (bindex = 0; bindex <= bend; bindex++) {
  20718. + struct file *file;
  20719. + struct inode *inode;
  20720. +
  20721. + br = stobr(sb, bindex);
  20722. + if (unlikely(!br->br_xino))
  20723. + continue;
  20724. +
  20725. + DEBUG_ON(file_count(br->br_xino) != 1);
  20726. + hi_lock_parent(dir);
  20727. + file = xino_create2(xino->file);
  20728. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20729. + err = PTR_ERR(file);
  20730. + if (IS_ERR(file)) {
  20731. + i_unlock(dir);
  20732. + break;
  20733. + }
  20734. + inode = br->br_xino->f_dentry->d_inode;
  20735. + err = au_copy_file(file, br->br_xino, i_size_read(inode), sb,
  20736. + &sparse);
  20737. + //if (LktrCond) err = -1;
  20738. + i_unlock(dir);
  20739. + if (unlikely(err)) {
  20740. + fput(file);
  20741. + break;
  20742. + }
  20743. + fput(br->br_xino);
  20744. + br->br_xino = file;
  20745. + br->br_xino_read = find_readf(file);
  20746. + DEBUG_ON(IS_ERR(br->br_xino_read));
  20747. + br->br_xino_write = find_writef(file);
  20748. + DEBUG_ON(IS_ERR(br->br_xino_write));
  20749. + }
  20750. +
  20751. + for (bindex = 0; bindex <= bend; bindex++)
  20752. + if (unlikely(!stobr(sb, bindex)->br_xino)) {
  20753. + err = xino_init(sb, bindex, xino->file, /*do_test*/1);
  20754. + //if (LktrCond) {fput(stobr(sb, bindex)->br_xino);
  20755. + //stobr(sb, bindex)->br_xino = NULL; err = -1;}
  20756. + if (!err)
  20757. + continue;
  20758. + IOErr("creating xino for branch %d(%d), "
  20759. + "forcing noxino\n", bindex, err);
  20760. + err = -EIO;
  20761. + break;
  20762. + }
  20763. + out:
  20764. + dput(parent);
  20765. + if (!err)
  20766. + au_flag_set(sb, AuFlag_XINO);
  20767. + else
  20768. + au_flag_clr(sb, AuFlag_XINO);
  20769. + TraceErr(err);
  20770. + return err;
  20771. +}
  20772. +
  20773. +/*
  20774. + * clear xino mount option
  20775. + */
  20776. +int xino_clr(struct super_block *sb)
  20777. +{
  20778. + aufs_bindex_t bindex, bend;
  20779. +
  20780. + TraceEnter();
  20781. + SiMustWriteLock(sb);
  20782. +
  20783. + bend = sbend(sb);
  20784. + for (bindex = 0; bindex <= bend; bindex++) {
  20785. + struct aufs_branch *br;
  20786. + br = stobr(sb, bindex);
  20787. + if (br->br_xino) {
  20788. + fput(br->br_xino);
  20789. + br->br_xino = NULL;
  20790. + }
  20791. + }
  20792. +
  20793. + //todo: need to make iunique() to return the larger inode number
  20794. +
  20795. + au_flag_clr(sb, AuFlag_XINO);
  20796. + return 0;
  20797. +}
  20798. +
  20799. +/*
  20800. + * create a xinofile at the default place/path.
  20801. + */
  20802. +struct file *xino_def(struct super_block *sb)
  20803. +{
  20804. + struct file *file;
  20805. + aufs_bindex_t bend, bindex, bwr;
  20806. + char *page, *p;
  20807. +
  20808. + bend = sbend(sb);
  20809. + bwr = -1;
  20810. + for (bindex = 0; bindex <= bend; bindex++)
  20811. + if (br_writable(sbr_perm(sb, bindex))
  20812. + && !au_is_nfs(au_h_dptr_i(sb->s_root, bindex)->d_sb)) {
  20813. + bwr = bindex;
  20814. + break;
  20815. + }
  20816. +
  20817. + if (bwr != -1) {
  20818. + // todo: rewrite with lkup_one()
  20819. + file = ERR_PTR(-ENOMEM);
  20820. + page = __getname();
  20821. + //if (LktrCond) {__putname(page); page = NULL;}
  20822. + if (unlikely(!page))
  20823. + goto out;
  20824. + p = d_path(au_h_dptr_i(sb->s_root, bwr), sbr_mnt(sb, bwr), page,
  20825. + PATH_MAX - sizeof(AUFS_XINO_FNAME));
  20826. + //if (LktrCond) p = ERR_PTR(-1);
  20827. + file = (void*)p;
  20828. + if (p && !IS_ERR(p)) {
  20829. + strcat(p, "/" AUFS_XINO_FNAME);
  20830. + LKTRTrace("%s\n", p);
  20831. + file = xino_create(sb, p, /*silent*/0, sb->s_root);
  20832. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20833. + }
  20834. + __putname(page);
  20835. + } else {
  20836. + file = xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
  20837. + /*parent*/NULL);
  20838. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20839. + }
  20840. +
  20841. + out:
  20842. + TraceErrPtr(file);
  20843. + return file;
  20844. +}
  20845. diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/Makefile linux-2.6.22.1/fs/squashfs/Makefile
  20846. --- linux-2.6.22.1.oorig/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100
  20847. +++ linux-2.6.22.1/fs/squashfs/Makefile 2007-07-24 14:17:46.000000000 +0200
  20848. @@ -0,0 +1,7 @@
  20849. +#
  20850. +# Makefile for the linux squashfs routines.
  20851. +#
  20852. +
  20853. +obj-$(CONFIG_SQUASHFS) += squashfs.o
  20854. +squashfs-y += inode.o
  20855. +squashfs-y += squashfs2_0.o
  20856. diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/inode.c linux-2.6.22.1/fs/squashfs/inode.c
  20857. --- linux-2.6.22.1.oorig/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100
  20858. +++ linux-2.6.22.1/fs/squashfs/inode.c 2007-07-24 14:17:46.000000000 +0200
  20859. @@ -0,0 +1,2329 @@
  20860. +/*
  20861. + * Squashfs - a compressed read only filesystem for Linux
  20862. + *
  20863. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  20864. + * Phillip Lougher <phillip@lougher.org.uk>
  20865. + *
  20866. + * This program is free software; you can redistribute it and/or
  20867. + * modify it under the terms of the GNU General Public License
  20868. + * as published by the Free Software Foundation; either version 2,
  20869. + * or (at your option) any later version.
  20870. + *
  20871. + * This program is distributed in the hope that it will be useful,
  20872. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20873. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20874. + * GNU General Public License for more details.
  20875. + *
  20876. + * You should have received a copy of the GNU General Public License
  20877. + * along with this program; if not, write to the Free Software
  20878. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20879. + *
  20880. + * inode.c
  20881. + */
  20882. +
  20883. +#include <linux/squashfs_fs.h>
  20884. +#include <linux/module.h>
  20885. +#include <linux/zlib.h>
  20886. +#include <linux/fs.h>
  20887. +#include <linux/squashfs_fs_sb.h>
  20888. +#include <linux/squashfs_fs_i.h>
  20889. +#include <linux/buffer_head.h>
  20890. +#include <linux/vfs.h>
  20891. +#include <linux/vmalloc.h>
  20892. +#include <linux/smp_lock.h>
  20893. +
  20894. +#include "squashfs.h"
  20895. +
  20896. +static void vfs_read_inode(struct inode *i);
  20897. +static struct dentry *squashfs_get_parent(struct dentry *child);
  20898. +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);
  20899. +static int squashfs_statfs(struct dentry *, struct kstatfs *);
  20900. +static int squashfs_symlink_readpage(struct file *file, struct page *page);
  20901. +static long long read_blocklist(struct inode *inode, int index,
  20902. + int readahead_blks, char *block_list,
  20903. + unsigned short **block_p, unsigned int *bsize);
  20904. +static int squashfs_readpage(struct file *file, struct page *page);
  20905. +static int squashfs_readpage4K(struct file *file, struct page *page);
  20906. +static int squashfs_readdir(struct file *, void *, filldir_t);
  20907. +static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
  20908. + struct nameidata *);
  20909. +static int squashfs_remount(struct super_block *s, int *flags, char *data);
  20910. +static void squashfs_put_super(struct super_block *);
  20911. +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,
  20912. + struct vfsmount *);
  20913. +static struct inode *squashfs_alloc_inode(struct super_block *sb);
  20914. +static void squashfs_destroy_inode(struct inode *inode);
  20915. +static int init_inodecache(void);
  20916. +static void destroy_inodecache(void);
  20917. +
  20918. +static struct file_system_type squashfs_fs_type = {
  20919. + .owner = THIS_MODULE,
  20920. + .name = "squashfs",
  20921. + .get_sb = squashfs_get_sb,
  20922. + .kill_sb = kill_block_super,
  20923. + .fs_flags = FS_REQUIRES_DEV
  20924. +};
  20925. +
  20926. +static const unsigned char squashfs_filetype_table[] = {
  20927. + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
  20928. +};
  20929. +
  20930. +static struct super_operations squashfs_super_ops = {
  20931. + .alloc_inode = squashfs_alloc_inode,
  20932. + .destroy_inode = squashfs_destroy_inode,
  20933. + .statfs = squashfs_statfs,
  20934. + .put_super = squashfs_put_super,
  20935. + .remount_fs = squashfs_remount
  20936. +};
  20937. +
  20938. +static struct super_operations squashfs_export_super_ops = {
  20939. + .alloc_inode = squashfs_alloc_inode,
  20940. + .destroy_inode = squashfs_destroy_inode,
  20941. + .statfs = squashfs_statfs,
  20942. + .put_super = squashfs_put_super,
  20943. + .read_inode = vfs_read_inode
  20944. +};
  20945. +
  20946. +static struct export_operations squashfs_export_ops = {
  20947. + .get_parent = squashfs_get_parent
  20948. +};
  20949. +
  20950. +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {
  20951. + .readpage = squashfs_symlink_readpage
  20952. +};
  20953. +
  20954. +SQSH_EXTERN const struct address_space_operations squashfs_aops = {
  20955. + .readpage = squashfs_readpage
  20956. +};
  20957. +
  20958. +SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {
  20959. + .readpage = squashfs_readpage4K
  20960. +};
  20961. +
  20962. +static const struct file_operations squashfs_dir_ops = {
  20963. + .read = generic_read_dir,
  20964. + .readdir = squashfs_readdir
  20965. +};
  20966. +
  20967. +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
  20968. + .lookup = squashfs_lookup
  20969. +};
  20970. +
  20971. +
  20972. +static struct buffer_head *get_block_length(struct super_block *s,
  20973. + int *cur_index, int *offset, int *c_byte)
  20974. +{
  20975. + struct squashfs_sb_info *msblk = s->s_fs_info;
  20976. + unsigned short temp;
  20977. + struct buffer_head *bh;
  20978. +
  20979. + if (!(bh = sb_bread(s, *cur_index)))
  20980. + goto out;
  20981. +
  20982. + if (msblk->devblksize - *offset == 1) {
  20983. + if (msblk->swap)
  20984. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  20985. + (bh->b_data + *offset));
  20986. + else
  20987. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  20988. + (bh->b_data + *offset));
  20989. + brelse(bh);
  20990. + if (!(bh = sb_bread(s, ++(*cur_index))))
  20991. + goto out;
  20992. + if (msblk->swap)
  20993. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  20994. + bh->b_data);
  20995. + else
  20996. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  20997. + bh->b_data);
  20998. + *c_byte = temp;
  20999. + *offset = 1;
  21000. + } else {
  21001. + if (msblk->swap) {
  21002. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  21003. + (bh->b_data + *offset));
  21004. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  21005. + (bh->b_data + *offset + 1));
  21006. + } else {
  21007. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  21008. + (bh->b_data + *offset));
  21009. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  21010. + (bh->b_data + *offset + 1));
  21011. + }
  21012. + *c_byte = temp;
  21013. + *offset += 2;
  21014. + }
  21015. +
  21016. + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
  21017. + if (*offset == msblk->devblksize) {
  21018. + brelse(bh);
  21019. + if (!(bh = sb_bread(s, ++(*cur_index))))
  21020. + goto out;
  21021. + *offset = 0;
  21022. + }
  21023. + if (*((unsigned char *) (bh->b_data + *offset)) !=
  21024. + SQUASHFS_MARKER_BYTE) {
  21025. + ERROR("Metadata block marker corrupt @ %x\n",
  21026. + *cur_index);
  21027. + brelse(bh);
  21028. + goto out;
  21029. + }
  21030. + (*offset)++;
  21031. + }
  21032. + return bh;
  21033. +
  21034. +out:
  21035. + return NULL;
  21036. +}
  21037. +
  21038. +
  21039. +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
  21040. + long long index, unsigned int length,
  21041. + long long *next_index, int srclength)
  21042. +{
  21043. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21044. + struct squashfs_super_block *sblk = &msblk->sblk;
  21045. + struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
  21046. + msblk->devblksize_log2) + 2];
  21047. + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
  21048. + unsigned int cur_index = index >> msblk->devblksize_log2;
  21049. + int bytes, avail_bytes, b = 0, k = 0;
  21050. + unsigned int compressed;
  21051. + unsigned int c_byte = length;
  21052. +
  21053. + if (c_byte) {
  21054. + bytes = msblk->devblksize - offset;
  21055. + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
  21056. + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
  21057. +
  21058. + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
  21059. + ? "" : "un", (unsigned int) c_byte, srclength);
  21060. +
  21061. + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
  21062. + goto read_failure;
  21063. +
  21064. + if (!(bh[0] = sb_getblk(s, cur_index)))
  21065. + goto block_release;
  21066. +
  21067. + for (b = 1; bytes < c_byte; b++) {
  21068. + if (!(bh[b] = sb_getblk(s, ++cur_index)))
  21069. + goto block_release;
  21070. + bytes += msblk->devblksize;
  21071. + }
  21072. + ll_rw_block(READ, b, bh);
  21073. + } else {
  21074. + if (index < 0 || (index + 2) > sblk->bytes_used)
  21075. + goto read_failure;
  21076. +
  21077. + if (!(bh[0] = get_block_length(s, &cur_index, &offset,
  21078. + &c_byte)))
  21079. + goto read_failure;
  21080. +
  21081. + bytes = msblk->devblksize - offset;
  21082. + compressed = SQUASHFS_COMPRESSED(c_byte);
  21083. + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  21084. +
  21085. + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
  21086. + ? "" : "un", (unsigned int) c_byte);
  21087. +
  21088. + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
  21089. + goto read_failure;
  21090. +
  21091. + for (b = 1; bytes < c_byte; b++) {
  21092. + if (!(bh[b] = sb_getblk(s, ++cur_index)))
  21093. + goto block_release;
  21094. + bytes += msblk->devblksize;
  21095. + }
  21096. + ll_rw_block(READ, b - 1, bh + 1);
  21097. + }
  21098. +
  21099. + if (compressed) {
  21100. + int zlib_err = 0;
  21101. +
  21102. + /*
  21103. + * uncompress block
  21104. + */
  21105. +
  21106. + mutex_lock(&msblk->read_data_mutex);
  21107. +
  21108. + msblk->stream.next_out = buffer;
  21109. + msblk->stream.avail_out = srclength;
  21110. +
  21111. + for (bytes = 0; k < b; k++) {
  21112. + avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
  21113. + msblk->devblksize - offset :
  21114. + c_byte - bytes;
  21115. + wait_on_buffer(bh[k]);
  21116. + if (!buffer_uptodate(bh[k]))
  21117. + goto release_mutex;
  21118. +
  21119. + msblk->stream.next_in = bh[k]->b_data + offset;
  21120. + msblk->stream.avail_in = avail_bytes;
  21121. +
  21122. + if (k == 0) {
  21123. + zlib_err = zlib_inflateInit(&msblk->stream);
  21124. + if (zlib_err != Z_OK) {
  21125. + ERROR("zlib_inflateInit returned unexpected result 0x%x, srclength %d\n",
  21126. + zlib_err, srclength);
  21127. + goto release_mutex;
  21128. + }
  21129. +
  21130. + if (avail_bytes == 0) {
  21131. + offset = 0;
  21132. + brelse(bh[k]);
  21133. + continue;
  21134. + }
  21135. + }
  21136. +
  21137. + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
  21138. + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) {
  21139. + ERROR("zlib_inflate returned unexpected result 0x%x, srclength %d, avail_in %d, avail_out %d\n",
  21140. + zlib_err, srclength, msblk->stream.avail_in, msblk->stream.avail_out);
  21141. + goto release_mutex;
  21142. + }
  21143. +
  21144. + bytes += avail_bytes;
  21145. + offset = 0;
  21146. + brelse(bh[k]);
  21147. + }
  21148. +
  21149. + if (zlib_err != Z_STREAM_END)
  21150. + goto release_mutex;
  21151. +
  21152. + zlib_err = zlib_inflateEnd(&msblk->stream);
  21153. + if (zlib_err != Z_OK) {
  21154. + ERROR("zlib_inflateEnd returned unexpected result 0x%x, srclength %d\n",
  21155. + zlib_err, srclength);
  21156. + goto release_mutex;
  21157. + }
  21158. + bytes = msblk->stream.total_out;
  21159. + mutex_unlock(&msblk->read_data_mutex);
  21160. + } else {
  21161. + int i;
  21162. +
  21163. + for(i = 0; i < b; i++) {
  21164. + wait_on_buffer(bh[i]);
  21165. + if(!buffer_uptodate(bh[i]))
  21166. + goto block_release;
  21167. + }
  21168. +
  21169. + for (bytes = 0; k < b; k++) {
  21170. + avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
  21171. + msblk->devblksize - offset :
  21172. + c_byte - bytes;
  21173. + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);
  21174. + bytes += avail_bytes;
  21175. + offset = 0;
  21176. + brelse(bh[k]);
  21177. + }
  21178. + }
  21179. +
  21180. + if (next_index)
  21181. + *next_index = index + c_byte + (length ? 0 :
  21182. + (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
  21183. + ? 3 : 2));
  21184. + return bytes;
  21185. +
  21186. +release_mutex:
  21187. + mutex_unlock(&msblk->read_data_mutex);
  21188. +
  21189. +block_release:
  21190. + for (; k < b; k++)
  21191. + brelse(bh[k]);
  21192. +
  21193. +read_failure:
  21194. + ERROR("sb_bread failed reading block 0x%x\n", cur_index);
  21195. + return 0;
  21196. +}
  21197. +
  21198. +
  21199. +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
  21200. + long long block, unsigned int offset,
  21201. + int length, long long *next_block,
  21202. + unsigned int *next_offset)
  21203. +{
  21204. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21205. + int n, i, bytes, return_length = length;
  21206. + long long next_index;
  21207. +
  21208. + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
  21209. +
  21210. + while ( 1 ) {
  21211. + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
  21212. + if (msblk->block_cache[i].block == block)
  21213. + break;
  21214. +
  21215. + mutex_lock(&msblk->block_cache_mutex);
  21216. +
  21217. + if (i == SQUASHFS_CACHED_BLKS) {
  21218. + /* read inode header block */
  21219. + for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
  21220. + n ; n --, i = (i + 1) %
  21221. + SQUASHFS_CACHED_BLKS)
  21222. + if (msblk->block_cache[i].block !=
  21223. + SQUASHFS_USED_BLK)
  21224. + break;
  21225. +
  21226. + if (n == 0) {
  21227. + wait_queue_t wait;
  21228. +
  21229. + init_waitqueue_entry(&wait, current);
  21230. + add_wait_queue(&msblk->waitq, &wait);
  21231. + set_current_state(TASK_UNINTERRUPTIBLE);
  21232. + mutex_unlock(&msblk->block_cache_mutex);
  21233. + schedule();
  21234. + set_current_state(TASK_RUNNING);
  21235. + remove_wait_queue(&msblk->waitq, &wait);
  21236. + continue;
  21237. + }
  21238. + msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
  21239. +
  21240. + if (msblk->block_cache[i].block ==
  21241. + SQUASHFS_INVALID_BLK) {
  21242. + if (!(msblk->block_cache[i].data =
  21243. + kmalloc(SQUASHFS_METADATA_SIZE,
  21244. + GFP_KERNEL))) {
  21245. + ERROR("Failed to allocate cache"
  21246. + "block\n");
  21247. + mutex_unlock(&msblk->block_cache_mutex);
  21248. + goto out;
  21249. + }
  21250. + }
  21251. +
  21252. + msblk->block_cache[i].block = SQUASHFS_USED_BLK;
  21253. + mutex_unlock(&msblk->block_cache_mutex);
  21254. +
  21255. + msblk->block_cache[i].length = squashfs_read_data(s,
  21256. + msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);
  21257. + if (msblk->block_cache[i].length == 0) {
  21258. + ERROR("Unable to read cache block [%llx:%x]\n",
  21259. + block, offset);
  21260. + mutex_lock(&msblk->block_cache_mutex);
  21261. + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
  21262. + kfree(msblk->block_cache[i].data);
  21263. + wake_up(&msblk->waitq);
  21264. + mutex_unlock(&msblk->block_cache_mutex);
  21265. + goto out;
  21266. + }
  21267. +
  21268. + mutex_lock(&msblk->block_cache_mutex);
  21269. + wake_up(&msblk->waitq);
  21270. + msblk->block_cache[i].block = block;
  21271. + msblk->block_cache[i].next_index = next_index;
  21272. + TRACE("Read cache block [%llx:%x]\n", block, offset);
  21273. + }
  21274. +
  21275. + if (msblk->block_cache[i].block != block) {
  21276. + mutex_unlock(&msblk->block_cache_mutex);
  21277. + continue;
  21278. + }
  21279. +
  21280. + bytes = msblk->block_cache[i].length - offset;
  21281. +
  21282. + if (bytes < 1) {
  21283. + mutex_unlock(&msblk->block_cache_mutex);
  21284. + goto out;
  21285. + } else if (bytes >= length) {
  21286. + if (buffer)
  21287. + memcpy(buffer, msblk->block_cache[i].data +
  21288. + offset, length);
  21289. + if (msblk->block_cache[i].length - offset == length) {
  21290. + *next_block = msblk->block_cache[i].next_index;
  21291. + *next_offset = 0;
  21292. + } else {
  21293. + *next_block = block;
  21294. + *next_offset = offset + length;
  21295. + }
  21296. + mutex_unlock(&msblk->block_cache_mutex);
  21297. + goto finish;
  21298. + } else {
  21299. + if (buffer) {
  21300. + memcpy(buffer, msblk->block_cache[i].data +
  21301. + offset, bytes);
  21302. + buffer += bytes;
  21303. + }
  21304. + block = msblk->block_cache[i].next_index;
  21305. + mutex_unlock(&msblk->block_cache_mutex);
  21306. + length -= bytes;
  21307. + offset = 0;
  21308. + }
  21309. + }
  21310. +
  21311. +finish:
  21312. + return return_length;
  21313. +out:
  21314. + return 0;
  21315. +}
  21316. +
  21317. +
  21318. +static int get_fragment_location(struct super_block *s, unsigned int fragment,
  21319. + long long *fragment_start_block,
  21320. + unsigned int *fragment_size)
  21321. +{
  21322. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21323. + long long start_block =
  21324. + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
  21325. + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
  21326. + struct squashfs_fragment_entry fragment_entry;
  21327. +
  21328. + if (msblk->swap) {
  21329. + struct squashfs_fragment_entry sfragment_entry;
  21330. +
  21331. + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
  21332. + start_block, offset,
  21333. + sizeof(sfragment_entry), &start_block,
  21334. + &offset))
  21335. + goto out;
  21336. + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
  21337. + } else
  21338. + if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
  21339. + start_block, offset,
  21340. + sizeof(fragment_entry), &start_block,
  21341. + &offset))
  21342. + goto out;
  21343. +
  21344. + *fragment_start_block = fragment_entry.start_block;
  21345. + *fragment_size = fragment_entry.size;
  21346. +
  21347. + return 1;
  21348. +
  21349. +out:
  21350. + return 0;
  21351. +}
  21352. +
  21353. +
  21354. +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
  21355. + squashfs_fragment_cache *fragment)
  21356. +{
  21357. + mutex_lock(&msblk->fragment_mutex);
  21358. + fragment->locked --;
  21359. + wake_up(&msblk->fragment_wait_queue);
  21360. + mutex_unlock(&msblk->fragment_mutex);
  21361. +}
  21362. +
  21363. +
  21364. +SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
  21365. + *s, long long start_block,
  21366. + int length)
  21367. +{
  21368. + int i, n;
  21369. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21370. + struct squashfs_super_block *sblk = &msblk->sblk;
  21371. +
  21372. + while ( 1 ) {
  21373. + mutex_lock(&msblk->fragment_mutex);
  21374. +
  21375. + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
  21376. + msblk->fragment[i].block != start_block; i++);
  21377. +
  21378. + if (i == SQUASHFS_CACHED_FRAGMENTS) {
  21379. + for (i = msblk->next_fragment, n =
  21380. + SQUASHFS_CACHED_FRAGMENTS; n &&
  21381. + msblk->fragment[i].locked; n--, i = (i + 1) %
  21382. + SQUASHFS_CACHED_FRAGMENTS);
  21383. +
  21384. + if (n == 0) {
  21385. + wait_queue_t wait;
  21386. +
  21387. + init_waitqueue_entry(&wait, current);
  21388. + add_wait_queue(&msblk->fragment_wait_queue,
  21389. + &wait);
  21390. + set_current_state(TASK_UNINTERRUPTIBLE);
  21391. + mutex_unlock(&msblk->fragment_mutex);
  21392. + schedule();
  21393. + set_current_state(TASK_RUNNING);
  21394. + remove_wait_queue(&msblk->fragment_wait_queue,
  21395. + &wait);
  21396. + continue;
  21397. + }
  21398. + msblk->next_fragment = (msblk->next_fragment + 1) %
  21399. + SQUASHFS_CACHED_FRAGMENTS;
  21400. +
  21401. + if (msblk->fragment[i].data == NULL)
  21402. + if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
  21403. + (SQUASHFS_FILE_MAX_SIZE))) {
  21404. + ERROR("Failed to allocate fragment "
  21405. + "cache block\n");
  21406. + mutex_unlock(&msblk->fragment_mutex);
  21407. + goto out;
  21408. + }
  21409. +
  21410. + msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
  21411. + msblk->fragment[i].locked = 1;
  21412. + mutex_unlock(&msblk->fragment_mutex);
  21413. +
  21414. + if (!(msblk->fragment[i].length = squashfs_read_data(s,
  21415. + msblk->fragment[i].data,
  21416. + start_block, length, NULL, sblk->block_size))) {
  21417. + ERROR("Unable to read fragment cache block "
  21418. + "[%llx]\n", start_block);
  21419. + msblk->fragment[i].locked = 0;
  21420. + smp_mb();
  21421. + goto out;
  21422. + }
  21423. +
  21424. + mutex_lock(&msblk->fragment_mutex);
  21425. + msblk->fragment[i].block = start_block;
  21426. + TRACE("New fragment %d, start block %lld, locked %d\n",
  21427. + i, msblk->fragment[i].block,
  21428. + msblk->fragment[i].locked);
  21429. + mutex_unlock(&msblk->fragment_mutex);
  21430. + break;
  21431. + }
  21432. +
  21433. + msblk->fragment[i].locked++;
  21434. + mutex_unlock(&msblk->fragment_mutex);
  21435. + TRACE("Got fragment %d, start block %lld, locked %d\n", i,
  21436. + msblk->fragment[i].block,
  21437. + msblk->fragment[i].locked);
  21438. + break;
  21439. + }
  21440. +
  21441. + return &msblk->fragment[i];
  21442. +
  21443. +out:
  21444. + return NULL;
  21445. +}
  21446. +
  21447. +
  21448. +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
  21449. + struct squashfs_base_inode_header *inodeb)
  21450. +{
  21451. + i->i_ino = inodeb->inode_number;
  21452. + i->i_mtime.tv_sec = inodeb->mtime;
  21453. + i->i_atime.tv_sec = inodeb->mtime;
  21454. + i->i_ctime.tv_sec = inodeb->mtime;
  21455. + i->i_uid = msblk->uid[inodeb->uid];
  21456. + i->i_mode = inodeb->mode;
  21457. + i->i_size = 0;
  21458. + if (inodeb->guid == SQUASHFS_GUIDS)
  21459. + i->i_gid = i->i_uid;
  21460. + else
  21461. + i->i_gid = msblk->guid[inodeb->guid];
  21462. +}
  21463. +
  21464. +
  21465. +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)
  21466. +{
  21467. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21468. + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];
  21469. + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
  21470. + squashfs_inode_t inode;
  21471. +
  21472. + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
  21473. +
  21474. + if (msblk->swap) {
  21475. + squashfs_inode_t sinode;
  21476. +
  21477. + if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,
  21478. + sizeof(sinode), &start, &offset))
  21479. + goto out;
  21480. + SQUASHFS_SWAP_INODE_T((&inode), &sinode);
  21481. + } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,
  21482. + sizeof(inode), &start, &offset))
  21483. + goto out;
  21484. +
  21485. + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);
  21486. +
  21487. + return inode;
  21488. +
  21489. +out:
  21490. + return SQUASHFS_INVALID_BLK;
  21491. +}
  21492. +
  21493. +
  21494. +static void vfs_read_inode(struct inode *i)
  21495. +{
  21496. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  21497. + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);
  21498. +
  21499. + TRACE("Entered vfs_read_inode\n");
  21500. +
  21501. + if(inode != SQUASHFS_INVALID_BLK)
  21502. + (msblk->read_inode)(i, inode);
  21503. +}
  21504. +
  21505. +
  21506. +static struct dentry *squashfs_get_parent(struct dentry *child)
  21507. +{
  21508. + struct inode *i = child->d_inode;
  21509. + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);
  21510. + struct dentry *rv;
  21511. +
  21512. + TRACE("Entered squashfs_get_parent\n");
  21513. +
  21514. + if(parent == NULL) {
  21515. + rv = ERR_PTR(-EACCES);
  21516. + goto out;
  21517. + }
  21518. +
  21519. + rv = d_alloc_anon(parent);
  21520. + if(rv == NULL)
  21521. + rv = ERR_PTR(-ENOMEM);
  21522. +
  21523. +out:
  21524. + return rv;
  21525. +}
  21526. +
  21527. +
  21528. +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)
  21529. +{
  21530. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21531. + struct inode *i = iget_locked(s, inode_number);
  21532. +
  21533. + TRACE("Entered squashfs_iget\n");
  21534. +
  21535. + if(i && (i->i_state & I_NEW)) {
  21536. + (msblk->read_inode)(i, inode);
  21537. + unlock_new_inode(i);
  21538. + }
  21539. +
  21540. + return i;
  21541. +}
  21542. +
  21543. +
  21544. +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)
  21545. +{
  21546. + struct super_block *s = i->i_sb;
  21547. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21548. + struct squashfs_super_block *sblk = &msblk->sblk;
  21549. + long long block = SQUASHFS_INODE_BLK(inode) +
  21550. + sblk->inode_table_start;
  21551. + unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
  21552. + long long next_block;
  21553. + unsigned int next_offset;
  21554. + union squashfs_inode_header id, sid;
  21555. + struct squashfs_base_inode_header *inodeb = &id.base,
  21556. + *sinodeb = &sid.base;
  21557. +
  21558. + TRACE("Entered squashfs_read_inode\n");
  21559. +
  21560. + if (msblk->swap) {
  21561. + if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
  21562. + offset, sizeof(*sinodeb), &next_block,
  21563. + &next_offset))
  21564. + goto failed_read;
  21565. + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
  21566. + sizeof(*sinodeb));
  21567. + } else
  21568. + if (!squashfs_get_cached_block(s, (char *) inodeb, block,
  21569. + offset, sizeof(*inodeb), &next_block,
  21570. + &next_offset))
  21571. + goto failed_read;
  21572. +
  21573. + squashfs_new_inode(msblk, i, inodeb);
  21574. +
  21575. + switch(inodeb->inode_type) {
  21576. + case SQUASHFS_FILE_TYPE: {
  21577. + unsigned int frag_size;
  21578. + long long frag_blk;
  21579. + struct squashfs_reg_inode_header *inodep = &id.reg;
  21580. + struct squashfs_reg_inode_header *sinodep = &sid.reg;
  21581. +
  21582. + if (msblk->swap) {
  21583. + if (!squashfs_get_cached_block(s, (char *)
  21584. + sinodep, block, offset,
  21585. + sizeof(*sinodep), &next_block,
  21586. + &next_offset))
  21587. + goto failed_read;
  21588. + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
  21589. + } else
  21590. + if (!squashfs_get_cached_block(s, (char *)
  21591. + inodep, block, offset,
  21592. + sizeof(*inodep), &next_block,
  21593. + &next_offset))
  21594. + goto failed_read;
  21595. +
  21596. + frag_blk = SQUASHFS_INVALID_BLK;
  21597. + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
  21598. + !get_fragment_location(s,
  21599. + inodep->fragment, &frag_blk, &frag_size))
  21600. + goto failed_read;
  21601. +
  21602. + i->i_nlink = 1;
  21603. + i->i_size = inodep->file_size;
  21604. + i->i_fop = &generic_ro_fops;
  21605. + i->i_mode |= S_IFREG;
  21606. + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
  21607. + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
  21608. + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
  21609. + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
  21610. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21611. + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
  21612. + SQUASHFS_I(i)->offset = next_offset;
  21613. + if (sblk->block_size > 4096)
  21614. + i->i_data.a_ops = &squashfs_aops;
  21615. + else
  21616. + i->i_data.a_ops = &squashfs_aops_4K;
  21617. +
  21618. + TRACE("File inode %x:%x, start_block %llx, "
  21619. + "block_list_start %llx, offset %x\n",
  21620. + SQUASHFS_INODE_BLK(inode), offset,
  21621. + inodep->start_block, next_block,
  21622. + next_offset);
  21623. + break;
  21624. + }
  21625. + case SQUASHFS_LREG_TYPE: {
  21626. + unsigned int frag_size;
  21627. + long long frag_blk;
  21628. + struct squashfs_lreg_inode_header *inodep = &id.lreg;
  21629. + struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
  21630. +
  21631. + if (msblk->swap) {
  21632. + if (!squashfs_get_cached_block(s, (char *)
  21633. + sinodep, block, offset,
  21634. + sizeof(*sinodep), &next_block,
  21635. + &next_offset))
  21636. + goto failed_read;
  21637. + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
  21638. + } else
  21639. + if (!squashfs_get_cached_block(s, (char *)
  21640. + inodep, block, offset,
  21641. + sizeof(*inodep), &next_block,
  21642. + &next_offset))
  21643. + goto failed_read;
  21644. +
  21645. + frag_blk = SQUASHFS_INVALID_BLK;
  21646. + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
  21647. + !get_fragment_location(s,
  21648. + inodep->fragment, &frag_blk, &frag_size))
  21649. + goto failed_read;
  21650. +
  21651. + i->i_nlink = inodep->nlink;
  21652. + i->i_size = inodep->file_size;
  21653. + i->i_fop = &generic_ro_fops;
  21654. + i->i_mode |= S_IFREG;
  21655. + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
  21656. + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
  21657. + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
  21658. + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
  21659. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21660. + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
  21661. + SQUASHFS_I(i)->offset = next_offset;
  21662. + if (sblk->block_size > 4096)
  21663. + i->i_data.a_ops = &squashfs_aops;
  21664. + else
  21665. + i->i_data.a_ops = &squashfs_aops_4K;
  21666. +
  21667. + TRACE("File inode %x:%x, start_block %llx, "
  21668. + "block_list_start %llx, offset %x\n",
  21669. + SQUASHFS_INODE_BLK(inode), offset,
  21670. + inodep->start_block, next_block,
  21671. + next_offset);
  21672. + break;
  21673. + }
  21674. + case SQUASHFS_DIR_TYPE: {
  21675. + struct squashfs_dir_inode_header *inodep = &id.dir;
  21676. + struct squashfs_dir_inode_header *sinodep = &sid.dir;
  21677. +
  21678. + if (msblk->swap) {
  21679. + if (!squashfs_get_cached_block(s, (char *)
  21680. + sinodep, block, offset,
  21681. + sizeof(*sinodep), &next_block,
  21682. + &next_offset))
  21683. + goto failed_read;
  21684. + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
  21685. + } else
  21686. + if (!squashfs_get_cached_block(s, (char *)
  21687. + inodep, block, offset,
  21688. + sizeof(*inodep), &next_block,
  21689. + &next_offset))
  21690. + goto failed_read;
  21691. +
  21692. + i->i_nlink = inodep->nlink;
  21693. + i->i_size = inodep->file_size;
  21694. + i->i_op = &squashfs_dir_inode_ops;
  21695. + i->i_fop = &squashfs_dir_ops;
  21696. + i->i_mode |= S_IFDIR;
  21697. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21698. + SQUASHFS_I(i)->offset = inodep->offset;
  21699. + SQUASHFS_I(i)->u.s2.directory_index_count = 0;
  21700. + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
  21701. +
  21702. + TRACE("Directory inode %x:%x, start_block %x, offset "
  21703. + "%x\n", SQUASHFS_INODE_BLK(inode),
  21704. + offset, inodep->start_block,
  21705. + inodep->offset);
  21706. + break;
  21707. + }
  21708. + case SQUASHFS_LDIR_TYPE: {
  21709. + struct squashfs_ldir_inode_header *inodep = &id.ldir;
  21710. + struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
  21711. +
  21712. + if (msblk->swap) {
  21713. + if (!squashfs_get_cached_block(s, (char *)
  21714. + sinodep, block, offset,
  21715. + sizeof(*sinodep), &next_block,
  21716. + &next_offset))
  21717. + goto failed_read;
  21718. + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
  21719. + sinodep);
  21720. + } else
  21721. + if (!squashfs_get_cached_block(s, (char *)
  21722. + inodep, block, offset,
  21723. + sizeof(*inodep), &next_block,
  21724. + &next_offset))
  21725. + goto failed_read;
  21726. +
  21727. + i->i_nlink = inodep->nlink;
  21728. + i->i_size = inodep->file_size;
  21729. + i->i_op = &squashfs_dir_inode_ops;
  21730. + i->i_fop = &squashfs_dir_ops;
  21731. + i->i_mode |= S_IFDIR;
  21732. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21733. + SQUASHFS_I(i)->offset = inodep->offset;
  21734. + SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
  21735. + SQUASHFS_I(i)->u.s2.directory_index_offset =
  21736. + next_offset;
  21737. + SQUASHFS_I(i)->u.s2.directory_index_count =
  21738. + inodep->i_count;
  21739. + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
  21740. +
  21741. + TRACE("Long directory inode %x:%x, start_block %x, "
  21742. + "offset %x\n",
  21743. + SQUASHFS_INODE_BLK(inode), offset,
  21744. + inodep->start_block, inodep->offset);
  21745. + break;
  21746. + }
  21747. + case SQUASHFS_SYMLINK_TYPE: {
  21748. + struct squashfs_symlink_inode_header *inodep =
  21749. + &id.symlink;
  21750. + struct squashfs_symlink_inode_header *sinodep =
  21751. + &sid.symlink;
  21752. +
  21753. + if (msblk->swap) {
  21754. + if (!squashfs_get_cached_block(s, (char *)
  21755. + sinodep, block, offset,
  21756. + sizeof(*sinodep), &next_block,
  21757. + &next_offset))
  21758. + goto failed_read;
  21759. + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
  21760. + sinodep);
  21761. + } else
  21762. + if (!squashfs_get_cached_block(s, (char *)
  21763. + inodep, block, offset,
  21764. + sizeof(*inodep), &next_block,
  21765. + &next_offset))
  21766. + goto failed_read;
  21767. +
  21768. + i->i_nlink = inodep->nlink;
  21769. + i->i_size = inodep->symlink_size;
  21770. + i->i_op = &page_symlink_inode_operations;
  21771. + i->i_data.a_ops = &squashfs_symlink_aops;
  21772. + i->i_mode |= S_IFLNK;
  21773. + SQUASHFS_I(i)->start_block = next_block;
  21774. + SQUASHFS_I(i)->offset = next_offset;
  21775. +
  21776. + TRACE("Symbolic link inode %x:%x, start_block %llx, "
  21777. + "offset %x\n",
  21778. + SQUASHFS_INODE_BLK(inode), offset,
  21779. + next_block, next_offset);
  21780. + break;
  21781. + }
  21782. + case SQUASHFS_BLKDEV_TYPE:
  21783. + case SQUASHFS_CHRDEV_TYPE: {
  21784. + struct squashfs_dev_inode_header *inodep = &id.dev;
  21785. + struct squashfs_dev_inode_header *sinodep = &sid.dev;
  21786. +
  21787. + if (msblk->swap) {
  21788. + if (!squashfs_get_cached_block(s, (char *)
  21789. + sinodep, block, offset,
  21790. + sizeof(*sinodep), &next_block,
  21791. + &next_offset))
  21792. + goto failed_read;
  21793. + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
  21794. + } else
  21795. + if (!squashfs_get_cached_block(s, (char *)
  21796. + inodep, block, offset,
  21797. + sizeof(*inodep), &next_block,
  21798. + &next_offset))
  21799. + goto failed_read;
  21800. +
  21801. + i->i_nlink = inodep->nlink;
  21802. + i->i_mode |= (inodeb->inode_type ==
  21803. + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
  21804. + S_IFBLK;
  21805. + init_special_inode(i, i->i_mode,
  21806. + old_decode_dev(inodep->rdev));
  21807. +
  21808. + TRACE("Device inode %x:%x, rdev %x\n",
  21809. + SQUASHFS_INODE_BLK(inode), offset,
  21810. + inodep->rdev);
  21811. + break;
  21812. + }
  21813. + case SQUASHFS_FIFO_TYPE:
  21814. + case SQUASHFS_SOCKET_TYPE: {
  21815. + struct squashfs_ipc_inode_header *inodep = &id.ipc;
  21816. + struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
  21817. +
  21818. + if (msblk->swap) {
  21819. + if (!squashfs_get_cached_block(s, (char *)
  21820. + sinodep, block, offset,
  21821. + sizeof(*sinodep), &next_block,
  21822. + &next_offset))
  21823. + goto failed_read;
  21824. + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
  21825. + } else
  21826. + if (!squashfs_get_cached_block(s, (char *)
  21827. + inodep, block, offset,
  21828. + sizeof(*inodep), &next_block,
  21829. + &next_offset))
  21830. + goto failed_read;
  21831. +
  21832. + i->i_nlink = inodep->nlink;
  21833. + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
  21834. + ? S_IFIFO : S_IFSOCK;
  21835. + init_special_inode(i, i->i_mode, 0);
  21836. + break;
  21837. + }
  21838. + default:
  21839. + ERROR("Unknown inode type %d in squashfs_iget!\n",
  21840. + inodeb->inode_type);
  21841. + goto failed_read1;
  21842. + }
  21843. +
  21844. + return 1;
  21845. +
  21846. +failed_read:
  21847. + ERROR("Unable to read inode [%llx:%x]\n", block, offset);
  21848. +
  21849. +failed_read1:
  21850. + make_bad_inode(i);
  21851. + return 0;
  21852. +}
  21853. +
  21854. +
  21855. +static int read_inode_lookup_table(struct super_block *s)
  21856. +{
  21857. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21858. + struct squashfs_super_block *sblk = &msblk->sblk;
  21859. + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);
  21860. +
  21861. + TRACE("In read_inode_lookup_table, length %d\n", length);
  21862. +
  21863. + /* Allocate inode lookup table */
  21864. + if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {
  21865. + ERROR("Failed to allocate inode lookup table\n");
  21866. + return 0;
  21867. + }
  21868. +
  21869. + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,
  21870. + sblk->lookup_table_start, length |
  21871. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
  21872. + ERROR("unable to read inode lookup table\n");
  21873. + return 0;
  21874. + }
  21875. +
  21876. + if (msblk->swap) {
  21877. + int i;
  21878. + long long block;
  21879. +
  21880. + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {
  21881. + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),
  21882. + &msblk->inode_lookup_table[i], 1);
  21883. + msblk->inode_lookup_table[i] = block;
  21884. + }
  21885. + }
  21886. +
  21887. + return 1;
  21888. +}
  21889. +
  21890. +
  21891. +static int read_fragment_index_table(struct super_block *s)
  21892. +{
  21893. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21894. + struct squashfs_super_block *sblk = &msblk->sblk;
  21895. + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
  21896. +
  21897. + if(length == 0)
  21898. + return 1;
  21899. +
  21900. + /* Allocate fragment index table */
  21901. + if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {
  21902. + ERROR("Failed to allocate fragment index table\n");
  21903. + return 0;
  21904. + }
  21905. +
  21906. + if (!squashfs_read_data(s, (char *) msblk->fragment_index,
  21907. + sblk->fragment_table_start, length |
  21908. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
  21909. + ERROR("unable to read fragment index table\n");
  21910. + return 0;
  21911. + }
  21912. +
  21913. + if (msblk->swap) {
  21914. + int i;
  21915. + long long fragment;
  21916. +
  21917. + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {
  21918. + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
  21919. + &msblk->fragment_index[i], 1);
  21920. + msblk->fragment_index[i] = fragment;
  21921. + }
  21922. + }
  21923. +
  21924. + return 1;
  21925. +}
  21926. +
  21927. +
  21928. +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
  21929. +{
  21930. + struct squashfs_super_block *sblk = &msblk->sblk;
  21931. +
  21932. + msblk->read_inode = squashfs_read_inode;
  21933. + msblk->read_blocklist = read_blocklist;
  21934. + msblk->read_fragment_index_table = read_fragment_index_table;
  21935. +
  21936. + if (sblk->s_major == 1) {
  21937. + if (!squashfs_1_0_supported(msblk)) {
  21938. + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
  21939. + "are unsupported\n");
  21940. + SERROR("Please recompile with "
  21941. + "Squashfs 1.0 support enabled\n");
  21942. + return 0;
  21943. + }
  21944. + } else if (sblk->s_major == 2) {
  21945. + if (!squashfs_2_0_supported(msblk)) {
  21946. + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
  21947. + "are unsupported\n");
  21948. + SERROR("Please recompile with "
  21949. + "Squashfs 2.0 support enabled\n");
  21950. + return 0;
  21951. + }
  21952. + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
  21953. + SQUASHFS_MINOR) {
  21954. + SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
  21955. + "filesystem\n", sblk->s_major, sblk->s_minor);
  21956. + SERROR("Please update your kernel\n");
  21957. + return 0;
  21958. + }
  21959. +
  21960. + return 1;
  21961. +}
  21962. +
  21963. +
  21964. +static int squashfs_fill_super(struct super_block *s, void *data, int silent)
  21965. +{
  21966. + struct squashfs_sb_info *msblk;
  21967. + struct squashfs_super_block *sblk;
  21968. + int i;
  21969. + char b[BDEVNAME_SIZE];
  21970. + struct inode *root;
  21971. +
  21972. + TRACE("Entered squashfs_read_superblock\n");
  21973. +
  21974. + if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
  21975. + GFP_KERNEL))) {
  21976. + ERROR("Failed to allocate superblock\n");
  21977. + goto failure;
  21978. + }
  21979. + memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
  21980. + msblk = s->s_fs_info;
  21981. + if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
  21982. + ERROR("Failed to allocate zlib workspace\n");
  21983. + goto failure;
  21984. + }
  21985. + sblk = &msblk->sblk;
  21986. +
  21987. + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
  21988. + msblk->devblksize_log2 = ffz(~msblk->devblksize);
  21989. +
  21990. + mutex_init(&msblk->read_data_mutex);
  21991. + mutex_init(&msblk->read_page_mutex);
  21992. + mutex_init(&msblk->block_cache_mutex);
  21993. + mutex_init(&msblk->fragment_mutex);
  21994. + mutex_init(&msblk->meta_index_mutex);
  21995. +
  21996. + init_waitqueue_head(&msblk->waitq);
  21997. + init_waitqueue_head(&msblk->fragment_wait_queue);
  21998. +
  21999. + sblk->bytes_used = sizeof(struct squashfs_super_block);
  22000. + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
  22001. + sizeof(struct squashfs_super_block) |
  22002. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {
  22003. + SERROR("unable to read superblock\n");
  22004. + goto failed_mount;
  22005. + }
  22006. +
  22007. + /* Check it is a SQUASHFS superblock */
  22008. + msblk->swap = 0;
  22009. + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
  22010. + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
  22011. + struct squashfs_super_block ssblk;
  22012. +
  22013. + WARNING("Mounting a different endian SQUASHFS "
  22014. + "filesystem on %s\n", bdevname(s->s_bdev, b));
  22015. +
  22016. + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
  22017. + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
  22018. + msblk->swap = 1;
  22019. + } else {
  22020. + SERROR("Can't find a SQUASHFS superblock on %s\n",
  22021. + bdevname(s->s_bdev, b));
  22022. + goto failed_mount;
  22023. + }
  22024. + }
  22025. +
  22026. + /* Check the MAJOR & MINOR versions */
  22027. + if(!supported_squashfs_filesystem(msblk, silent))
  22028. + goto failed_mount;
  22029. +
  22030. + /* Check the filesystem does not extend beyond the end of the
  22031. + block device */
  22032. + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
  22033. + goto failed_mount;
  22034. +
  22035. + /* Check the root inode for sanity */
  22036. + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
  22037. + goto failed_mount;
  22038. +
  22039. + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
  22040. + TRACE("Inodes are %scompressed\n",
  22041. + SQUASHFS_UNCOMPRESSED_INODES
  22042. + (sblk->flags) ? "un" : "");
  22043. + TRACE("Data is %scompressed\n",
  22044. + SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
  22045. + ? "un" : "");
  22046. + TRACE("Check data is %s present in the filesystem\n",
  22047. + SQUASHFS_CHECK_DATA(sblk->flags) ?
  22048. + "" : "not");
  22049. + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
  22050. + TRACE("Block size %d\n", sblk->block_size);
  22051. + TRACE("Number of inodes %d\n", sblk->inodes);
  22052. + if (sblk->s_major > 1)
  22053. + TRACE("Number of fragments %d\n", sblk->fragments);
  22054. + TRACE("Number of uids %d\n", sblk->no_uids);
  22055. + TRACE("Number of gids %d\n", sblk->no_guids);
  22056. + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
  22057. + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
  22058. + if (sblk->s_major > 1)
  22059. + TRACE("sblk->fragment_table_start %llx\n",
  22060. + sblk->fragment_table_start);
  22061. + TRACE("sblk->uid_start %llx\n", sblk->uid_start);
  22062. +
  22063. + s->s_flags |= MS_RDONLY;
  22064. + s->s_op = &squashfs_super_ops;
  22065. +
  22066. + /* Init inode_table block pointer array */
  22067. + if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
  22068. + SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
  22069. + ERROR("Failed to allocate block cache\n");
  22070. + goto failed_mount;
  22071. + }
  22072. +
  22073. + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
  22074. + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
  22075. +
  22076. + msblk->next_cache = 0;
  22077. +
  22078. + /* Allocate read_page block */
  22079. + if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
  22080. + ERROR("Failed to allocate read_page block\n");
  22081. + goto failed_mount;
  22082. + }
  22083. +
  22084. + /* Allocate uid and gid tables */
  22085. + if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
  22086. + sizeof(unsigned int), GFP_KERNEL))) {
  22087. + ERROR("Failed to allocate uid/gid table\n");
  22088. + goto failed_mount;
  22089. + }
  22090. + msblk->guid = msblk->uid + sblk->no_uids;
  22091. +
  22092. + if (msblk->swap) {
  22093. + unsigned int suid[sblk->no_uids + sblk->no_guids];
  22094. +
  22095. + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
  22096. + ((sblk->no_uids + sblk->no_guids) *
  22097. + sizeof(unsigned int)) |
  22098. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
  22099. + ERROR("unable to read uid/gid table\n");
  22100. + goto failed_mount;
  22101. + }
  22102. +
  22103. + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
  22104. + sblk->no_guids), (sizeof(unsigned int) * 8));
  22105. + } else
  22106. + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
  22107. + ((sblk->no_uids + sblk->no_guids) *
  22108. + sizeof(unsigned int)) |
  22109. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
  22110. + ERROR("unable to read uid/gid table\n");
  22111. + goto failed_mount;
  22112. + }
  22113. +
  22114. +
  22115. + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
  22116. + goto allocate_root;
  22117. +
  22118. + if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
  22119. + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
  22120. + ERROR("Failed to allocate fragment block cache\n");
  22121. + goto failed_mount;
  22122. + }
  22123. +
  22124. + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
  22125. + msblk->fragment[i].locked = 0;
  22126. + msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
  22127. + msblk->fragment[i].data = NULL;
  22128. + }
  22129. +
  22130. + msblk->next_fragment = 0;
  22131. +
  22132. + /* Allocate and read fragment index table */
  22133. + if (msblk->read_fragment_index_table(s) == 0)
  22134. + goto failed_mount;
  22135. +
  22136. + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)
  22137. + goto allocate_root;
  22138. +
  22139. + /* Allocate and read inode lookup table */
  22140. + if (read_inode_lookup_table(s) == 0)
  22141. + goto failed_mount;
  22142. +
  22143. + s->s_op = &squashfs_export_super_ops;
  22144. + s->s_export_op = &squashfs_export_ops;
  22145. +
  22146. +allocate_root:
  22147. + root = new_inode(s);
  22148. + if ((msblk->read_inode)(root, sblk->root_inode) == 0)
  22149. + goto failed_mount;
  22150. + insert_inode_hash(root);
  22151. +
  22152. + if ((s->s_root = d_alloc_root(root)) == NULL) {
  22153. + ERROR("Root inode create failed\n");
  22154. + iput(root);
  22155. + goto failed_mount;
  22156. + }
  22157. +
  22158. + TRACE("Leaving squashfs_read_super\n");
  22159. + return 0;
  22160. +
  22161. +failed_mount:
  22162. + kfree(msblk->inode_lookup_table);
  22163. + kfree(msblk->fragment_index);
  22164. + kfree(msblk->fragment);
  22165. + kfree(msblk->uid);
  22166. + kfree(msblk->read_page);
  22167. + kfree(msblk->block_cache);
  22168. + kfree(msblk->fragment_index_2);
  22169. + vfree(msblk->stream.workspace);
  22170. + kfree(s->s_fs_info);
  22171. + s->s_fs_info = NULL;
  22172. + return -EINVAL;
  22173. +
  22174. +failure:
  22175. + return -ENOMEM;
  22176. +}
  22177. +
  22178. +
  22179. +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  22180. +{
  22181. + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
  22182. + struct squashfs_super_block *sblk = &msblk->sblk;
  22183. +
  22184. + TRACE("Entered squashfs_statfs\n");
  22185. +
  22186. + buf->f_type = SQUASHFS_MAGIC;
  22187. + buf->f_bsize = sblk->block_size;
  22188. + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
  22189. + buf->f_bfree = buf->f_bavail = 0;
  22190. + buf->f_files = sblk->inodes;
  22191. + buf->f_ffree = 0;
  22192. + buf->f_namelen = SQUASHFS_NAME_LEN;
  22193. +
  22194. + return 0;
  22195. +}
  22196. +
  22197. +
  22198. +static int squashfs_symlink_readpage(struct file *file, struct page *page)
  22199. +{
  22200. + struct inode *inode = page->mapping->host;
  22201. + int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
  22202. + long long block = SQUASHFS_I(inode)->start_block;
  22203. + int offset = SQUASHFS_I(inode)->offset;
  22204. + void *pageaddr = kmap(page);
  22205. +
  22206. + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
  22207. + "%llx, offset %x\n", page->index,
  22208. + SQUASHFS_I(inode)->start_block,
  22209. + SQUASHFS_I(inode)->offset);
  22210. +
  22211. + for (length = 0; length < index; length += bytes) {
  22212. + if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
  22213. + block, offset, PAGE_CACHE_SIZE, &block,
  22214. + &offset))) {
  22215. + ERROR("Unable to read symbolic link [%llx:%x]\n", block,
  22216. + offset);
  22217. + goto skip_read;
  22218. + }
  22219. + }
  22220. +
  22221. + if (length != index) {
  22222. + ERROR("(squashfs_symlink_readpage) length != index\n");
  22223. + bytes = 0;
  22224. + goto skip_read;
  22225. + }
  22226. +
  22227. + bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
  22228. + i_size_read(inode) - length;
  22229. +
  22230. + if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
  22231. + offset, bytes, &block, &offset)))
  22232. + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
  22233. +
  22234. +skip_read:
  22235. + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
  22236. + kunmap(page);
  22237. + flush_dcache_page(page);
  22238. + SetPageUptodate(page);
  22239. + unlock_page(page);
  22240. +
  22241. + return 0;
  22242. +}
  22243. +
  22244. +
  22245. +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
  22246. +{
  22247. + struct meta_index *meta = NULL;
  22248. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22249. + int i;
  22250. +
  22251. + mutex_lock(&msblk->meta_index_mutex);
  22252. +
  22253. + TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
  22254. +
  22255. + if(msblk->meta_index == NULL)
  22256. + goto not_allocated;
  22257. +
  22258. + for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
  22259. + if (msblk->meta_index[i].inode_number == inode->i_ino &&
  22260. + msblk->meta_index[i].offset >= offset &&
  22261. + msblk->meta_index[i].offset <= index &&
  22262. + msblk->meta_index[i].locked == 0) {
  22263. + TRACE("locate_meta_index: entry %d, offset %d\n", i,
  22264. + msblk->meta_index[i].offset);
  22265. + meta = &msblk->meta_index[i];
  22266. + offset = meta->offset;
  22267. + }
  22268. +
  22269. + if (meta)
  22270. + meta->locked = 1;
  22271. +
  22272. +not_allocated:
  22273. + mutex_unlock(&msblk->meta_index_mutex);
  22274. +
  22275. + return meta;
  22276. +}
  22277. +
  22278. +
  22279. +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
  22280. +{
  22281. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22282. + struct meta_index *meta = NULL;
  22283. + int i;
  22284. +
  22285. + mutex_lock(&msblk->meta_index_mutex);
  22286. +
  22287. + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
  22288. +
  22289. + if(msblk->meta_index == NULL) {
  22290. + if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
  22291. + SQUASHFS_META_NUMBER, GFP_KERNEL))) {
  22292. + ERROR("Failed to allocate meta_index\n");
  22293. + goto failed;
  22294. + }
  22295. + for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
  22296. + msblk->meta_index[i].inode_number = 0;
  22297. + msblk->meta_index[i].locked = 0;
  22298. + }
  22299. + msblk->next_meta_index = 0;
  22300. + }
  22301. +
  22302. + for(i = SQUASHFS_META_NUMBER; i &&
  22303. + msblk->meta_index[msblk->next_meta_index].locked; i --)
  22304. + msblk->next_meta_index = (msblk->next_meta_index + 1) %
  22305. + SQUASHFS_META_NUMBER;
  22306. +
  22307. + if(i == 0) {
  22308. + TRACE("empty_meta_index: failed!\n");
  22309. + goto failed;
  22310. + }
  22311. +
  22312. + TRACE("empty_meta_index: returned meta entry %d, %p\n",
  22313. + msblk->next_meta_index,
  22314. + &msblk->meta_index[msblk->next_meta_index]);
  22315. +
  22316. + meta = &msblk->meta_index[msblk->next_meta_index];
  22317. + msblk->next_meta_index = (msblk->next_meta_index + 1) %
  22318. + SQUASHFS_META_NUMBER;
  22319. +
  22320. + meta->inode_number = inode->i_ino;
  22321. + meta->offset = offset;
  22322. + meta->skip = skip;
  22323. + meta->entries = 0;
  22324. + meta->locked = 1;
  22325. +
  22326. +failed:
  22327. + mutex_unlock(&msblk->meta_index_mutex);
  22328. + return meta;
  22329. +}
  22330. +
  22331. +
  22332. +void release_meta_index(struct inode *inode, struct meta_index *meta)
  22333. +{
  22334. + meta->locked = 0;
  22335. + smp_mb();
  22336. +}
  22337. +
  22338. +
  22339. +static int read_block_index(struct super_block *s, int blocks, char *block_list,
  22340. + long long *start_block, int *offset)
  22341. +{
  22342. + struct squashfs_sb_info *msblk = s->s_fs_info;
  22343. + unsigned int *block_listp;
  22344. + int block = 0;
  22345. +
  22346. + if (msblk->swap) {
  22347. + char sblock_list[blocks << 2];
  22348. +
  22349. + if (!squashfs_get_cached_block(s, sblock_list, *start_block,
  22350. + *offset, blocks << 2, start_block, offset)) {
  22351. + ERROR("Unable to read block list [%llx:%x]\n",
  22352. + *start_block, *offset);
  22353. + goto failure;
  22354. + }
  22355. + SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
  22356. + ((unsigned int *)sblock_list), blocks);
  22357. + } else
  22358. + if (!squashfs_get_cached_block(s, block_list, *start_block,
  22359. + *offset, blocks << 2, start_block, offset)) {
  22360. + ERROR("Unable to read block list [%llx:%x]\n",
  22361. + *start_block, *offset);
  22362. + goto failure;
  22363. + }
  22364. +
  22365. + for (block_listp = (unsigned int *) block_list; blocks;
  22366. + block_listp++, blocks --)
  22367. + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
  22368. +
  22369. + return block;
  22370. +
  22371. +failure:
  22372. + return -1;
  22373. +}
  22374. +
  22375. +
  22376. +#define SIZE 256
  22377. +
  22378. +static inline int calculate_skip(int blocks) {
  22379. + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
  22380. + return skip >= 7 ? 7 : skip + 1;
  22381. +}
  22382. +
  22383. +
  22384. +static int get_meta_index(struct inode *inode, int index,
  22385. + long long *index_block, int *index_offset,
  22386. + long long *data_block, char *block_list)
  22387. +{
  22388. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22389. + struct squashfs_super_block *sblk = &msblk->sblk;
  22390. + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
  22391. + int offset = 0;
  22392. + struct meta_index *meta;
  22393. + struct meta_entry *meta_entry;
  22394. + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
  22395. + int cur_offset = SQUASHFS_I(inode)->offset;
  22396. + long long cur_data_block = SQUASHFS_I(inode)->start_block;
  22397. + int i;
  22398. +
  22399. + index /= SQUASHFS_META_INDEXES * skip;
  22400. +
  22401. + while ( offset < index ) {
  22402. + meta = locate_meta_index(inode, index, offset + 1);
  22403. +
  22404. + if (meta == NULL) {
  22405. + if ((meta = empty_meta_index(inode, offset + 1,
  22406. + skip)) == NULL)
  22407. + goto all_done;
  22408. + } else {
  22409. + if(meta->entries == 0)
  22410. + goto failed;
  22411. + offset = index < meta->offset + meta->entries ? index :
  22412. + meta->offset + meta->entries - 1;
  22413. + meta_entry = &meta->meta_entry[offset - meta->offset];
  22414. + cur_index_block = meta_entry->index_block + sblk->inode_table_start;
  22415. + cur_offset = meta_entry->offset;
  22416. + cur_data_block = meta_entry->data_block;
  22417. + TRACE("get_meta_index: offset %d, meta->offset %d, "
  22418. + "meta->entries %d\n", offset, meta->offset,
  22419. + meta->entries);
  22420. + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
  22421. + " data_block 0x%llx\n", cur_index_block,
  22422. + cur_offset, cur_data_block);
  22423. + }
  22424. +
  22425. + for (i = meta->offset + meta->entries; i <= index &&
  22426. + i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
  22427. + int blocks = skip * SQUASHFS_META_INDEXES;
  22428. +
  22429. + while (blocks) {
  22430. + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
  22431. + blocks;
  22432. + int res = read_block_index(inode->i_sb, block,
  22433. + block_list, &cur_index_block,
  22434. + &cur_offset);
  22435. +
  22436. + if (res == -1)
  22437. + goto failed;
  22438. +
  22439. + cur_data_block += res;
  22440. + blocks -= block;
  22441. + }
  22442. +
  22443. + meta_entry = &meta->meta_entry[i - meta->offset];
  22444. + meta_entry->index_block = cur_index_block - sblk->inode_table_start;
  22445. + meta_entry->offset = cur_offset;
  22446. + meta_entry->data_block = cur_data_block;
  22447. + meta->entries ++;
  22448. + offset ++;
  22449. + }
  22450. +
  22451. + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
  22452. + meta->offset, meta->entries);
  22453. +
  22454. + release_meta_index(inode, meta);
  22455. + }
  22456. +
  22457. +all_done:
  22458. + *index_block = cur_index_block;
  22459. + *index_offset = cur_offset;
  22460. + *data_block = cur_data_block;
  22461. +
  22462. + return offset * SQUASHFS_META_INDEXES * skip;
  22463. +
  22464. +failed:
  22465. + release_meta_index(inode, meta);
  22466. + return -1;
  22467. +}
  22468. +
  22469. +
  22470. +static long long read_blocklist(struct inode *inode, int index,
  22471. + int readahead_blks, char *block_list,
  22472. + unsigned short **block_p, unsigned int *bsize)
  22473. +{
  22474. + long long block_ptr;
  22475. + int offset;
  22476. + long long block;
  22477. + int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
  22478. + block_list);
  22479. +
  22480. + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
  22481. + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
  22482. + block);
  22483. +
  22484. + if(res == -1)
  22485. + goto failure;
  22486. +
  22487. + index -= res;
  22488. +
  22489. + while ( index ) {
  22490. + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
  22491. + int res = read_block_index(inode->i_sb, blocks, block_list,
  22492. + &block_ptr, &offset);
  22493. + if (res == -1)
  22494. + goto failure;
  22495. + block += res;
  22496. + index -= blocks;
  22497. + }
  22498. +
  22499. + if (read_block_index(inode->i_sb, 1, block_list,
  22500. + &block_ptr, &offset) == -1)
  22501. + goto failure;
  22502. + *bsize = *((unsigned int *) block_list);
  22503. +
  22504. + return block;
  22505. +
  22506. +failure:
  22507. + return 0;
  22508. +}
  22509. +
  22510. +
  22511. +static int squashfs_readpage(struct file *file, struct page *page)
  22512. +{
  22513. + struct inode *inode = page->mapping->host;
  22514. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22515. + struct squashfs_super_block *sblk = &msblk->sblk;
  22516. + unsigned char *block_list;
  22517. + long long block;
  22518. + unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
  22519. + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
  22520. + void *pageaddr;
  22521. + struct squashfs_fragment_cache *fragment = NULL;
  22522. + char *data_ptr = msblk->read_page;
  22523. +
  22524. + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
  22525. + int start_index = page->index & ~mask;
  22526. + int end_index = start_index | mask;
  22527. +
  22528. + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
  22529. + page->index,
  22530. + SQUASHFS_I(inode)->start_block);
  22531. +
  22532. + if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
  22533. + ERROR("Failed to allocate block_list\n");
  22534. + goto skip_read;
  22535. + }
  22536. +
  22537. + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
  22538. + PAGE_CACHE_SHIFT))
  22539. + goto skip_read;
  22540. +
  22541. + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
  22542. + || index < (i_size_read(inode) >>
  22543. + sblk->block_log)) {
  22544. + if ((block = (msblk->read_blocklist)(inode, index, 1,
  22545. + block_list, NULL, &bsize)) == 0)
  22546. + goto skip_read;
  22547. +
  22548. + mutex_lock(&msblk->read_page_mutex);
  22549. +
  22550. + if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
  22551. + block, bsize, NULL, sblk->block_size))) {
  22552. + ERROR("Unable to read page, block %llx, size %x\n", block,
  22553. + bsize);
  22554. + mutex_unlock(&msblk->read_page_mutex);
  22555. + goto skip_read;
  22556. + }
  22557. + } else {
  22558. + if ((fragment = get_cached_fragment(inode->i_sb,
  22559. + SQUASHFS_I(inode)->
  22560. + u.s1.fragment_start_block,
  22561. + SQUASHFS_I(inode)->u.s1.fragment_size))
  22562. + == NULL) {
  22563. + ERROR("Unable to read page, block %llx, size %x\n",
  22564. + SQUASHFS_I(inode)->
  22565. + u.s1.fragment_start_block,
  22566. + (int) SQUASHFS_I(inode)->
  22567. + u.s1.fragment_size);
  22568. + goto skip_read;
  22569. + }
  22570. + bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
  22571. + (i_size_read(inode) & (sblk->block_size
  22572. + - 1));
  22573. + byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
  22574. + data_ptr = fragment->data;
  22575. + }
  22576. +
  22577. + for (i = start_index; i <= end_index && byte_offset < bytes;
  22578. + i++, byte_offset += PAGE_CACHE_SIZE) {
  22579. + struct page *push_page;
  22580. + int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
  22581. + PAGE_CACHE_SIZE : bytes - byte_offset;
  22582. +
  22583. + TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
  22584. + bytes, i, byte_offset, avail);
  22585. +
  22586. + push_page = (i == page->index) ? page :
  22587. + grab_cache_page_nowait(page->mapping, i);
  22588. +
  22589. + if (!push_page)
  22590. + continue;
  22591. +
  22592. + if (PageUptodate(push_page))
  22593. + goto skip_page;
  22594. +
  22595. + pageaddr = kmap_atomic(push_page, KM_USER0);
  22596. + memcpy(pageaddr, data_ptr + byte_offset, avail);
  22597. + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
  22598. + kunmap_atomic(pageaddr, KM_USER0);
  22599. + flush_dcache_page(push_page);
  22600. + SetPageUptodate(push_page);
  22601. +skip_page:
  22602. + unlock_page(push_page);
  22603. + if(i != page->index)
  22604. + page_cache_release(push_page);
  22605. + }
  22606. +
  22607. + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
  22608. + || index < (i_size_read(inode) >>
  22609. + sblk->block_log))
  22610. + mutex_unlock(&msblk->read_page_mutex);
  22611. + else
  22612. + release_cached_fragment(msblk, fragment);
  22613. +
  22614. + kfree(block_list);
  22615. + return 0;
  22616. +
  22617. +skip_read:
  22618. + pageaddr = kmap_atomic(page, KM_USER0);
  22619. + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
  22620. + kunmap_atomic(pageaddr, KM_USER0);
  22621. + flush_dcache_page(page);
  22622. + SetPageUptodate(page);
  22623. + unlock_page(page);
  22624. +
  22625. + kfree(block_list);
  22626. + return 0;
  22627. +}
  22628. +
  22629. +
  22630. +static int squashfs_readpage4K(struct file *file, struct page *page)
  22631. +{
  22632. + struct inode *inode = page->mapping->host;
  22633. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22634. + struct squashfs_super_block *sblk = &msblk->sblk;
  22635. + unsigned char *block_list;
  22636. + long long block;
  22637. + unsigned int bsize, bytes = 0;
  22638. + void *pageaddr;
  22639. +
  22640. + TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
  22641. + page->index,
  22642. + SQUASHFS_I(inode)->start_block);
  22643. +
  22644. + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
  22645. + PAGE_CACHE_SHIFT)) {
  22646. + block_list = NULL;
  22647. + goto skip_read;
  22648. + }
  22649. +
  22650. + if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
  22651. + ERROR("Failed to allocate block_list\n");
  22652. + goto skip_read;
  22653. + }
  22654. +
  22655. + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
  22656. + || page->index < (i_size_read(inode) >>
  22657. + sblk->block_log)) {
  22658. + block = (msblk->read_blocklist)(inode, page->index, 1,
  22659. + block_list, NULL, &bsize);
  22660. + if(block == 0)
  22661. + goto skip_read;
  22662. +
  22663. + mutex_lock(&msblk->read_page_mutex);
  22664. + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
  22665. + bsize, NULL, sblk->block_size);
  22666. + if (bytes) {
  22667. + pageaddr = kmap_atomic(page, KM_USER0);
  22668. + memcpy(pageaddr, msblk->read_page, bytes);
  22669. + kunmap_atomic(pageaddr, KM_USER0);
  22670. + } else
  22671. + ERROR("Unable to read page, block %llx, size %x\n",
  22672. + block, bsize);
  22673. + mutex_unlock(&msblk->read_page_mutex);
  22674. + } else {
  22675. + struct squashfs_fragment_cache *fragment =
  22676. + get_cached_fragment(inode->i_sb,
  22677. + SQUASHFS_I(inode)->
  22678. + u.s1.fragment_start_block,
  22679. + SQUASHFS_I(inode)-> u.s1.fragment_size);
  22680. + if (fragment) {
  22681. + bytes = i_size_read(inode) & (sblk->block_size - 1);
  22682. + pageaddr = kmap_atomic(page, KM_USER0);
  22683. + memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
  22684. + u.s1.fragment_offset, bytes);
  22685. + kunmap_atomic(pageaddr, KM_USER0);
  22686. + release_cached_fragment(msblk, fragment);
  22687. + } else
  22688. + ERROR("Unable to read page, block %llx, size %x\n",
  22689. + SQUASHFS_I(inode)->
  22690. + u.s1.fragment_start_block, (int)
  22691. + SQUASHFS_I(inode)-> u.s1.fragment_size);
  22692. + }
  22693. +
  22694. +skip_read:
  22695. + pageaddr = kmap_atomic(page, KM_USER0);
  22696. + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
  22697. + kunmap_atomic(pageaddr, KM_USER0);
  22698. + flush_dcache_page(page);
  22699. + SetPageUptodate(page);
  22700. + unlock_page(page);
  22701. +
  22702. + kfree(block_list);
  22703. + return 0;
  22704. +}
  22705. +
  22706. +
  22707. +static int get_dir_index_using_offset(struct super_block *s, long long
  22708. + *next_block, unsigned int *next_offset,
  22709. + long long index_start,
  22710. + unsigned int index_offset, int i_count,
  22711. + long long f_pos)
  22712. +{
  22713. + struct squashfs_sb_info *msblk = s->s_fs_info;
  22714. + struct squashfs_super_block *sblk = &msblk->sblk;
  22715. + int i, length = 0;
  22716. + struct squashfs_dir_index index;
  22717. +
  22718. + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
  22719. + i_count, (unsigned int) f_pos);
  22720. +
  22721. + f_pos =- 3;
  22722. + if (f_pos == 0)
  22723. + goto finish;
  22724. +
  22725. + for (i = 0; i < i_count; i++) {
  22726. + if (msblk->swap) {
  22727. + struct squashfs_dir_index sindex;
  22728. + squashfs_get_cached_block(s, (char *) &sindex,
  22729. + index_start, index_offset,
  22730. + sizeof(sindex), &index_start,
  22731. + &index_offset);
  22732. + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
  22733. + } else
  22734. + squashfs_get_cached_block(s, (char *) &index,
  22735. + index_start, index_offset,
  22736. + sizeof(index), &index_start,
  22737. + &index_offset);
  22738. +
  22739. + if (index.index > f_pos)
  22740. + break;
  22741. +
  22742. + squashfs_get_cached_block(s, NULL, index_start, index_offset,
  22743. + index.size + 1, &index_start,
  22744. + &index_offset);
  22745. +
  22746. + length = index.index;
  22747. + *next_block = index.start_block + sblk->directory_table_start;
  22748. + }
  22749. +
  22750. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  22751. +
  22752. +finish:
  22753. + return length + 3;
  22754. +}
  22755. +
  22756. +
  22757. +static int get_dir_index_using_name(struct super_block *s, long long
  22758. + *next_block, unsigned int *next_offset,
  22759. + long long index_start,
  22760. + unsigned int index_offset, int i_count,
  22761. + const char *name, int size)
  22762. +{
  22763. + struct squashfs_sb_info *msblk = s->s_fs_info;
  22764. + struct squashfs_super_block *sblk = &msblk->sblk;
  22765. + int i, length = 0;
  22766. + struct squashfs_dir_index *index;
  22767. + char *str;
  22768. +
  22769. + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
  22770. +
  22771. + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
  22772. + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
  22773. + ERROR("Failed to allocate squashfs_dir_index\n");
  22774. + goto failure;
  22775. + }
  22776. +
  22777. + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);
  22778. + strncpy(str, name, size);
  22779. + str[size] = '\0';
  22780. +
  22781. + for (i = 0; i < i_count; i++) {
  22782. + if (msblk->swap) {
  22783. + struct squashfs_dir_index sindex;
  22784. + squashfs_get_cached_block(s, (char *) &sindex,
  22785. + index_start, index_offset,
  22786. + sizeof(sindex), &index_start,
  22787. + &index_offset);
  22788. + SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
  22789. + } else
  22790. + squashfs_get_cached_block(s, (char *) index,
  22791. + index_start, index_offset,
  22792. + sizeof(struct squashfs_dir_index),
  22793. + &index_start, &index_offset);
  22794. +
  22795. + squashfs_get_cached_block(s, index->name, index_start,
  22796. + index_offset, index->size + 1,
  22797. + &index_start, &index_offset);
  22798. +
  22799. + index->name[index->size + 1] = '\0';
  22800. +
  22801. + if (strcmp(index->name, str) > 0)
  22802. + break;
  22803. +
  22804. + length = index->index;
  22805. + *next_block = index->start_block + sblk->directory_table_start;
  22806. + }
  22807. +
  22808. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  22809. + kfree(str);
  22810. +failure:
  22811. + return length + 3;
  22812. +}
  22813. +
  22814. +
  22815. +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
  22816. +{
  22817. + struct inode *i = file->f_dentry->d_inode;
  22818. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  22819. + struct squashfs_super_block *sblk = &msblk->sblk;
  22820. + long long next_block = SQUASHFS_I(i)->start_block +
  22821. + sblk->directory_table_start;
  22822. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  22823. + dir_count;
  22824. + struct squashfs_dir_header dirh;
  22825. + struct squashfs_dir_entry *dire;
  22826. +
  22827. + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
  22828. +
  22829. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  22830. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  22831. + ERROR("Failed to allocate squashfs_dir_entry\n");
  22832. + goto finish;
  22833. + }
  22834. +
  22835. + while(file->f_pos < 3) {
  22836. + char *name;
  22837. + int size, i_ino;
  22838. +
  22839. + if(file->f_pos == 0) {
  22840. + name = ".";
  22841. + size = 1;
  22842. + i_ino = i->i_ino;
  22843. + } else {
  22844. + name = "..";
  22845. + size = 2;
  22846. + i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
  22847. + }
  22848. + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
  22849. + (unsigned int) dirent, name, size, (int)
  22850. + file->f_pos, i_ino,
  22851. + squashfs_filetype_table[1]);
  22852. +
  22853. + if (filldir(dirent, name, size,
  22854. + file->f_pos, i_ino,
  22855. + squashfs_filetype_table[1]) < 0) {
  22856. + TRACE("Filldir returned less than 0\n");
  22857. + goto finish;
  22858. + }
  22859. + file->f_pos += size;
  22860. + }
  22861. +
  22862. + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
  22863. + SQUASHFS_I(i)->u.s2.directory_index_start,
  22864. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  22865. + SQUASHFS_I(i)->u.s2.directory_index_count,
  22866. + file->f_pos);
  22867. +
  22868. + while (length < i_size_read(i)) {
  22869. + /* read directory header */
  22870. + if (msblk->swap) {
  22871. + struct squashfs_dir_header sdirh;
  22872. +
  22873. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  22874. + next_block, next_offset, sizeof(sdirh),
  22875. + &next_block, &next_offset))
  22876. + goto failed_read;
  22877. +
  22878. + length += sizeof(sdirh);
  22879. + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
  22880. + } else {
  22881. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  22882. + next_block, next_offset, sizeof(dirh),
  22883. + &next_block, &next_offset))
  22884. + goto failed_read;
  22885. +
  22886. + length += sizeof(dirh);
  22887. + }
  22888. +
  22889. + dir_count = dirh.count + 1;
  22890. + while (dir_count--) {
  22891. + if (msblk->swap) {
  22892. + struct squashfs_dir_entry sdire;
  22893. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  22894. + &sdire, next_block, next_offset,
  22895. + sizeof(sdire), &next_block,
  22896. + &next_offset))
  22897. + goto failed_read;
  22898. +
  22899. + length += sizeof(sdire);
  22900. + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
  22901. + } else {
  22902. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  22903. + dire, next_block, next_offset,
  22904. + sizeof(*dire), &next_block,
  22905. + &next_offset))
  22906. + goto failed_read;
  22907. +
  22908. + length += sizeof(*dire);
  22909. + }
  22910. +
  22911. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  22912. + next_block, next_offset,
  22913. + dire->size + 1, &next_block,
  22914. + &next_offset))
  22915. + goto failed_read;
  22916. +
  22917. + length += dire->size + 1;
  22918. +
  22919. + if (file->f_pos >= length)
  22920. + continue;
  22921. +
  22922. + dire->name[dire->size + 1] = '\0';
  22923. +
  22924. + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
  22925. + (unsigned int) dirent, dire->name,
  22926. + dire->size + 1, (int) file->f_pos,
  22927. + dirh.start_block, dire->offset,
  22928. + dirh.inode_number + dire->inode_number,
  22929. + squashfs_filetype_table[dire->type]);
  22930. +
  22931. + if (filldir(dirent, dire->name, dire->size + 1,
  22932. + file->f_pos,
  22933. + dirh.inode_number + dire->inode_number,
  22934. + squashfs_filetype_table[dire->type])
  22935. + < 0) {
  22936. + TRACE("Filldir returned less than 0\n");
  22937. + goto finish;
  22938. + }
  22939. + file->f_pos = length;
  22940. + }
  22941. + }
  22942. +
  22943. +finish:
  22944. + kfree(dire);
  22945. + return 0;
  22946. +
  22947. +failed_read:
  22948. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  22949. + next_offset);
  22950. + kfree(dire);
  22951. + return 0;
  22952. +}
  22953. +
  22954. +
  22955. +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
  22956. + struct nameidata *nd)
  22957. +{
  22958. + const unsigned char *name = dentry->d_name.name;
  22959. + int len = dentry->d_name.len;
  22960. + struct inode *inode = NULL;
  22961. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  22962. + struct squashfs_super_block *sblk = &msblk->sblk;
  22963. + long long next_block = SQUASHFS_I(i)->start_block +
  22964. + sblk->directory_table_start;
  22965. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  22966. + dir_count;
  22967. + struct squashfs_dir_header dirh;
  22968. + struct squashfs_dir_entry *dire;
  22969. +
  22970. + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
  22971. +
  22972. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  22973. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  22974. + ERROR("Failed to allocate squashfs_dir_entry\n");
  22975. + goto exit_lookup;
  22976. + }
  22977. +
  22978. + if (len > SQUASHFS_NAME_LEN)
  22979. + goto exit_lookup;
  22980. +
  22981. + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
  22982. + SQUASHFS_I(i)->u.s2.directory_index_start,
  22983. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  22984. + SQUASHFS_I(i)->u.s2.directory_index_count, name,
  22985. + len);
  22986. +
  22987. + while (length < i_size_read(i)) {
  22988. + /* read directory header */
  22989. + if (msblk->swap) {
  22990. + struct squashfs_dir_header sdirh;
  22991. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  22992. + next_block, next_offset, sizeof(sdirh),
  22993. + &next_block, &next_offset))
  22994. + goto failed_read;
  22995. +
  22996. + length += sizeof(sdirh);
  22997. + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
  22998. + } else {
  22999. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  23000. + next_block, next_offset, sizeof(dirh),
  23001. + &next_block, &next_offset))
  23002. + goto failed_read;
  23003. +
  23004. + length += sizeof(dirh);
  23005. + }
  23006. +
  23007. + dir_count = dirh.count + 1;
  23008. + while (dir_count--) {
  23009. + if (msblk->swap) {
  23010. + struct squashfs_dir_entry sdire;
  23011. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23012. + &sdire, next_block,next_offset,
  23013. + sizeof(sdire), &next_block,
  23014. + &next_offset))
  23015. + goto failed_read;
  23016. +
  23017. + length += sizeof(sdire);
  23018. + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
  23019. + } else {
  23020. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23021. + dire, next_block,next_offset,
  23022. + sizeof(*dire), &next_block,
  23023. + &next_offset))
  23024. + goto failed_read;
  23025. +
  23026. + length += sizeof(*dire);
  23027. + }
  23028. +
  23029. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  23030. + next_block, next_offset, dire->size + 1,
  23031. + &next_block, &next_offset))
  23032. + goto failed_read;
  23033. +
  23034. + length += dire->size + 1;
  23035. +
  23036. + if (name[0] < dire->name[0])
  23037. + goto exit_lookup;
  23038. +
  23039. + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
  23040. + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,
  23041. + dire->offset);
  23042. +
  23043. + TRACE("calling squashfs_iget for directory "
  23044. + "entry %s, inode %x:%x, %d\n", name,
  23045. + dirh.start_block, dire->offset,
  23046. + dirh.inode_number + dire->inode_number);
  23047. +
  23048. + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);
  23049. +
  23050. + goto exit_lookup;
  23051. + }
  23052. + }
  23053. + }
  23054. +
  23055. +exit_lookup:
  23056. + kfree(dire);
  23057. + if (inode)
  23058. + return d_splice_alias(inode, dentry);
  23059. + d_add(dentry, inode);
  23060. + return ERR_PTR(0);
  23061. +
  23062. +failed_read:
  23063. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  23064. + next_offset);
  23065. + goto exit_lookup;
  23066. +}
  23067. +
  23068. +
  23069. +static int squashfs_remount(struct super_block *s, int *flags, char *data)
  23070. +{
  23071. + *flags |= MS_RDONLY;
  23072. + return 0;
  23073. +}
  23074. +
  23075. +
  23076. +static void squashfs_put_super(struct super_block *s)
  23077. +{
  23078. + int i;
  23079. +
  23080. + if (s->s_fs_info) {
  23081. + struct squashfs_sb_info *sbi = s->s_fs_info;
  23082. + if (sbi->block_cache)
  23083. + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
  23084. + if (sbi->block_cache[i].block !=
  23085. + SQUASHFS_INVALID_BLK)
  23086. + kfree(sbi->block_cache[i].data);
  23087. + if (sbi->fragment)
  23088. + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
  23089. + SQUASHFS_FREE(sbi->fragment[i].data);
  23090. + kfree(sbi->fragment);
  23091. + kfree(sbi->block_cache);
  23092. + kfree(sbi->read_page);
  23093. + kfree(sbi->uid);
  23094. + kfree(sbi->fragment_index);
  23095. + kfree(sbi->fragment_index_2);
  23096. + kfree(sbi->meta_index);
  23097. + vfree(sbi->stream.workspace);
  23098. + kfree(s->s_fs_info);
  23099. + s->s_fs_info = NULL;
  23100. + }
  23101. +}
  23102. +
  23103. +
  23104. +static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
  23105. + const char *dev_name, void *data,
  23106. + struct vfsmount *mnt)
  23107. +{
  23108. + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
  23109. + mnt);
  23110. +}
  23111. +
  23112. +
  23113. +static int __init init_squashfs_fs(void)
  23114. +{
  23115. + int err = init_inodecache();
  23116. + if (err)
  23117. + goto out;
  23118. +
  23119. + printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "
  23120. + "Phillip Lougher\n");
  23121. +
  23122. + if ((err = register_filesystem(&squashfs_fs_type)))
  23123. + destroy_inodecache();
  23124. +
  23125. +out:
  23126. + return err;
  23127. +}
  23128. +
  23129. +
  23130. +static void __exit exit_squashfs_fs(void)
  23131. +{
  23132. + unregister_filesystem(&squashfs_fs_type);
  23133. + destroy_inodecache();
  23134. +}
  23135. +
  23136. +
  23137. +static struct kmem_cache * squashfs_inode_cachep;
  23138. +
  23139. +
  23140. +static struct inode *squashfs_alloc_inode(struct super_block *sb)
  23141. +{
  23142. + struct squashfs_inode_info *ei;
  23143. + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
  23144. + if (!ei)
  23145. + return NULL;
  23146. + return &ei->vfs_inode;
  23147. +}
  23148. +
  23149. +
  23150. +static void squashfs_destroy_inode(struct inode *inode)
  23151. +{
  23152. + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
  23153. +}
  23154. +
  23155. +
  23156. +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
  23157. +{
  23158. + struct squashfs_inode_info *ei = foo;
  23159. +
  23160. + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
  23161. + SLAB_CTOR_CONSTRUCTOR)
  23162. + inode_init_once(&ei->vfs_inode);
  23163. +}
  23164. +
  23165. +
  23166. +static int __init init_inodecache(void)
  23167. +{
  23168. + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
  23169. + sizeof(struct squashfs_inode_info),
  23170. + 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
  23171. + init_once, NULL);
  23172. + if (squashfs_inode_cachep == NULL)
  23173. + return -ENOMEM;
  23174. + return 0;
  23175. +}
  23176. +
  23177. +
  23178. +static void destroy_inodecache(void)
  23179. +{
  23180. + kmem_cache_destroy(squashfs_inode_cachep);
  23181. +}
  23182. +
  23183. +
  23184. +module_init(init_squashfs_fs);
  23185. +module_exit(exit_squashfs_fs);
  23186. +MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem");
  23187. +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
  23188. +MODULE_LICENSE("GPL");
  23189. diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/squashfs.h linux-2.6.22.1/fs/squashfs/squashfs.h
  23190. --- linux-2.6.22.1.oorig/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100
  23191. +++ linux-2.6.22.1/fs/squashfs/squashfs.h 2007-07-24 14:17:46.000000000 +0200
  23192. @@ -0,0 +1,87 @@
  23193. +/*
  23194. + * Squashfs - a compressed read only filesystem for Linux
  23195. + *
  23196. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  23197. + * Phillip Lougher <phillip@lougher.org.uk>
  23198. + *
  23199. + * This program is free software; you can redistribute it and/or
  23200. + * modify it under the terms of the GNU General Public License
  23201. + * as published by the Free Software Foundation; either version 2,
  23202. + * or (at your option) any later version.
  23203. + *
  23204. + * This program is distributed in the hope that it will be useful,
  23205. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23206. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23207. + * GNU General Public License for more details.
  23208. + *
  23209. + * You should have received a copy of the GNU General Public License
  23210. + * along with this program; if not, write to the Free Software
  23211. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23212. + *
  23213. + * squashfs.h
  23214. + */
  23215. +
  23216. +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  23217. +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  23218. +#endif
  23219. +
  23220. +#ifdef SQUASHFS_TRACE
  23221. +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
  23222. +#else
  23223. +#define TRACE(s, args...) {}
  23224. +#endif
  23225. +
  23226. +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
  23227. +
  23228. +#define SERROR(s, args...) do { \
  23229. + if (!silent) \
  23230. + printk(KERN_ERR "SQUASHFS error: "s, ## args);\
  23231. + } while(0)
  23232. +
  23233. +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
  23234. +
  23235. +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
  23236. +{
  23237. + return list_entry(inode, struct squashfs_inode_info, vfs_inode);
  23238. +}
  23239. +
  23240. +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
  23241. +#define SQSH_EXTERN
  23242. +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
  23243. + long long index, unsigned int length,
  23244. + long long *next_index, int srclength);
  23245. +extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
  23246. + long long block, unsigned int offset,
  23247. + int length, long long *next_block,
  23248. + unsigned int *next_offset);
  23249. +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
  23250. + squashfs_fragment_cache *fragment);
  23251. +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
  23252. + *s, long long start_block,
  23253. + int length);
  23254. +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);
  23255. +extern const struct address_space_operations squashfs_symlink_aops;
  23256. +extern const struct address_space_operations squashfs_aops;
  23257. +extern const struct address_space_operations squashfs_aops_4K;
  23258. +extern struct inode_operations squashfs_dir_inode_ops;
  23259. +#else
  23260. +#define SQSH_EXTERN static
  23261. +#endif
  23262. +
  23263. +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  23264. +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
  23265. +#else
  23266. +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
  23267. +{
  23268. + return 0;
  23269. +}
  23270. +#endif
  23271. +
  23272. +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
  23273. +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
  23274. +#else
  23275. +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
  23276. +{
  23277. + return 0;
  23278. +}
  23279. +#endif
  23280. diff -rduNp linux-2.6.22.1.oorig/fs/squashfs/squashfs2_0.c linux-2.6.22.1/fs/squashfs/squashfs2_0.c
  23281. --- linux-2.6.22.1.oorig/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100
  23282. +++ linux-2.6.22.1/fs/squashfs/squashfs2_0.c 2007-07-24 14:17:46.000000000 +0200
  23283. @@ -0,0 +1,742 @@
  23284. +/*
  23285. + * Squashfs - a compressed read only filesystem for Linux
  23286. + *
  23287. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  23288. + * Phillip Lougher <phillip@lougher.org.uk>
  23289. + *
  23290. + * This program is free software; you can redistribute it and/or
  23291. + * modify it under the terms of the GNU General Public License
  23292. + * as published by the Free Software Foundation; either version 2,
  23293. + * or (at your option) any later version.
  23294. + *
  23295. + * This program is distributed in the hope that it will be useful,
  23296. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23297. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23298. + * GNU General Public License for more details.
  23299. + *
  23300. + * You should have received a copy of the GNU General Public License
  23301. + * along with this program; if not, write to the Free Software
  23302. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23303. + *
  23304. + * squashfs2_0.c
  23305. + */
  23306. +
  23307. +#include <linux/squashfs_fs.h>
  23308. +#include <linux/module.h>
  23309. +#include <linux/zlib.h>
  23310. +#include <linux/fs.h>
  23311. +#include <linux/squashfs_fs_sb.h>
  23312. +#include <linux/squashfs_fs_i.h>
  23313. +
  23314. +#include "squashfs.h"
  23315. +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
  23316. +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
  23317. + struct nameidata *);
  23318. +
  23319. +static struct file_operations squashfs_dir_ops_2 = {
  23320. + .read = generic_read_dir,
  23321. + .readdir = squashfs_readdir_2
  23322. +};
  23323. +
  23324. +static struct inode_operations squashfs_dir_inode_ops_2 = {
  23325. + .lookup = squashfs_lookup_2
  23326. +};
  23327. +
  23328. +static unsigned char squashfs_filetype_table[] = {
  23329. + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
  23330. +};
  23331. +
  23332. +static int read_fragment_index_table_2(struct super_block *s)
  23333. +{
  23334. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23335. + struct squashfs_super_block *sblk = &msblk->sblk;
  23336. +
  23337. + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
  23338. + (sblk->fragments), GFP_KERNEL))) {
  23339. + ERROR("Failed to allocate uid/gid table\n");
  23340. + return 0;
  23341. + }
  23342. +
  23343. + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
  23344. + !squashfs_read_data(s, (char *)
  23345. + msblk->fragment_index_2,
  23346. + sblk->fragment_table_start,
  23347. + SQUASHFS_FRAGMENT_INDEX_BYTES_2
  23348. + (sblk->fragments) |
  23349. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
  23350. + ERROR("unable to read fragment index table\n");
  23351. + return 0;
  23352. + }
  23353. +
  23354. + if (msblk->swap) {
  23355. + int i;
  23356. + unsigned int fragment;
  23357. +
  23358. + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
  23359. + i++) {
  23360. + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
  23361. + &msblk->fragment_index_2[i], 1);
  23362. + msblk->fragment_index_2[i] = fragment;
  23363. + }
  23364. + }
  23365. +
  23366. + return 1;
  23367. +}
  23368. +
  23369. +
  23370. +static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
  23371. + long long *fragment_start_block,
  23372. + unsigned int *fragment_size)
  23373. +{
  23374. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23375. + long long start_block =
  23376. + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
  23377. + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
  23378. + struct squashfs_fragment_entry_2 fragment_entry;
  23379. +
  23380. + if (msblk->swap) {
  23381. + struct squashfs_fragment_entry_2 sfragment_entry;
  23382. +
  23383. + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
  23384. + start_block, offset,
  23385. + sizeof(sfragment_entry), &start_block,
  23386. + &offset))
  23387. + goto out;
  23388. + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
  23389. + } else
  23390. + if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
  23391. + start_block, offset,
  23392. + sizeof(fragment_entry), &start_block,
  23393. + &offset))
  23394. + goto out;
  23395. +
  23396. + *fragment_start_block = fragment_entry.start_block;
  23397. + *fragment_size = fragment_entry.size;
  23398. +
  23399. + return 1;
  23400. +
  23401. +out:
  23402. + return 0;
  23403. +}
  23404. +
  23405. +
  23406. +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
  23407. + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
  23408. +{
  23409. + struct squashfs_super_block *sblk = &msblk->sblk;
  23410. +
  23411. + i->i_ino = ino;
  23412. + i->i_mtime.tv_sec = sblk->mkfs_time;
  23413. + i->i_atime.tv_sec = sblk->mkfs_time;
  23414. + i->i_ctime.tv_sec = sblk->mkfs_time;
  23415. + i->i_uid = msblk->uid[inodeb->uid];
  23416. + i->i_mode = inodeb->mode;
  23417. + i->i_nlink = 1;
  23418. + i->i_size = 0;
  23419. + if (inodeb->guid == SQUASHFS_GUIDS)
  23420. + i->i_gid = i->i_uid;
  23421. + else
  23422. + i->i_gid = msblk->guid[inodeb->guid];
  23423. +}
  23424. +
  23425. +
  23426. +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
  23427. +{
  23428. + struct super_block *s = i->i_sb;
  23429. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23430. + struct squashfs_super_block *sblk = &msblk->sblk;
  23431. + unsigned int block = SQUASHFS_INODE_BLK(inode) +
  23432. + sblk->inode_table_start;
  23433. + unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
  23434. + unsigned int ino = i->i_ino;
  23435. + long long next_block;
  23436. + unsigned int next_offset;
  23437. + union squashfs_inode_header_2 id, sid;
  23438. + struct squashfs_base_inode_header_2 *inodeb = &id.base,
  23439. + *sinodeb = &sid.base;
  23440. +
  23441. + TRACE("Entered squashfs_iget\n");
  23442. +
  23443. + if (msblk->swap) {
  23444. + if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
  23445. + offset, sizeof(*sinodeb), &next_block,
  23446. + &next_offset))
  23447. + goto failed_read;
  23448. + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
  23449. + sizeof(*sinodeb));
  23450. + } else
  23451. + if (!squashfs_get_cached_block(s, (char *) inodeb, block,
  23452. + offset, sizeof(*inodeb), &next_block,
  23453. + &next_offset))
  23454. + goto failed_read;
  23455. +
  23456. + squashfs_new_inode(msblk, i, inodeb, ino);
  23457. +
  23458. + switch(inodeb->inode_type) {
  23459. + case SQUASHFS_FILE_TYPE: {
  23460. + struct squashfs_reg_inode_header_2 *inodep = &id.reg;
  23461. + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
  23462. + long long frag_blk;
  23463. + unsigned int frag_size = 0;
  23464. +
  23465. + if (msblk->swap) {
  23466. + if (!squashfs_get_cached_block(s, (char *)
  23467. + sinodep, block, offset,
  23468. + sizeof(*sinodep), &next_block,
  23469. + &next_offset))
  23470. + goto failed_read;
  23471. + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
  23472. + } else
  23473. + if (!squashfs_get_cached_block(s, (char *)
  23474. + inodep, block, offset,
  23475. + sizeof(*inodep), &next_block,
  23476. + &next_offset))
  23477. + goto failed_read;
  23478. +
  23479. + frag_blk = SQUASHFS_INVALID_BLK;
  23480. + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
  23481. + !get_fragment_location_2(s,
  23482. + inodep->fragment, &frag_blk, &frag_size))
  23483. + goto failed_read;
  23484. +
  23485. + i->i_size = inodep->file_size;
  23486. + i->i_fop = &generic_ro_fops;
  23487. + i->i_mode |= S_IFREG;
  23488. + i->i_mtime.tv_sec = inodep->mtime;
  23489. + i->i_atime.tv_sec = inodep->mtime;
  23490. + i->i_ctime.tv_sec = inodep->mtime;
  23491. + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
  23492. + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
  23493. + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
  23494. + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
  23495. + SQUASHFS_I(i)->start_block = inodep->start_block;
  23496. + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
  23497. + SQUASHFS_I(i)->offset = next_offset;
  23498. + if (sblk->block_size > 4096)
  23499. + i->i_data.a_ops = &squashfs_aops;
  23500. + else
  23501. + i->i_data.a_ops = &squashfs_aops_4K;
  23502. +
  23503. + TRACE("File inode %x:%x, start_block %x, "
  23504. + "block_list_start %llx, offset %x\n",
  23505. + SQUASHFS_INODE_BLK(inode), offset,
  23506. + inodep->start_block, next_block,
  23507. + next_offset);
  23508. + break;
  23509. + }
  23510. + case SQUASHFS_DIR_TYPE: {
  23511. + struct squashfs_dir_inode_header_2 *inodep = &id.dir;
  23512. + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
  23513. +
  23514. + if (msblk->swap) {
  23515. + if (!squashfs_get_cached_block(s, (char *)
  23516. + sinodep, block, offset,
  23517. + sizeof(*sinodep), &next_block,
  23518. + &next_offset))
  23519. + goto failed_read;
  23520. + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
  23521. + } else
  23522. + if (!squashfs_get_cached_block(s, (char *)
  23523. + inodep, block, offset,
  23524. + sizeof(*inodep), &next_block,
  23525. + &next_offset))
  23526. + goto failed_read;
  23527. +
  23528. + i->i_size = inodep->file_size;
  23529. + i->i_op = &squashfs_dir_inode_ops_2;
  23530. + i->i_fop = &squashfs_dir_ops_2;
  23531. + i->i_mode |= S_IFDIR;
  23532. + i->i_mtime.tv_sec = inodep->mtime;
  23533. + i->i_atime.tv_sec = inodep->mtime;
  23534. + i->i_ctime.tv_sec = inodep->mtime;
  23535. + SQUASHFS_I(i)->start_block = inodep->start_block;
  23536. + SQUASHFS_I(i)->offset = inodep->offset;
  23537. + SQUASHFS_I(i)->u.s2.directory_index_count = 0;
  23538. + SQUASHFS_I(i)->u.s2.parent_inode = 0;
  23539. +
  23540. + TRACE("Directory inode %x:%x, start_block %x, offset "
  23541. + "%x\n", SQUASHFS_INODE_BLK(inode),
  23542. + offset, inodep->start_block,
  23543. + inodep->offset);
  23544. + break;
  23545. + }
  23546. + case SQUASHFS_LDIR_TYPE: {
  23547. + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
  23548. + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
  23549. +
  23550. + if (msblk->swap) {
  23551. + if (!squashfs_get_cached_block(s, (char *)
  23552. + sinodep, block, offset,
  23553. + sizeof(*sinodep), &next_block,
  23554. + &next_offset))
  23555. + goto failed_read;
  23556. + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
  23557. + sinodep);
  23558. + } else
  23559. + if (!squashfs_get_cached_block(s, (char *)
  23560. + inodep, block, offset,
  23561. + sizeof(*inodep), &next_block,
  23562. + &next_offset))
  23563. + goto failed_read;
  23564. +
  23565. + i->i_size = inodep->file_size;
  23566. + i->i_op = &squashfs_dir_inode_ops_2;
  23567. + i->i_fop = &squashfs_dir_ops_2;
  23568. + i->i_mode |= S_IFDIR;
  23569. + i->i_mtime.tv_sec = inodep->mtime;
  23570. + i->i_atime.tv_sec = inodep->mtime;
  23571. + i->i_ctime.tv_sec = inodep->mtime;
  23572. + SQUASHFS_I(i)->start_block = inodep->start_block;
  23573. + SQUASHFS_I(i)->offset = inodep->offset;
  23574. + SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
  23575. + SQUASHFS_I(i)->u.s2.directory_index_offset =
  23576. + next_offset;
  23577. + SQUASHFS_I(i)->u.s2.directory_index_count =
  23578. + inodep->i_count;
  23579. + SQUASHFS_I(i)->u.s2.parent_inode = 0;
  23580. +
  23581. + TRACE("Long directory inode %x:%x, start_block %x, "
  23582. + "offset %x\n",
  23583. + SQUASHFS_INODE_BLK(inode), offset,
  23584. + inodep->start_block, inodep->offset);
  23585. + break;
  23586. + }
  23587. + case SQUASHFS_SYMLINK_TYPE: {
  23588. + struct squashfs_symlink_inode_header_2 *inodep =
  23589. + &id.symlink;
  23590. + struct squashfs_symlink_inode_header_2 *sinodep =
  23591. + &sid.symlink;
  23592. +
  23593. + if (msblk->swap) {
  23594. + if (!squashfs_get_cached_block(s, (char *)
  23595. + sinodep, block, offset,
  23596. + sizeof(*sinodep), &next_block,
  23597. + &next_offset))
  23598. + goto failed_read;
  23599. + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
  23600. + sinodep);
  23601. + } else
  23602. + if (!squashfs_get_cached_block(s, (char *)
  23603. + inodep, block, offset,
  23604. + sizeof(*inodep), &next_block,
  23605. + &next_offset))
  23606. + goto failed_read;
  23607. +
  23608. + i->i_size = inodep->symlink_size;
  23609. + i->i_op = &page_symlink_inode_operations;
  23610. + i->i_data.a_ops = &squashfs_symlink_aops;
  23611. + i->i_mode |= S_IFLNK;
  23612. + SQUASHFS_I(i)->start_block = next_block;
  23613. + SQUASHFS_I(i)->offset = next_offset;
  23614. +
  23615. + TRACE("Symbolic link inode %x:%x, start_block %llx, "
  23616. + "offset %x\n",
  23617. + SQUASHFS_INODE_BLK(inode), offset,
  23618. + next_block, next_offset);
  23619. + break;
  23620. + }
  23621. + case SQUASHFS_BLKDEV_TYPE:
  23622. + case SQUASHFS_CHRDEV_TYPE: {
  23623. + struct squashfs_dev_inode_header_2 *inodep = &id.dev;
  23624. + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
  23625. +
  23626. + if (msblk->swap) {
  23627. + if (!squashfs_get_cached_block(s, (char *)
  23628. + sinodep, block, offset,
  23629. + sizeof(*sinodep), &next_block,
  23630. + &next_offset))
  23631. + goto failed_read;
  23632. + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
  23633. + } else
  23634. + if (!squashfs_get_cached_block(s, (char *)
  23635. + inodep, block, offset,
  23636. + sizeof(*inodep), &next_block,
  23637. + &next_offset))
  23638. + goto failed_read;
  23639. +
  23640. + i->i_mode |= (inodeb->inode_type ==
  23641. + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
  23642. + S_IFBLK;
  23643. + init_special_inode(i, i->i_mode,
  23644. + old_decode_dev(inodep->rdev));
  23645. +
  23646. + TRACE("Device inode %x:%x, rdev %x\n",
  23647. + SQUASHFS_INODE_BLK(inode), offset,
  23648. + inodep->rdev);
  23649. + break;
  23650. + }
  23651. + case SQUASHFS_FIFO_TYPE:
  23652. + case SQUASHFS_SOCKET_TYPE: {
  23653. +
  23654. + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
  23655. + ? S_IFIFO : S_IFSOCK;
  23656. + init_special_inode(i, i->i_mode, 0);
  23657. + break;
  23658. + }
  23659. + default:
  23660. + ERROR("Unknown inode type %d in squashfs_iget!\n",
  23661. + inodeb->inode_type);
  23662. + goto failed_read1;
  23663. + }
  23664. +
  23665. + return 1;
  23666. +
  23667. +failed_read:
  23668. + ERROR("Unable to read inode [%x:%x]\n", block, offset);
  23669. +
  23670. +failed_read1:
  23671. + return 0;
  23672. +}
  23673. +
  23674. +
  23675. +static int get_dir_index_using_offset(struct super_block *s, long long
  23676. + *next_block, unsigned int *next_offset,
  23677. + long long index_start,
  23678. + unsigned int index_offset, int i_count,
  23679. + long long f_pos)
  23680. +{
  23681. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23682. + struct squashfs_super_block *sblk = &msblk->sblk;
  23683. + int i, length = 0;
  23684. + struct squashfs_dir_index_2 index;
  23685. +
  23686. + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
  23687. + i_count, (unsigned int) f_pos);
  23688. +
  23689. + if (f_pos == 0)
  23690. + goto finish;
  23691. +
  23692. + for (i = 0; i < i_count; i++) {
  23693. + if (msblk->swap) {
  23694. + struct squashfs_dir_index_2 sindex;
  23695. + squashfs_get_cached_block(s, (char *) &sindex,
  23696. + index_start, index_offset,
  23697. + sizeof(sindex), &index_start,
  23698. + &index_offset);
  23699. + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
  23700. + } else
  23701. + squashfs_get_cached_block(s, (char *) &index,
  23702. + index_start, index_offset,
  23703. + sizeof(index), &index_start,
  23704. + &index_offset);
  23705. +
  23706. + if (index.index > f_pos)
  23707. + break;
  23708. +
  23709. + squashfs_get_cached_block(s, NULL, index_start, index_offset,
  23710. + index.size + 1, &index_start,
  23711. + &index_offset);
  23712. +
  23713. + length = index.index;
  23714. + *next_block = index.start_block + sblk->directory_table_start;
  23715. + }
  23716. +
  23717. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  23718. +
  23719. +finish:
  23720. + return length;
  23721. +}
  23722. +
  23723. +
  23724. +static int get_dir_index_using_name(struct super_block *s, long long
  23725. + *next_block, unsigned int *next_offset,
  23726. + long long index_start,
  23727. + unsigned int index_offset, int i_count,
  23728. + const char *name, int size)
  23729. +{
  23730. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23731. + struct squashfs_super_block *sblk = &msblk->sblk;
  23732. + int i, length = 0;
  23733. + struct squashfs_dir_index_2 *index;
  23734. + char *str;
  23735. +
  23736. + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
  23737. +
  23738. + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
  23739. + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
  23740. + ERROR("Failed to allocate squashfs_dir_index\n");
  23741. + goto failure;
  23742. + }
  23743. +
  23744. + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
  23745. + strncpy(str, name, size);
  23746. + str[size] = '\0';
  23747. +
  23748. + for (i = 0; i < i_count; i++) {
  23749. + if (msblk->swap) {
  23750. + struct squashfs_dir_index_2 sindex;
  23751. + squashfs_get_cached_block(s, (char *) &sindex,
  23752. + index_start, index_offset,
  23753. + sizeof(sindex), &index_start,
  23754. + &index_offset);
  23755. + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
  23756. + } else
  23757. + squashfs_get_cached_block(s, (char *) index,
  23758. + index_start, index_offset,
  23759. + sizeof(struct squashfs_dir_index_2),
  23760. + &index_start, &index_offset);
  23761. +
  23762. + squashfs_get_cached_block(s, index->name, index_start,
  23763. + index_offset, index->size + 1,
  23764. + &index_start, &index_offset);
  23765. +
  23766. + index->name[index->size + 1] = '\0';
  23767. +
  23768. + if (strcmp(index->name, str) > 0)
  23769. + break;
  23770. +
  23771. + length = index->index;
  23772. + *next_block = index->start_block + sblk->directory_table_start;
  23773. + }
  23774. +
  23775. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  23776. + kfree(str);
  23777. +failure:
  23778. + return length;
  23779. +}
  23780. +
  23781. +
  23782. +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
  23783. +{
  23784. + struct inode *i = file->f_dentry->d_inode;
  23785. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  23786. + struct squashfs_super_block *sblk = &msblk->sblk;
  23787. + long long next_block = SQUASHFS_I(i)->start_block +
  23788. + sblk->directory_table_start;
  23789. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  23790. + dir_count;
  23791. + struct squashfs_dir_header_2 dirh;
  23792. + struct squashfs_dir_entry_2 *dire;
  23793. +
  23794. + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
  23795. +
  23796. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  23797. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  23798. + ERROR("Failed to allocate squashfs_dir_entry\n");
  23799. + goto finish;
  23800. + }
  23801. +
  23802. + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
  23803. + SQUASHFS_I(i)->u.s2.directory_index_start,
  23804. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  23805. + SQUASHFS_I(i)->u.s2.directory_index_count,
  23806. + file->f_pos);
  23807. +
  23808. + while (length < i_size_read(i)) {
  23809. + /* read directory header */
  23810. + if (msblk->swap) {
  23811. + struct squashfs_dir_header_2 sdirh;
  23812. +
  23813. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  23814. + next_block, next_offset, sizeof(sdirh),
  23815. + &next_block, &next_offset))
  23816. + goto failed_read;
  23817. +
  23818. + length += sizeof(sdirh);
  23819. + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
  23820. + } else {
  23821. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  23822. + next_block, next_offset, sizeof(dirh),
  23823. + &next_block, &next_offset))
  23824. + goto failed_read;
  23825. +
  23826. + length += sizeof(dirh);
  23827. + }
  23828. +
  23829. + dir_count = dirh.count + 1;
  23830. + while (dir_count--) {
  23831. + if (msblk->swap) {
  23832. + struct squashfs_dir_entry_2 sdire;
  23833. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23834. + &sdire, next_block, next_offset,
  23835. + sizeof(sdire), &next_block,
  23836. + &next_offset))
  23837. + goto failed_read;
  23838. +
  23839. + length += sizeof(sdire);
  23840. + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
  23841. + } else {
  23842. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23843. + dire, next_block, next_offset,
  23844. + sizeof(*dire), &next_block,
  23845. + &next_offset))
  23846. + goto failed_read;
  23847. +
  23848. + length += sizeof(*dire);
  23849. + }
  23850. +
  23851. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  23852. + next_block, next_offset,
  23853. + dire->size + 1, &next_block,
  23854. + &next_offset))
  23855. + goto failed_read;
  23856. +
  23857. + length += dire->size + 1;
  23858. +
  23859. + if (file->f_pos >= length)
  23860. + continue;
  23861. +
  23862. + dire->name[dire->size + 1] = '\0';
  23863. +
  23864. + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
  23865. + (unsigned int) dirent, dire->name,
  23866. + dire->size + 1, (int) file->f_pos,
  23867. + dirh.start_block, dire->offset,
  23868. + squashfs_filetype_table[dire->type]);
  23869. +
  23870. + if (filldir(dirent, dire->name, dire->size + 1,
  23871. + file->f_pos, SQUASHFS_MK_VFS_INODE(
  23872. + dirh.start_block, dire->offset),
  23873. + squashfs_filetype_table[dire->type])
  23874. + < 0) {
  23875. + TRACE("Filldir returned less than 0\n");
  23876. + goto finish;
  23877. + }
  23878. + file->f_pos = length;
  23879. + }
  23880. + }
  23881. +
  23882. +finish:
  23883. + kfree(dire);
  23884. + return 0;
  23885. +
  23886. +failed_read:
  23887. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  23888. + next_offset);
  23889. + kfree(dire);
  23890. + return 0;
  23891. +}
  23892. +
  23893. +
  23894. +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
  23895. + struct nameidata *nd)
  23896. +{
  23897. + const unsigned char *name = dentry->d_name.name;
  23898. + int len = dentry->d_name.len;
  23899. + struct inode *inode = NULL;
  23900. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  23901. + struct squashfs_super_block *sblk = &msblk->sblk;
  23902. + long long next_block = SQUASHFS_I(i)->start_block +
  23903. + sblk->directory_table_start;
  23904. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  23905. + dir_count;
  23906. + struct squashfs_dir_header_2 dirh;
  23907. + struct squashfs_dir_entry_2 *dire;
  23908. + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
  23909. +
  23910. + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
  23911. +
  23912. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  23913. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  23914. + ERROR("Failed to allocate squashfs_dir_entry\n");
  23915. + goto exit_loop;
  23916. + }
  23917. +
  23918. + if (len > SQUASHFS_NAME_LEN)
  23919. + goto exit_loop;
  23920. +
  23921. + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
  23922. + SQUASHFS_I(i)->u.s2.directory_index_start,
  23923. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  23924. + SQUASHFS_I(i)->u.s2.directory_index_count, name,
  23925. + len);
  23926. +
  23927. + while (length < i_size_read(i)) {
  23928. + /* read directory header */
  23929. + if (msblk->swap) {
  23930. + struct squashfs_dir_header_2 sdirh;
  23931. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  23932. + next_block, next_offset, sizeof(sdirh),
  23933. + &next_block, &next_offset))
  23934. + goto failed_read;
  23935. +
  23936. + length += sizeof(sdirh);
  23937. + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
  23938. + } else {
  23939. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  23940. + next_block, next_offset, sizeof(dirh),
  23941. + &next_block, &next_offset))
  23942. + goto failed_read;
  23943. +
  23944. + length += sizeof(dirh);
  23945. + }
  23946. +
  23947. + dir_count = dirh.count + 1;
  23948. + while (dir_count--) {
  23949. + if (msblk->swap) {
  23950. + struct squashfs_dir_entry_2 sdire;
  23951. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23952. + &sdire, next_block,next_offset,
  23953. + sizeof(sdire), &next_block,
  23954. + &next_offset))
  23955. + goto failed_read;
  23956. +
  23957. + length += sizeof(sdire);
  23958. + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
  23959. + } else {
  23960. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23961. + dire, next_block,next_offset,
  23962. + sizeof(*dire), &next_block,
  23963. + &next_offset))
  23964. + goto failed_read;
  23965. +
  23966. + length += sizeof(*dire);
  23967. + }
  23968. +
  23969. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  23970. + next_block, next_offset, dire->size + 1,
  23971. + &next_block, &next_offset))
  23972. + goto failed_read;
  23973. +
  23974. + length += dire->size + 1;
  23975. +
  23976. + if (sorted && name[0] < dire->name[0])
  23977. + goto exit_loop;
  23978. +
  23979. + if ((len == dire->size + 1) && !strncmp(name,
  23980. + dire->name, len)) {
  23981. + squashfs_inode_t ino =
  23982. + SQUASHFS_MKINODE(dirh.start_block,
  23983. + dire->offset);
  23984. + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
  23985. + dire->offset);
  23986. +
  23987. + TRACE("calling squashfs_iget for directory "
  23988. + "entry %s, inode %x:%x, %lld\n", name,
  23989. + dirh.start_block, dire->offset, ino);
  23990. +
  23991. + inode = squashfs_iget(i->i_sb, ino, inode_number);
  23992. +
  23993. + goto exit_loop;
  23994. + }
  23995. + }
  23996. + }
  23997. +
  23998. +exit_loop:
  23999. + kfree(dire);
  24000. + d_add(dentry, inode);
  24001. + return ERR_PTR(0);
  24002. +
  24003. +failed_read:
  24004. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  24005. + next_offset);
  24006. + goto exit_loop;
  24007. +}
  24008. +
  24009. +
  24010. +int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
  24011. +{
  24012. + struct squashfs_super_block *sblk = &msblk->sblk;
  24013. +
  24014. + msblk->read_inode = squashfs_read_inode_2;
  24015. + msblk->read_fragment_index_table = read_fragment_index_table_2;
  24016. +
  24017. + sblk->bytes_used = sblk->bytes_used_2;
  24018. + sblk->uid_start = sblk->uid_start_2;
  24019. + sblk->guid_start = sblk->guid_start_2;
  24020. + sblk->inode_table_start = sblk->inode_table_start_2;
  24021. + sblk->directory_table_start = sblk->directory_table_start_2;
  24022. + sblk->fragment_table_start = sblk->fragment_table_start_2;
  24023. +
  24024. + return 1;
  24025. +}
  24026. diff -rduNp linux-2.6.22.1.oorig/include/linux/aufs_type.h linux-2.6.22.1/include/linux/aufs_type.h
  24027. --- linux-2.6.22.1.oorig/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
  24028. +++ linux-2.6.22.1/include/linux/aufs_type.h 2007-07-24 14:17:46.000000000 +0200
  24029. @@ -0,0 +1,97 @@
  24030. +/*
  24031. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  24032. + *
  24033. + * This program, aufs is free software; you can redistribute it and/or modify
  24034. + * it under the terms of the GNU General Public License as published by
  24035. + * the Free Software Foundation; either version 2 of the License, or
  24036. + * (at your option) any later version.
  24037. + *
  24038. + * This program is distributed in the hope that it will be useful,
  24039. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24040. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24041. + * GNU General Public License for more details.
  24042. + *
  24043. + * You should have received a copy of the GNU General Public License
  24044. + * along with this program; if not, write to the Free Software
  24045. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  24046. + */
  24047. +
  24048. +/* $Id: aufs_type.h,v 1.55 2007/05/14 03:40:57 sfjro Exp $ */
  24049. +
  24050. +#include <linux/ioctl.h>
  24051. +
  24052. +#ifndef __AUFS_TYPE_H__
  24053. +#define __AUFS_TYPE_H__
  24054. +
  24055. +#define AUFS_VERSION "20070514"
  24056. +
  24057. +/* ---------------------------------------------------------------------- */
  24058. +
  24059. +#ifdef CONFIG_AUFS_BRANCH_MAX_127
  24060. +typedef char aufs_bindex_t;
  24061. +#define AUFS_BRANCH_MAX 127
  24062. +#else
  24063. +typedef short aufs_bindex_t;
  24064. +#ifdef CONFIG_AUFS_BRANCH_MAX_511
  24065. +#define AUFS_BRANCH_MAX 511
  24066. +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
  24067. +#define AUFS_BRANCH_MAX 1023
  24068. +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
  24069. +#define AUFS_BRANCH_MAX 32767
  24070. +#else
  24071. +#error unknown CONFIG_AUFS_BRANCH_MAX value
  24072. +#endif
  24073. +#endif
  24074. +
  24075. +#define AUFS_NAME "aufs"
  24076. +#define AUFS_FSTYPE AUFS_NAME
  24077. +
  24078. +#define AUFS_ROOT_INO 2
  24079. +#define AUFS_FIRST_INO 11
  24080. +
  24081. +#define AUFS_WH_PFX ".wh."
  24082. +#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
  24083. +#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
  24084. +#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
  24085. +#define AUFS_DIRWH_DEF 3
  24086. +#define AUFS_RDCACHE_DEF 10 /* seconds */
  24087. +#define AUFS_WKQ_NAME AUFS_NAME "d"
  24088. +#define AUFS_NWKQ_DEF 4
  24089. +
  24090. +#ifdef CONFIG_AUFS_COMPAT
  24091. +#define AUFS_DIROPQ_NAME "__dir_opaque"
  24092. +#else
  24093. +#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
  24094. +#endif
  24095. +#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
  24096. +
  24097. +/* will be whiteouted doubly */
  24098. +#define AUFS_WH_BASENAME AUFS_WH_PFX AUFS_NAME
  24099. +#define AUFS_WH_PLINKDIR AUFS_WH_PFX "plink"
  24100. +
  24101. +/* ---------------------------------------------------------------------- */
  24102. +
  24103. +/* ioctl */
  24104. +enum {AuCtlErr, AuCtlErr_Last};
  24105. +enum {
  24106. + AuCtl_REFRESH, //AuCtl_REFRESHV,
  24107. + //AuCtl_FLUSH_PLINK,
  24108. + //AuCtl_CPUP,
  24109. + AuCtl_CPDOWN, AuCtl_MVDOWN
  24110. +};
  24111. +
  24112. +struct aufs_ctl_cp {
  24113. + int bsrc, bdst;
  24114. + int err;
  24115. +};
  24116. +
  24117. +#define Type 'A'
  24118. +#define AUFS_CTL_REFRESH _IO(Type, AuCtl_REFRESH)
  24119. +//#define AUFS_CTL_REFRESHV _IO(Type, AuCtl_REFRESHV)
  24120. +//#define AUFS_CTL_FLUSH_PLINK _IOR(Type, AuCtl_FLUSH_PLINK)
  24121. +//#define AUFS_CTL_CPUP _IOWR(Type, AuCtl_CPUP, struct aufs_ctl_cp)
  24122. +#define AUFS_CTL_CPDOWN _IOWR(Type, AuCtl_CPDOWN, struct aufs_ctl_cp)
  24123. +#define AUFS_CTL_MVDOWN _IOWR(Type, AuCtl_MVDOWN, struct aufs_ctl_cp)
  24124. +#undef Type
  24125. +
  24126. +#endif /* __AUFS_TYPE_H__ */
  24127. diff -rduNp linux-2.6.22.1.oorig/include/linux/squashfs_fs.h linux-2.6.22.1/include/linux/squashfs_fs.h
  24128. --- linux-2.6.22.1.oorig/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100
  24129. +++ linux-2.6.22.1/include/linux/squashfs_fs.h 2007-07-24 14:17:46.000000000 +0200
  24130. @@ -0,0 +1,934 @@
  24131. +#ifndef SQUASHFS_FS
  24132. +#define SQUASHFS_FS
  24133. +
  24134. +/*
  24135. + * Squashfs
  24136. + *
  24137. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  24138. + * Phillip Lougher <phillip@lougher.org.uk>
  24139. + *
  24140. + * This program is free software; you can redistribute it and/or
  24141. + * modify it under the terms of the GNU General Public License
  24142. + * as published by the Free Software Foundation; either version 2,
  24143. + * or (at your option) any later version.
  24144. + *
  24145. + * This program is distributed in the hope that it will be useful,
  24146. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24147. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24148. + * GNU General Public License for more details.
  24149. + *
  24150. + * You should have received a copy of the GNU General Public License
  24151. + * along with this program; if not, write to the Free Software
  24152. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24153. + *
  24154. + * squashfs_fs.h
  24155. + */
  24156. +
  24157. +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
  24158. +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
  24159. +#endif
  24160. +
  24161. +#ifdef CONFIG_SQUASHFS_VMALLOC
  24162. +#define SQUASHFS_ALLOC(a) vmalloc(a)
  24163. +#define SQUASHFS_FREE(a) vfree(a)
  24164. +#else
  24165. +#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
  24166. +#define SQUASHFS_FREE(a) kfree(a)
  24167. +#endif
  24168. +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
  24169. +#define SQUASHFS_MAJOR 3
  24170. +#define SQUASHFS_MINOR 0
  24171. +#define SQUASHFS_MAGIC 0x73717368
  24172. +#define SQUASHFS_MAGIC_SWAP 0x68737173
  24173. +#define SQUASHFS_START 0
  24174. +
  24175. +/* size of metadata (inode and directory) blocks */
  24176. +#define SQUASHFS_METADATA_SIZE 8192
  24177. +#define SQUASHFS_METADATA_LOG 13
  24178. +
  24179. +/* default size of data blocks */
  24180. +#define SQUASHFS_FILE_SIZE 65536
  24181. +#define SQUASHFS_FILE_LOG 16
  24182. +
  24183. +#define SQUASHFS_FILE_MAX_SIZE 65536
  24184. +
  24185. +/* Max number of uids and gids */
  24186. +#define SQUASHFS_UIDS 256
  24187. +#define SQUASHFS_GUIDS 255
  24188. +
  24189. +/* Max length of filename (not 255) */
  24190. +#define SQUASHFS_NAME_LEN 256
  24191. +
  24192. +#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
  24193. +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
  24194. +#define SQUASHFS_INVALID_BLK ((long long) -1)
  24195. +#define SQUASHFS_USED_BLK ((long long) -2)
  24196. +
  24197. +/* Filesystem flags */
  24198. +#define SQUASHFS_NOI 0
  24199. +#define SQUASHFS_NOD 1
  24200. +#define SQUASHFS_CHECK 2
  24201. +#define SQUASHFS_NOF 3
  24202. +#define SQUASHFS_NO_FRAG 4
  24203. +#define SQUASHFS_ALWAYS_FRAG 5
  24204. +#define SQUASHFS_DUPLICATE 6
  24205. +#define SQUASHFS_EXPORT 7
  24206. +
  24207. +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
  24208. +
  24209. +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
  24210. + SQUASHFS_NOI)
  24211. +
  24212. +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
  24213. + SQUASHFS_NOD)
  24214. +
  24215. +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  24216. + SQUASHFS_NOF)
  24217. +
  24218. +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  24219. + SQUASHFS_NO_FRAG)
  24220. +
  24221. +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  24222. + SQUASHFS_ALWAYS_FRAG)
  24223. +
  24224. +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
  24225. + SQUASHFS_DUPLICATE)
  24226. +
  24227. +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
  24228. + SQUASHFS_EXPORT)
  24229. +
  24230. +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
  24231. + SQUASHFS_CHECK)
  24232. +
  24233. +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
  24234. + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \
  24235. + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
  24236. + (duplicate_checking << 6) | (exportable << 7))
  24237. +
  24238. +/* Max number of types and file types */
  24239. +#define SQUASHFS_DIR_TYPE 1
  24240. +#define SQUASHFS_FILE_TYPE 2
  24241. +#define SQUASHFS_SYMLINK_TYPE 3
  24242. +#define SQUASHFS_BLKDEV_TYPE 4
  24243. +#define SQUASHFS_CHRDEV_TYPE 5
  24244. +#define SQUASHFS_FIFO_TYPE 6
  24245. +#define SQUASHFS_SOCKET_TYPE 7
  24246. +#define SQUASHFS_LDIR_TYPE 8
  24247. +#define SQUASHFS_LREG_TYPE 9
  24248. +
  24249. +/* 1.0 filesystem type definitions */
  24250. +#define SQUASHFS_TYPES 5
  24251. +#define SQUASHFS_IPC_TYPE 0
  24252. +
  24253. +/* Flag whether block is compressed or uncompressed, bit is set if block is
  24254. + * uncompressed */
  24255. +#define SQUASHFS_COMPRESSED_BIT (1 << 15)
  24256. +
  24257. +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
  24258. + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
  24259. +
  24260. +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
  24261. +
  24262. +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
  24263. +
  24264. +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
  24265. + ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
  24266. + ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
  24267. +
  24268. +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
  24269. +
  24270. +/*
  24271. + * Inode number ops. Inodes consist of a compressed block number, and an
  24272. + * uncompressed offset within that block
  24273. + */
  24274. +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
  24275. +
  24276. +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
  24277. +
  24278. +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
  24279. + << 16) + (B)))
  24280. +
  24281. +/* Compute 32 bit VFS inode number from squashfs inode number */
  24282. +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
  24283. + ((b) >> 2) + 1))
  24284. +/* XXX */
  24285. +
  24286. +/* Translate between VFS mode and squashfs mode */
  24287. +#define SQUASHFS_MODE(a) ((a) & 0xfff)
  24288. +
  24289. +/* fragment and fragment table defines */
  24290. +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry))
  24291. +
  24292. +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
  24293. + SQUASHFS_METADATA_SIZE)
  24294. +
  24295. +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
  24296. + SQUASHFS_METADATA_SIZE)
  24297. +
  24298. +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
  24299. + SQUASHFS_METADATA_SIZE - 1) / \
  24300. + SQUASHFS_METADATA_SIZE)
  24301. +
  24302. +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
  24303. + sizeof(long long))
  24304. +
  24305. +/* inode lookup table defines */
  24306. +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t))
  24307. +
  24308. +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
  24309. + SQUASHFS_METADATA_SIZE)
  24310. +
  24311. +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
  24312. + SQUASHFS_METADATA_SIZE)
  24313. +
  24314. +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
  24315. + SQUASHFS_METADATA_SIZE - 1) / \
  24316. + SQUASHFS_METADATA_SIZE)
  24317. +
  24318. +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
  24319. + sizeof(long long))
  24320. +
  24321. +/* cached data constants for filesystem */
  24322. +#define SQUASHFS_CACHED_BLKS 8
  24323. +
  24324. +#define SQUASHFS_MAX_FILE_SIZE_LOG 64
  24325. +
  24326. +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
  24327. + (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
  24328. +
  24329. +#define SQUASHFS_MARKER_BYTE 0xff
  24330. +
  24331. +/* meta index cache */
  24332. +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
  24333. +#define SQUASHFS_META_ENTRIES 31
  24334. +#define SQUASHFS_META_NUMBER 8
  24335. +#define SQUASHFS_SLOTS 4
  24336. +
  24337. +struct meta_entry {
  24338. + long long data_block;
  24339. + unsigned int index_block;
  24340. + unsigned short offset;
  24341. + unsigned short pad;
  24342. +};
  24343. +
  24344. +struct meta_index {
  24345. + unsigned int inode_number;
  24346. + unsigned int offset;
  24347. + unsigned short entries;
  24348. + unsigned short skip;
  24349. + unsigned short locked;
  24350. + unsigned short pad;
  24351. + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
  24352. +};
  24353. +
  24354. +
  24355. +/*
  24356. + * definitions for structures on disk
  24357. + */
  24358. +
  24359. +typedef long long squashfs_block_t;
  24360. +typedef long long squashfs_inode_t;
  24361. +
  24362. +struct squashfs_super_block {
  24363. + unsigned int s_magic;
  24364. + unsigned int inodes;
  24365. + unsigned int bytes_used_2;
  24366. + unsigned int uid_start_2;
  24367. + unsigned int guid_start_2;
  24368. + unsigned int inode_table_start_2;
  24369. + unsigned int directory_table_start_2;
  24370. + unsigned int s_major:16;
  24371. + unsigned int s_minor:16;
  24372. + unsigned int block_size_1:16;
  24373. + unsigned int block_log:16;
  24374. + unsigned int flags:8;
  24375. + unsigned int no_uids:8;
  24376. + unsigned int no_guids:8;
  24377. + unsigned int mkfs_time /* time of filesystem creation */;
  24378. + squashfs_inode_t root_inode;
  24379. + unsigned int block_size;
  24380. + unsigned int fragments;
  24381. + unsigned int fragment_table_start_2;
  24382. + long long bytes_used;
  24383. + long long uid_start;
  24384. + long long guid_start;
  24385. + long long inode_table_start;
  24386. + long long directory_table_start;
  24387. + long long fragment_table_start;
  24388. + long long lookup_table_start;
  24389. +} __attribute__ ((packed));
  24390. +
  24391. +struct squashfs_dir_index {
  24392. + unsigned int index;
  24393. + unsigned int start_block;
  24394. + unsigned char size;
  24395. + unsigned char name[0];
  24396. +} __attribute__ ((packed));
  24397. +
  24398. +#define SQUASHFS_BASE_INODE_HEADER \
  24399. + unsigned int inode_type:4; \
  24400. + unsigned int mode:12; \
  24401. + unsigned int uid:8; \
  24402. + unsigned int guid:8; \
  24403. + unsigned int mtime; \
  24404. + unsigned int inode_number;
  24405. +
  24406. +struct squashfs_base_inode_header {
  24407. + SQUASHFS_BASE_INODE_HEADER;
  24408. +} __attribute__ ((packed));
  24409. +
  24410. +struct squashfs_ipc_inode_header {
  24411. + SQUASHFS_BASE_INODE_HEADER;
  24412. + unsigned int nlink;
  24413. +} __attribute__ ((packed));
  24414. +
  24415. +struct squashfs_dev_inode_header {
  24416. + SQUASHFS_BASE_INODE_HEADER;
  24417. + unsigned int nlink;
  24418. + unsigned short rdev;
  24419. +} __attribute__ ((packed));
  24420. +
  24421. +struct squashfs_symlink_inode_header {
  24422. + SQUASHFS_BASE_INODE_HEADER;
  24423. + unsigned int nlink;
  24424. + unsigned short symlink_size;
  24425. + char symlink[0];
  24426. +} __attribute__ ((packed));
  24427. +
  24428. +struct squashfs_reg_inode_header {
  24429. + SQUASHFS_BASE_INODE_HEADER;
  24430. + squashfs_block_t start_block;
  24431. + unsigned int fragment;
  24432. + unsigned int offset;
  24433. + unsigned int file_size;
  24434. + unsigned short block_list[0];
  24435. +} __attribute__ ((packed));
  24436. +
  24437. +struct squashfs_lreg_inode_header {
  24438. + SQUASHFS_BASE_INODE_HEADER;
  24439. + unsigned int nlink;
  24440. + squashfs_block_t start_block;
  24441. + unsigned int fragment;
  24442. + unsigned int offset;
  24443. + long long file_size;
  24444. + unsigned short block_list[0];
  24445. +} __attribute__ ((packed));
  24446. +
  24447. +struct squashfs_dir_inode_header {
  24448. + SQUASHFS_BASE_INODE_HEADER;
  24449. + unsigned int nlink;
  24450. + unsigned int file_size:19;
  24451. + unsigned int offset:13;
  24452. + unsigned int start_block;
  24453. + unsigned int parent_inode;
  24454. +} __attribute__ ((packed));
  24455. +
  24456. +struct squashfs_ldir_inode_header {
  24457. + SQUASHFS_BASE_INODE_HEADER;
  24458. + unsigned int nlink;
  24459. + unsigned int file_size:27;
  24460. + unsigned int offset:13;
  24461. + unsigned int start_block;
  24462. + unsigned int i_count:16;
  24463. + unsigned int parent_inode;
  24464. + struct squashfs_dir_index index[0];
  24465. +} __attribute__ ((packed));
  24466. +
  24467. +union squashfs_inode_header {
  24468. + struct squashfs_base_inode_header base;
  24469. + struct squashfs_dev_inode_header dev;
  24470. + struct squashfs_symlink_inode_header symlink;
  24471. + struct squashfs_reg_inode_header reg;
  24472. + struct squashfs_lreg_inode_header lreg;
  24473. + struct squashfs_dir_inode_header dir;
  24474. + struct squashfs_ldir_inode_header ldir;
  24475. + struct squashfs_ipc_inode_header ipc;
  24476. +};
  24477. +
  24478. +struct squashfs_dir_entry {
  24479. + unsigned int offset:13;
  24480. + unsigned int type:3;
  24481. + unsigned int size:8;
  24482. + int inode_number:16;
  24483. + char name[0];
  24484. +} __attribute__ ((packed));
  24485. +
  24486. +struct squashfs_dir_header {
  24487. + unsigned int count:8;
  24488. + unsigned int start_block;
  24489. + unsigned int inode_number;
  24490. +} __attribute__ ((packed));
  24491. +
  24492. +struct squashfs_fragment_entry {
  24493. + long long start_block;
  24494. + unsigned int size;
  24495. + unsigned int pending;
  24496. +} __attribute__ ((packed));
  24497. +
  24498. +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
  24499. +extern int squashfs_uncompress_init(void);
  24500. +extern int squashfs_uncompress_exit(void);
  24501. +
  24502. +/*
  24503. + * macros to convert each packed bitfield structure from little endian to big
  24504. + * endian and vice versa. These are needed when creating or using a filesystem
  24505. + * on a machine with different byte ordering to the target architecture.
  24506. + *
  24507. + */
  24508. +
  24509. +#define SQUASHFS_SWAP_START \
  24510. + int bits;\
  24511. + int b_pos;\
  24512. + unsigned long long val;\
  24513. + unsigned char *s;\
  24514. + unsigned char *d;
  24515. +
  24516. +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
  24517. + SQUASHFS_SWAP_START\
  24518. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
  24519. + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
  24520. + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
  24521. + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
  24522. + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
  24523. + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
  24524. + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
  24525. + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
  24526. + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
  24527. + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
  24528. + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
  24529. + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
  24530. + SQUASHFS_SWAP((s)->flags, d, 288, 8);\
  24531. + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
  24532. + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
  24533. + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
  24534. + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
  24535. + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
  24536. + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
  24537. + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
  24538. + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
  24539. + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
  24540. + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
  24541. + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
  24542. + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
  24543. + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
  24544. + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\
  24545. +}
  24546. +
  24547. +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
  24548. + SQUASHFS_MEMSET(s, d, n);\
  24549. + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
  24550. + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
  24551. + SQUASHFS_SWAP((s)->uid, d, 16, 8);\
  24552. + SQUASHFS_SWAP((s)->guid, d, 24, 8);\
  24553. + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
  24554. + SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
  24555. +
  24556. +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
  24557. + SQUASHFS_SWAP_START\
  24558. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
  24559. +}
  24560. +
  24561. +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
  24562. + SQUASHFS_SWAP_START\
  24563. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24564. + sizeof(struct squashfs_ipc_inode_header))\
  24565. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24566. +}
  24567. +
  24568. +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
  24569. + SQUASHFS_SWAP_START\
  24570. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24571. + sizeof(struct squashfs_dev_inode_header)); \
  24572. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24573. + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
  24574. +}
  24575. +
  24576. +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
  24577. + SQUASHFS_SWAP_START\
  24578. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24579. + sizeof(struct squashfs_symlink_inode_header));\
  24580. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24581. + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
  24582. +}
  24583. +
  24584. +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
  24585. + SQUASHFS_SWAP_START\
  24586. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24587. + sizeof(struct squashfs_reg_inode_header));\
  24588. + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
  24589. + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
  24590. + SQUASHFS_SWAP((s)->offset, d, 192, 32);\
  24591. + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
  24592. +}
  24593. +
  24594. +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
  24595. + SQUASHFS_SWAP_START\
  24596. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24597. + sizeof(struct squashfs_lreg_inode_header));\
  24598. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24599. + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
  24600. + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
  24601. + SQUASHFS_SWAP((s)->offset, d, 224, 32);\
  24602. + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
  24603. +}
  24604. +
  24605. +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
  24606. + SQUASHFS_SWAP_START\
  24607. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24608. + sizeof(struct squashfs_dir_inode_header));\
  24609. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24610. + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
  24611. + SQUASHFS_SWAP((s)->offset, d, 147, 13);\
  24612. + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
  24613. + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
  24614. +}
  24615. +
  24616. +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
  24617. + SQUASHFS_SWAP_START\
  24618. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24619. + sizeof(struct squashfs_ldir_inode_header));\
  24620. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24621. + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
  24622. + SQUASHFS_SWAP((s)->offset, d, 155, 13);\
  24623. + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
  24624. + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
  24625. + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
  24626. +}
  24627. +
  24628. +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
  24629. + SQUASHFS_SWAP_START\
  24630. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
  24631. + SQUASHFS_SWAP((s)->index, d, 0, 32);\
  24632. + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
  24633. + SQUASHFS_SWAP((s)->size, d, 64, 8);\
  24634. +}
  24635. +
  24636. +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
  24637. + SQUASHFS_SWAP_START\
  24638. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
  24639. + SQUASHFS_SWAP((s)->count, d, 0, 8);\
  24640. + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
  24641. + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
  24642. +}
  24643. +
  24644. +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
  24645. + SQUASHFS_SWAP_START\
  24646. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
  24647. + SQUASHFS_SWAP((s)->offset, d, 0, 13);\
  24648. + SQUASHFS_SWAP((s)->type, d, 13, 3);\
  24649. + SQUASHFS_SWAP((s)->size, d, 16, 8);\
  24650. + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
  24651. +}
  24652. +
  24653. +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
  24654. + SQUASHFS_SWAP_START\
  24655. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
  24656. + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
  24657. + SQUASHFS_SWAP((s)->size, d, 64, 32);\
  24658. +}
  24659. +
  24660. +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)
  24661. +
  24662. +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
  24663. + int entry;\
  24664. + int bit_position;\
  24665. + SQUASHFS_SWAP_START\
  24666. + SQUASHFS_MEMSET(s, d, n * 2);\
  24667. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24668. + 16)\
  24669. + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
  24670. +}
  24671. +
  24672. +#define SQUASHFS_SWAP_INTS(s, d, n) {\
  24673. + int entry;\
  24674. + int bit_position;\
  24675. + SQUASHFS_SWAP_START\
  24676. + SQUASHFS_MEMSET(s, d, n * 4);\
  24677. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24678. + 32)\
  24679. + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
  24680. +}
  24681. +
  24682. +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
  24683. + int entry;\
  24684. + int bit_position;\
  24685. + SQUASHFS_SWAP_START\
  24686. + SQUASHFS_MEMSET(s, d, n * 8);\
  24687. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24688. + 64)\
  24689. + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
  24690. +}
  24691. +
  24692. +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
  24693. + int entry;\
  24694. + int bit_position;\
  24695. + SQUASHFS_SWAP_START\
  24696. + SQUASHFS_MEMSET(s, d, n * bits / 8);\
  24697. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24698. + bits)\
  24699. + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
  24700. +}
  24701. +
  24702. +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
  24703. +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
  24704. +
  24705. +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  24706. +
  24707. +struct squashfs_base_inode_header_1 {
  24708. + unsigned int inode_type:4;
  24709. + unsigned int mode:12; /* protection */
  24710. + unsigned int uid:4; /* index into uid table */
  24711. + unsigned int guid:4; /* index into guid table */
  24712. +} __attribute__ ((packed));
  24713. +
  24714. +struct squashfs_ipc_inode_header_1 {
  24715. + unsigned int inode_type:4;
  24716. + unsigned int mode:12; /* protection */
  24717. + unsigned int uid:4; /* index into uid table */
  24718. + unsigned int guid:4; /* index into guid table */
  24719. + unsigned int type:4;
  24720. + unsigned int offset:4;
  24721. +} __attribute__ ((packed));
  24722. +
  24723. +struct squashfs_dev_inode_header_1 {
  24724. + unsigned int inode_type:4;
  24725. + unsigned int mode:12; /* protection */
  24726. + unsigned int uid:4; /* index into uid table */
  24727. + unsigned int guid:4; /* index into guid table */
  24728. + unsigned short rdev;
  24729. +} __attribute__ ((packed));
  24730. +
  24731. +struct squashfs_symlink_inode_header_1 {
  24732. + unsigned int inode_type:4;
  24733. + unsigned int mode:12; /* protection */
  24734. + unsigned int uid:4; /* index into uid table */
  24735. + unsigned int guid:4; /* index into guid table */
  24736. + unsigned short symlink_size;
  24737. + char symlink[0];
  24738. +} __attribute__ ((packed));
  24739. +
  24740. +struct squashfs_reg_inode_header_1 {
  24741. + unsigned int inode_type:4;
  24742. + unsigned int mode:12; /* protection */
  24743. + unsigned int uid:4; /* index into uid table */
  24744. + unsigned int guid:4; /* index into guid table */
  24745. + unsigned int mtime;
  24746. + unsigned int start_block;
  24747. + unsigned int file_size:32;
  24748. + unsigned short block_list[0];
  24749. +} __attribute__ ((packed));
  24750. +
  24751. +struct squashfs_dir_inode_header_1 {
  24752. + unsigned int inode_type:4;
  24753. + unsigned int mode:12; /* protection */
  24754. + unsigned int uid:4; /* index into uid table */
  24755. + unsigned int guid:4; /* index into guid table */
  24756. + unsigned int file_size:19;
  24757. + unsigned int offset:13;
  24758. + unsigned int mtime;
  24759. + unsigned int start_block:24;
  24760. +} __attribute__ ((packed));
  24761. +
  24762. +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
  24763. + SQUASHFS_MEMSET(s, d, n);\
  24764. + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
  24765. + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
  24766. + SQUASHFS_SWAP((s)->uid, d, 16, 4);\
  24767. + SQUASHFS_SWAP((s)->guid, d, 20, 4);
  24768. +
  24769. +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
  24770. + SQUASHFS_SWAP_START\
  24771. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
  24772. +}
  24773. +
  24774. +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
  24775. + SQUASHFS_SWAP_START\
  24776. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24777. + sizeof(struct squashfs_ipc_inode_header_1));\
  24778. + SQUASHFS_SWAP((s)->type, d, 24, 4);\
  24779. + SQUASHFS_SWAP((s)->offset, d, 28, 4);\
  24780. +}
  24781. +
  24782. +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
  24783. + SQUASHFS_SWAP_START\
  24784. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24785. + sizeof(struct squashfs_dev_inode_header_1));\
  24786. + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
  24787. +}
  24788. +
  24789. +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
  24790. + SQUASHFS_SWAP_START\
  24791. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24792. + sizeof(struct squashfs_symlink_inode_header_1));\
  24793. + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
  24794. +}
  24795. +
  24796. +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
  24797. + SQUASHFS_SWAP_START\
  24798. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24799. + sizeof(struct squashfs_reg_inode_header_1));\
  24800. + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
  24801. + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
  24802. + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
  24803. +}
  24804. +
  24805. +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
  24806. + SQUASHFS_SWAP_START\
  24807. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24808. + sizeof(struct squashfs_dir_inode_header_1));\
  24809. + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
  24810. + SQUASHFS_SWAP((s)->offset, d, 43, 13);\
  24811. + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
  24812. + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
  24813. +}
  24814. +
  24815. +#endif
  24816. +
  24817. +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
  24818. +
  24819. +struct squashfs_dir_index_2 {
  24820. + unsigned int index:27;
  24821. + unsigned int start_block:29;
  24822. + unsigned char size;
  24823. + unsigned char name[0];
  24824. +} __attribute__ ((packed));
  24825. +
  24826. +struct squashfs_base_inode_header_2 {
  24827. + unsigned int inode_type:4;
  24828. + unsigned int mode:12; /* protection */
  24829. + unsigned int uid:8; /* index into uid table */
  24830. + unsigned int guid:8; /* index into guid table */
  24831. +} __attribute__ ((packed));
  24832. +
  24833. +struct squashfs_ipc_inode_header_2 {
  24834. + unsigned int inode_type:4;
  24835. + unsigned int mode:12; /* protection */
  24836. + unsigned int uid:8; /* index into uid table */
  24837. + unsigned int guid:8; /* index into guid table */
  24838. +} __attribute__ ((packed));
  24839. +
  24840. +struct squashfs_dev_inode_header_2 {
  24841. + unsigned int inode_type:4;
  24842. + unsigned int mode:12; /* protection */
  24843. + unsigned int uid:8; /* index into uid table */
  24844. + unsigned int guid:8; /* index into guid table */
  24845. + unsigned short rdev;
  24846. +} __attribute__ ((packed));
  24847. +
  24848. +struct squashfs_symlink_inode_header_2 {
  24849. + unsigned int inode_type:4;
  24850. + unsigned int mode:12; /* protection */
  24851. + unsigned int uid:8; /* index into uid table */
  24852. + unsigned int guid:8; /* index into guid table */
  24853. + unsigned short symlink_size;
  24854. + char symlink[0];
  24855. +} __attribute__ ((packed));
  24856. +
  24857. +struct squashfs_reg_inode_header_2 {
  24858. + unsigned int inode_type:4;
  24859. + unsigned int mode:12; /* protection */
  24860. + unsigned int uid:8; /* index into uid table */
  24861. + unsigned int guid:8; /* index into guid table */
  24862. + unsigned int mtime;
  24863. + unsigned int start_block;
  24864. + unsigned int fragment;
  24865. + unsigned int offset;
  24866. + unsigned int file_size:32;
  24867. + unsigned short block_list[0];
  24868. +} __attribute__ ((packed));
  24869. +
  24870. +struct squashfs_dir_inode_header_2 {
  24871. + unsigned int inode_type:4;
  24872. + unsigned int mode:12; /* protection */
  24873. + unsigned int uid:8; /* index into uid table */
  24874. + unsigned int guid:8; /* index into guid table */
  24875. + unsigned int file_size:19;
  24876. + unsigned int offset:13;
  24877. + unsigned int mtime;
  24878. + unsigned int start_block:24;
  24879. +} __attribute__ ((packed));
  24880. +
  24881. +struct squashfs_ldir_inode_header_2 {
  24882. + unsigned int inode_type:4;
  24883. + unsigned int mode:12; /* protection */
  24884. + unsigned int uid:8; /* index into uid table */
  24885. + unsigned int guid:8; /* index into guid table */
  24886. + unsigned int file_size:27;
  24887. + unsigned int offset:13;
  24888. + unsigned int mtime;
  24889. + unsigned int start_block:24;
  24890. + unsigned int i_count:16;
  24891. + struct squashfs_dir_index_2 index[0];
  24892. +} __attribute__ ((packed));
  24893. +
  24894. +union squashfs_inode_header_2 {
  24895. + struct squashfs_base_inode_header_2 base;
  24896. + struct squashfs_dev_inode_header_2 dev;
  24897. + struct squashfs_symlink_inode_header_2 symlink;
  24898. + struct squashfs_reg_inode_header_2 reg;
  24899. + struct squashfs_dir_inode_header_2 dir;
  24900. + struct squashfs_ldir_inode_header_2 ldir;
  24901. + struct squashfs_ipc_inode_header_2 ipc;
  24902. +};
  24903. +
  24904. +struct squashfs_dir_header_2 {
  24905. + unsigned int count:8;
  24906. + unsigned int start_block:24;
  24907. +} __attribute__ ((packed));
  24908. +
  24909. +struct squashfs_dir_entry_2 {
  24910. + unsigned int offset:13;
  24911. + unsigned int type:3;
  24912. + unsigned int size:8;
  24913. + char name[0];
  24914. +} __attribute__ ((packed));
  24915. +
  24916. +struct squashfs_fragment_entry_2 {
  24917. + unsigned int start_block;
  24918. + unsigned int size;
  24919. +} __attribute__ ((packed));
  24920. +
  24921. +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
  24922. + SQUASHFS_MEMSET(s, d, n);\
  24923. + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
  24924. + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
  24925. + SQUASHFS_SWAP((s)->uid, d, 16, 8);\
  24926. + SQUASHFS_SWAP((s)->guid, d, 24, 8);\
  24927. +
  24928. +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
  24929. + SQUASHFS_SWAP_START\
  24930. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
  24931. +}
  24932. +
  24933. +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
  24934. + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
  24935. +
  24936. +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
  24937. + SQUASHFS_SWAP_START\
  24938. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  24939. + sizeof(struct squashfs_dev_inode_header_2)); \
  24940. + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
  24941. +}
  24942. +
  24943. +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
  24944. + SQUASHFS_SWAP_START\
  24945. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  24946. + sizeof(struct squashfs_symlink_inode_header_2));\
  24947. + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
  24948. +}
  24949. +
  24950. +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
  24951. + SQUASHFS_SWAP_START\
  24952. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  24953. + sizeof(struct squashfs_reg_inode_header_2));\
  24954. + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
  24955. + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
  24956. + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
  24957. + SQUASHFS_SWAP((s)->offset, d, 128, 32);\
  24958. + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
  24959. +}
  24960. +
  24961. +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
  24962. + SQUASHFS_SWAP_START\
  24963. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  24964. + sizeof(struct squashfs_dir_inode_header_2));\
  24965. + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
  24966. + SQUASHFS_SWAP((s)->offset, d, 51, 13);\
  24967. + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
  24968. + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
  24969. +}
  24970. +
  24971. +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
  24972. + SQUASHFS_SWAP_START\
  24973. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  24974. + sizeof(struct squashfs_ldir_inode_header_2));\
  24975. + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
  24976. + SQUASHFS_SWAP((s)->offset, d, 59, 13);\
  24977. + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
  24978. + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
  24979. + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
  24980. +}
  24981. +
  24982. +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
  24983. + SQUASHFS_SWAP_START\
  24984. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
  24985. + SQUASHFS_SWAP((s)->index, d, 0, 27);\
  24986. + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
  24987. + SQUASHFS_SWAP((s)->size, d, 56, 8);\
  24988. +}
  24989. +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
  24990. + SQUASHFS_SWAP_START\
  24991. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
  24992. + SQUASHFS_SWAP((s)->count, d, 0, 8);\
  24993. + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
  24994. +}
  24995. +
  24996. +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
  24997. + SQUASHFS_SWAP_START\
  24998. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
  24999. + SQUASHFS_SWAP((s)->offset, d, 0, 13);\
  25000. + SQUASHFS_SWAP((s)->type, d, 13, 3);\
  25001. + SQUASHFS_SWAP((s)->size, d, 16, 8);\
  25002. +}
  25003. +
  25004. +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
  25005. + SQUASHFS_SWAP_START\
  25006. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
  25007. + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
  25008. + SQUASHFS_SWAP((s)->size, d, 32, 32);\
  25009. +}
  25010. +
  25011. +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
  25012. +
  25013. +/* fragment and fragment table defines */
  25014. +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
  25015. +
  25016. +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
  25017. + SQUASHFS_METADATA_SIZE)
  25018. +
  25019. +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
  25020. + SQUASHFS_METADATA_SIZE)
  25021. +
  25022. +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
  25023. + SQUASHFS_METADATA_SIZE - 1) / \
  25024. + SQUASHFS_METADATA_SIZE)
  25025. +
  25026. +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
  25027. + sizeof(int))
  25028. +
  25029. +#endif
  25030. +
  25031. +#ifdef __KERNEL__
  25032. +
  25033. +/*
  25034. + * macros used to swap each structure entry, taking into account
  25035. + * bitfields and different bitfield placing conventions on differing
  25036. + * architectures
  25037. + */
  25038. +
  25039. +#include <asm/byteorder.h>
  25040. +
  25041. +#ifdef __BIG_ENDIAN
  25042. + /* convert from little endian to big endian */
  25043. +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
  25044. + tbits, b_pos)
  25045. +#else
  25046. + /* convert from big endian to little endian */
  25047. +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
  25048. + tbits, 64 - tbits - b_pos)
  25049. +#endif
  25050. +
  25051. +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
  25052. + b_pos = pos % 8;\
  25053. + val = 0;\
  25054. + s = (unsigned char *)p + (pos / 8);\
  25055. + d = ((unsigned char *) &val) + 7;\
  25056. + for(bits = 0; bits < (tbits + b_pos); bits += 8) \
  25057. + *d-- = *s++;\
  25058. + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
  25059. +}
  25060. +
  25061. +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
  25062. +
  25063. +#endif
  25064. +#endif
  25065. diff -rduNp linux-2.6.22.1.oorig/include/linux/squashfs_fs_i.h linux-2.6.22.1/include/linux/squashfs_fs_i.h
  25066. --- linux-2.6.22.1.oorig/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100
  25067. +++ linux-2.6.22.1/include/linux/squashfs_fs_i.h 2007-07-24 14:17:46.000000000 +0200
  25068. @@ -0,0 +1,45 @@
  25069. +#ifndef SQUASHFS_FS_I
  25070. +#define SQUASHFS_FS_I
  25071. +/*
  25072. + * Squashfs
  25073. + *
  25074. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  25075. + * Phillip Lougher <phillip@lougher.org.uk>
  25076. + *
  25077. + * This program is free software; you can redistribute it and/or
  25078. + * modify it under the terms of the GNU General Public License
  25079. + * as published by the Free Software Foundation; either version 2,
  25080. + * or (at your option) any later version.
  25081. + *
  25082. + * This program is distributed in the hope that it will be useful,
  25083. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25084. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25085. + * GNU General Public License for more details.
  25086. + *
  25087. + * You should have received a copy of the GNU General Public License
  25088. + * along with this program; if not, write to the Free Software
  25089. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25090. + *
  25091. + * squashfs_fs_i.h
  25092. + */
  25093. +
  25094. +struct squashfs_inode_info {
  25095. + long long start_block;
  25096. + unsigned int offset;
  25097. + union {
  25098. + struct {
  25099. + long long fragment_start_block;
  25100. + unsigned int fragment_size;
  25101. + unsigned int fragment_offset;
  25102. + long long block_list_start;
  25103. + } s1;
  25104. + struct {
  25105. + long long directory_index_start;
  25106. + unsigned int directory_index_offset;
  25107. + unsigned int directory_index_count;
  25108. + unsigned int parent_inode;
  25109. + } s2;
  25110. + } u;
  25111. + struct inode vfs_inode;
  25112. +};
  25113. +#endif
  25114. diff -rduNp linux-2.6.22.1.oorig/include/linux/squashfs_fs_sb.h linux-2.6.22.1/include/linux/squashfs_fs_sb.h
  25115. --- linux-2.6.22.1.oorig/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
  25116. +++ linux-2.6.22.1/include/linux/squashfs_fs_sb.h 2007-07-24 14:17:46.000000000 +0200
  25117. @@ -0,0 +1,74 @@
  25118. +#ifndef SQUASHFS_FS_SB
  25119. +#define SQUASHFS_FS_SB
  25120. +/*
  25121. + * Squashfs
  25122. + *
  25123. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  25124. + * Phillip Lougher <phillip@lougher.org.uk>
  25125. + *
  25126. + * This program is free software; you can redistribute it and/or
  25127. + * modify it under the terms of the GNU General Public License
  25128. + * as published by the Free Software Foundation; either version 2,
  25129. + * or (at your option) any later version.
  25130. + *
  25131. + * This program is distributed in the hope that it will be useful,
  25132. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25133. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25134. + * GNU General Public License for more details.
  25135. + *
  25136. + * You should have received a copy of the GNU General Public License
  25137. + * along with this program; if not, write to the Free Software
  25138. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25139. + *
  25140. + * squashfs_fs_sb.h
  25141. + */
  25142. +
  25143. +#include <linux/squashfs_fs.h>
  25144. +
  25145. +struct squashfs_cache {
  25146. + long long block;
  25147. + int length;
  25148. + long long next_index;
  25149. + char *data;
  25150. +};
  25151. +
  25152. +struct squashfs_fragment_cache {
  25153. + long long block;
  25154. + int length;
  25155. + unsigned int locked;
  25156. + char *data;
  25157. +};
  25158. +
  25159. +struct squashfs_sb_info {
  25160. + struct squashfs_super_block sblk;
  25161. + int devblksize;
  25162. + int devblksize_log2;
  25163. + int swap;
  25164. + struct squashfs_cache *block_cache;
  25165. + struct squashfs_fragment_cache *fragment;
  25166. + int next_cache;
  25167. + int next_fragment;
  25168. + int next_meta_index;
  25169. + unsigned int *uid;
  25170. + unsigned int *guid;
  25171. + long long *fragment_index;
  25172. + unsigned int *fragment_index_2;
  25173. + char *read_page;
  25174. + struct mutex read_data_mutex;
  25175. + struct mutex read_page_mutex;
  25176. + struct mutex block_cache_mutex;
  25177. + struct mutex fragment_mutex;
  25178. + struct mutex meta_index_mutex;
  25179. + wait_queue_head_t waitq;
  25180. + wait_queue_head_t fragment_wait_queue;
  25181. + struct meta_index *meta_index;
  25182. + z_stream stream;
  25183. + long long *inode_lookup_table;
  25184. + int (*read_inode)(struct inode *i, squashfs_inode_t \
  25185. + inode);
  25186. + long long (*read_blocklist)(struct inode *inode, int \
  25187. + index, int readahead_blks, char *block_list, \
  25188. + unsigned short **block_p, unsigned int *bsize);
  25189. + int (*read_fragment_index_table)(struct super_block *s);
  25190. +};
  25191. +#endif
  25192. diff -rduNp linux-2.6.22.1.oorig/init/Kconfig linux-2.6.22.1/init/Kconfig
  25193. --- linux-2.6.22.1.oorig/init/Kconfig 2007-07-10 20:56:30.000000000 +0200
  25194. +++ linux-2.6.22.1/init/Kconfig 2007-07-24 14:17:46.000000000 +0200
  25195. @@ -246,23 +246,21 @@ config AUDITSYSCALL
  25196. ensure that INOTIFY is configured.
  25197. config IKCONFIG
  25198. - tristate "Kernel .config support"
  25199. + tristate "Kernel .miniconfig support"
  25200. ---help---
  25201. - This option enables the complete Linux kernel ".config" file
  25202. + This option enables the mini Linux kernel ".miniconfig" file
  25203. contents to be saved in the kernel. It provides documentation
  25204. of which kernel options are used in a running kernel or in an
  25205. - on-disk kernel. This information can be extracted from the kernel
  25206. - image file with the script scripts/extract-ikconfig and used as
  25207. - input to rebuild the current kernel or to build another kernel.
  25208. - It can also be extracted from a running kernel by reading
  25209. - /proc/config.gz if enabled (below).
  25210. + on-disk kernel.
  25211. + It can be extracted from a running kernel by reading
  25212. + /proc/miniconfig.gz if enabled (below).
  25213. config IKCONFIG_PROC
  25214. - bool "Enable access to .config through /proc/config.gz"
  25215. + bool "Enable access to .miniconfig through /proc/miniconfig.gz"
  25216. depends on IKCONFIG && PROC_FS
  25217. ---help---
  25218. This option enables access to the kernel configuration file
  25219. - through /proc/config.gz.
  25220. + through /proc/miniconfig.gz.
  25221. config LOG_BUF_SHIFT
  25222. int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
  25223. diff -rduNp linux-2.6.22.1.oorig/init/LzmaDecode.c linux-2.6.22.1/init/LzmaDecode.c
  25224. --- linux-2.6.22.1.oorig/init/LzmaDecode.c 1970-01-01 01:00:00.000000000 +0100
  25225. +++ linux-2.6.22.1/init/LzmaDecode.c 2007-07-24 14:17:46.000000000 +0200
  25226. @@ -0,0 +1,588 @@
  25227. +/*
  25228. + LzmaDecode.c
  25229. + LZMA Decoder (optimized for Speed version)
  25230. +
  25231. + LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
  25232. + http://www.7-zip.org/
  25233. +
  25234. + LZMA SDK is licensed under two licenses:
  25235. + 1) GNU Lesser General Public License (GNU LGPL)
  25236. + 2) Common Public License (CPL)
  25237. + It means that you can select one of these two licenses and
  25238. + follow rules of that license.
  25239. +
  25240. + SPECIAL EXCEPTION:
  25241. + Igor Pavlov, as the author of this Code, expressly permits you to
  25242. + statically or dynamically link your Code (or bind by name) to the
  25243. + interfaces of this file without subjecting your linked Code to the
  25244. + terms of the CPL or GNU LGPL. Any modifications or additions
  25245. + to this file, however, are subject to the LGPL or CPL terms.
  25246. +*/
  25247. +
  25248. +#include "LzmaDecode.h"
  25249. +
  25250. +#ifndef Byte
  25251. +#define Byte unsigned char
  25252. +#endif
  25253. +
  25254. +#define kNumTopBits 24
  25255. +#define kTopValue ((UInt32)1 << kNumTopBits)
  25256. +
  25257. +#define kNumBitModelTotalBits 11
  25258. +#define kBitModelTotal (1 << kNumBitModelTotalBits)
  25259. +#define kNumMoveBits 5
  25260. +
  25261. +#define RC_READ_BYTE (*Buffer++)
  25262. +
  25263. +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
  25264. + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
  25265. +
  25266. +#ifdef _LZMA_IN_CB
  25267. +
  25268. +#define RC_TEST { if (Buffer == BufferLim) \
  25269. + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
  25270. + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
  25271. +
  25272. +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
  25273. +
  25274. +#else
  25275. +
  25276. +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
  25277. +
  25278. +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
  25279. +
  25280. +#endif
  25281. +
  25282. +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
  25283. +
  25284. +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
  25285. +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
  25286. +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
  25287. +
  25288. +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
  25289. + { UpdateBit0(p); mi <<= 1; A0; } else \
  25290. + { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
  25291. +
  25292. +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
  25293. +
  25294. +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
  25295. + { int i = numLevels; res = 1; \
  25296. + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
  25297. + res -= (1 << numLevels); }
  25298. +
  25299. +
  25300. +#define kNumPosBitsMax 4
  25301. +#define kNumPosStatesMax (1 << kNumPosBitsMax)
  25302. +
  25303. +#define kLenNumLowBits 3
  25304. +#define kLenNumLowSymbols (1 << kLenNumLowBits)
  25305. +#define kLenNumMidBits 3
  25306. +#define kLenNumMidSymbols (1 << kLenNumMidBits)
  25307. +#define kLenNumHighBits 8
  25308. +#define kLenNumHighSymbols (1 << kLenNumHighBits)
  25309. +
  25310. +#define LenChoice 0
  25311. +#define LenChoice2 (LenChoice + 1)
  25312. +#define LenLow (LenChoice2 + 1)
  25313. +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
  25314. +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
  25315. +#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
  25316. +
  25317. +
  25318. +#define kNumStates 12
  25319. +#define kNumLitStates 7
  25320. +
  25321. +#define kStartPosModelIndex 4
  25322. +#define kEndPosModelIndex 14
  25323. +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
  25324. +
  25325. +#define kNumPosSlotBits 6
  25326. +#define kNumLenToPosStates 4
  25327. +
  25328. +#define kNumAlignBits 4
  25329. +#define kAlignTableSize (1 << kNumAlignBits)
  25330. +
  25331. +#define kMatchMinLen 2
  25332. +
  25333. +#define IsMatch 0
  25334. +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
  25335. +#define IsRepG0 (IsRep + kNumStates)
  25336. +#define IsRepG1 (IsRepG0 + kNumStates)
  25337. +#define IsRepG2 (IsRepG1 + kNumStates)
  25338. +#define IsRep0Long (IsRepG2 + kNumStates)
  25339. +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
  25340. +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
  25341. +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
  25342. +#define LenCoder (Align + kAlignTableSize)
  25343. +#define RepLenCoder (LenCoder + kNumLenProbs)
  25344. +#define Literal (RepLenCoder + kNumLenProbs)
  25345. +
  25346. +#if Literal != LZMA_BASE_SIZE
  25347. +StopCompilingDueBUG
  25348. +#endif
  25349. +
  25350. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
  25351. +{
  25352. + unsigned char prop0;
  25353. + if (size < LZMA_PROPERTIES_SIZE)
  25354. + return LZMA_RESULT_DATA_ERROR;
  25355. + prop0 = propsData[0];
  25356. + if (prop0 >= (9 * 5 * 5))
  25357. + return LZMA_RESULT_DATA_ERROR;
  25358. + {
  25359. + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
  25360. + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
  25361. + propsRes->lc = prop0;
  25362. + /*
  25363. + unsigned char remainder = (unsigned char)(prop0 / 9);
  25364. + propsRes->lc = prop0 % 9;
  25365. + propsRes->pb = remainder / 5;
  25366. + propsRes->lp = remainder % 5;
  25367. + */
  25368. + }
  25369. +
  25370. + #ifdef _LZMA_OUT_READ
  25371. + {
  25372. + int i;
  25373. + propsRes->DictionarySize = 0;
  25374. + for (i = 0; i < 4; i++)
  25375. + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
  25376. + if (propsRes->DictionarySize == 0)
  25377. + propsRes->DictionarySize = 1;
  25378. + }
  25379. + #endif
  25380. + return LZMA_RESULT_OK;
  25381. +}
  25382. +
  25383. +#define kLzmaStreamWasFinishedId (-1)
  25384. +
  25385. +int LzmaDecode(CLzmaDecoderState *vs,
  25386. + #ifdef _LZMA_IN_CB
  25387. + ILzmaInCallback *InCallback,
  25388. + #else
  25389. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  25390. + #endif
  25391. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
  25392. +{
  25393. + CProb *p = vs->Probs;
  25394. + SizeT nowPos = 0;
  25395. + Byte previousByte = 0;
  25396. + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
  25397. + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
  25398. + int lc = vs->Properties.lc;
  25399. +
  25400. + #ifdef _LZMA_OUT_READ
  25401. +
  25402. + UInt32 Range = vs->Range;
  25403. + UInt32 Code = vs->Code;
  25404. + #ifdef _LZMA_IN_CB
  25405. + const Byte *Buffer = vs->Buffer;
  25406. + const Byte *BufferLim = vs->BufferLim;
  25407. + #else
  25408. + const Byte *Buffer = inStream;
  25409. + const Byte *BufferLim = inStream + inSize;
  25410. + #endif
  25411. + int state = vs->State;
  25412. + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
  25413. + int len = vs->RemainLen;
  25414. + UInt32 globalPos = vs->GlobalPos;
  25415. + UInt32 distanceLimit = vs->DistanceLimit;
  25416. +
  25417. + Byte *dictionary = vs->Dictionary;
  25418. + UInt32 dictionarySize = vs->Properties.DictionarySize;
  25419. + UInt32 dictionaryPos = vs->DictionaryPos;
  25420. +
  25421. + Byte tempDictionary[4];
  25422. +
  25423. + #ifndef _LZMA_IN_CB
  25424. + *inSizeProcessed = 0;
  25425. + #endif
  25426. + *outSizeProcessed = 0;
  25427. + if (len == kLzmaStreamWasFinishedId)
  25428. + return LZMA_RESULT_OK;
  25429. +
  25430. + if (dictionarySize == 0)
  25431. + {
  25432. + dictionary = tempDictionary;
  25433. + dictionarySize = 1;
  25434. + tempDictionary[0] = vs->TempDictionary[0];
  25435. + }
  25436. +
  25437. + if (len == kLzmaNeedInitId)
  25438. + {
  25439. + {
  25440. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  25441. + UInt32 i;
  25442. + for (i = 0; i < numProbs; i++)
  25443. + p[i] = kBitModelTotal >> 1;
  25444. + rep0 = rep1 = rep2 = rep3 = 1;
  25445. + state = 0;
  25446. + globalPos = 0;
  25447. + distanceLimit = 0;
  25448. + dictionaryPos = 0;
  25449. + dictionary[dictionarySize - 1] = 0;
  25450. + #ifdef _LZMA_IN_CB
  25451. + RC_INIT;
  25452. + #else
  25453. + RC_INIT(inStream, inSize);
  25454. + #endif
  25455. + }
  25456. + len = 0;
  25457. + }
  25458. + while(len != 0 && nowPos < outSize)
  25459. + {
  25460. + UInt32 pos = dictionaryPos - rep0;
  25461. + if (pos >= dictionarySize)
  25462. + pos += dictionarySize;
  25463. + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
  25464. + if (++dictionaryPos == dictionarySize)
  25465. + dictionaryPos = 0;
  25466. + len--;
  25467. + }
  25468. + if (dictionaryPos == 0)
  25469. + previousByte = dictionary[dictionarySize - 1];
  25470. + else
  25471. + previousByte = dictionary[dictionaryPos - 1];
  25472. +
  25473. + #else /* if !_LZMA_OUT_READ */
  25474. +
  25475. + int state = 0;
  25476. + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
  25477. + int len = 0;
  25478. + const Byte *Buffer;
  25479. + const Byte *BufferLim;
  25480. + UInt32 Range;
  25481. + UInt32 Code;
  25482. +
  25483. + #ifndef _LZMA_IN_CB
  25484. + *inSizeProcessed = 0;
  25485. + #endif
  25486. + *outSizeProcessed = 0;
  25487. +
  25488. + {
  25489. + UInt32 i;
  25490. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  25491. + for (i = 0; i < numProbs; i++)
  25492. + p[i] = kBitModelTotal >> 1;
  25493. + }
  25494. +
  25495. + #ifdef _LZMA_IN_CB
  25496. + RC_INIT;
  25497. + #else
  25498. + RC_INIT(inStream, inSize);
  25499. + #endif
  25500. +
  25501. + #endif /* _LZMA_OUT_READ */
  25502. +
  25503. + while(nowPos < outSize)
  25504. + {
  25505. + CProb *prob;
  25506. + UInt32 bound;
  25507. + int posState = (int)(
  25508. + (nowPos
  25509. + #ifdef _LZMA_OUT_READ
  25510. + + globalPos
  25511. + #endif
  25512. + )
  25513. + & posStateMask);
  25514. +
  25515. + prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
  25516. + IfBit0(prob)
  25517. + {
  25518. + int symbol = 1;
  25519. + UpdateBit0(prob)
  25520. + prob = p + Literal + (LZMA_LIT_SIZE *
  25521. + (((
  25522. + (nowPos
  25523. + #ifdef _LZMA_OUT_READ
  25524. + + globalPos
  25525. + #endif
  25526. + )
  25527. + & literalPosMask) << lc) + (previousByte >> (8 - lc))));
  25528. +
  25529. + if (state >= kNumLitStates)
  25530. + {
  25531. + int matchByte;
  25532. + #ifdef _LZMA_OUT_READ
  25533. + UInt32 pos = dictionaryPos - rep0;
  25534. + if (pos >= dictionarySize)
  25535. + pos += dictionarySize;
  25536. + matchByte = dictionary[pos];
  25537. + #else
  25538. + matchByte = outStream[nowPos - rep0];
  25539. + #endif
  25540. + do
  25541. + {
  25542. + int bit;
  25543. + CProb *probLit;
  25544. + matchByte <<= 1;
  25545. + bit = (matchByte & 0x100);
  25546. + probLit = prob + 0x100 + bit + symbol;
  25547. + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
  25548. + }
  25549. + while (symbol < 0x100);
  25550. + }
  25551. + while (symbol < 0x100)
  25552. + {
  25553. + CProb *probLit = prob + symbol;
  25554. + RC_GET_BIT(probLit, symbol)
  25555. + }
  25556. + previousByte = (Byte)symbol;
  25557. +
  25558. + outStream[nowPos++] = previousByte;
  25559. + #ifdef _LZMA_OUT_READ
  25560. + if (distanceLimit < dictionarySize)
  25561. + distanceLimit++;
  25562. +
  25563. + dictionary[dictionaryPos] = previousByte;
  25564. + if (++dictionaryPos == dictionarySize)
  25565. + dictionaryPos = 0;
  25566. + #endif
  25567. + if (state < 4) state = 0;
  25568. + else if (state < 10) state -= 3;
  25569. + else state -= 6;
  25570. + }
  25571. + else
  25572. + {
  25573. + UpdateBit1(prob);
  25574. + prob = p + IsRep + state;
  25575. + IfBit0(prob)
  25576. + {
  25577. + UpdateBit0(prob);
  25578. + rep3 = rep2;
  25579. + rep2 = rep1;
  25580. + rep1 = rep0;
  25581. + state = state < kNumLitStates ? 0 : 3;
  25582. + prob = p + LenCoder;
  25583. + }
  25584. + else
  25585. + {
  25586. + UpdateBit1(prob);
  25587. + prob = p + IsRepG0 + state;
  25588. + IfBit0(prob)
  25589. + {
  25590. + UpdateBit0(prob);
  25591. + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
  25592. + IfBit0(prob)
  25593. + {
  25594. + #ifdef _LZMA_OUT_READ
  25595. + UInt32 pos;
  25596. + #endif
  25597. + UpdateBit0(prob);
  25598. +
  25599. + #ifdef _LZMA_OUT_READ
  25600. + if (distanceLimit == 0)
  25601. + #else
  25602. + if (nowPos == 0)
  25603. + #endif
  25604. + return LZMA_RESULT_DATA_ERROR;
  25605. +
  25606. + state = state < kNumLitStates ? 9 : 11;
  25607. + #ifdef _LZMA_OUT_READ
  25608. + pos = dictionaryPos - rep0;
  25609. + if (pos >= dictionarySize)
  25610. + pos += dictionarySize;
  25611. + previousByte = dictionary[pos];
  25612. + dictionary[dictionaryPos] = previousByte;
  25613. + if (++dictionaryPos == dictionarySize)
  25614. + dictionaryPos = 0;
  25615. + #else
  25616. + previousByte = outStream[nowPos - rep0];
  25617. + #endif
  25618. + outStream[nowPos++] = previousByte;
  25619. + #ifdef _LZMA_OUT_READ
  25620. + if (distanceLimit < dictionarySize)
  25621. + distanceLimit++;
  25622. + #endif
  25623. +
  25624. + continue;
  25625. + }
  25626. + else
  25627. + {
  25628. + UpdateBit1(prob);
  25629. + }
  25630. + }
  25631. + else
  25632. + {
  25633. + UInt32 distance;
  25634. + UpdateBit1(prob);
  25635. + prob = p + IsRepG1 + state;
  25636. + IfBit0(prob)
  25637. + {
  25638. + UpdateBit0(prob);
  25639. + distance = rep1;
  25640. + }
  25641. + else
  25642. + {
  25643. + UpdateBit1(prob);
  25644. + prob = p + IsRepG2 + state;
  25645. + IfBit0(prob)
  25646. + {
  25647. + UpdateBit0(prob);
  25648. + distance = rep2;
  25649. + }
  25650. + else
  25651. + {
  25652. + UpdateBit1(prob);
  25653. + distance = rep3;
  25654. + rep3 = rep2;
  25655. + }
  25656. + rep2 = rep1;
  25657. + }
  25658. + rep1 = rep0;
  25659. + rep0 = distance;
  25660. + }
  25661. + state = state < kNumLitStates ? 8 : 11;
  25662. + prob = p + RepLenCoder;
  25663. + }
  25664. + {
  25665. + int numBits, offset;
  25666. + CProb *probLen = prob + LenChoice;
  25667. + IfBit0(probLen)
  25668. + {
  25669. + UpdateBit0(probLen);
  25670. + probLen = prob + LenLow + (posState << kLenNumLowBits);
  25671. + offset = 0;
  25672. + numBits = kLenNumLowBits;
  25673. + }
  25674. + else
  25675. + {
  25676. + UpdateBit1(probLen);
  25677. + probLen = prob + LenChoice2;
  25678. + IfBit0(probLen)
  25679. + {
  25680. + UpdateBit0(probLen);
  25681. + probLen = prob + LenMid + (posState << kLenNumMidBits);
  25682. + offset = kLenNumLowSymbols;
  25683. + numBits = kLenNumMidBits;
  25684. + }
  25685. + else
  25686. + {
  25687. + UpdateBit1(probLen);
  25688. + probLen = prob + LenHigh;
  25689. + offset = kLenNumLowSymbols + kLenNumMidSymbols;
  25690. + numBits = kLenNumHighBits;
  25691. + }
  25692. + }
  25693. + RangeDecoderBitTreeDecode(probLen, numBits, len);
  25694. + len += offset;
  25695. + }
  25696. +
  25697. + if (state < 4)
  25698. + {
  25699. + int posSlot;
  25700. + state += kNumLitStates;
  25701. + prob = p + PosSlot +
  25702. + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
  25703. + kNumPosSlotBits);
  25704. + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
  25705. + if (posSlot >= kStartPosModelIndex)
  25706. + {
  25707. + int numDirectBits = ((posSlot >> 1) - 1);
  25708. + rep0 = (2 | ((UInt32)posSlot & 1));
  25709. + if (posSlot < kEndPosModelIndex)
  25710. + {
  25711. + rep0 <<= numDirectBits;
  25712. + prob = p + SpecPos + rep0 - posSlot - 1;
  25713. + }
  25714. + else
  25715. + {
  25716. + numDirectBits -= kNumAlignBits;
  25717. + do
  25718. + {
  25719. + RC_NORMALIZE
  25720. + Range >>= 1;
  25721. + rep0 <<= 1;
  25722. + if (Code >= Range)
  25723. + {
  25724. + Code -= Range;
  25725. + rep0 |= 1;
  25726. + }
  25727. + }
  25728. + while (--numDirectBits != 0);
  25729. + prob = p + Align;
  25730. + rep0 <<= kNumAlignBits;
  25731. + numDirectBits = kNumAlignBits;
  25732. + }
  25733. + {
  25734. + int i = 1;
  25735. + int mi = 1;
  25736. + do
  25737. + {
  25738. + CProb *prob3 = prob + mi;
  25739. + RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
  25740. + i <<= 1;
  25741. + }
  25742. + while(--numDirectBits != 0);
  25743. + }
  25744. + }
  25745. + else
  25746. + rep0 = posSlot;
  25747. + if (++rep0 == (UInt32)(0))
  25748. + {
  25749. + /* it's for stream version */
  25750. + len = kLzmaStreamWasFinishedId;
  25751. + break;
  25752. + }
  25753. + }
  25754. +
  25755. + len += kMatchMinLen;
  25756. + #ifdef _LZMA_OUT_READ
  25757. + if (rep0 > distanceLimit)
  25758. + #else
  25759. + if (rep0 > nowPos)
  25760. + #endif
  25761. + return LZMA_RESULT_DATA_ERROR;
  25762. +
  25763. + #ifdef _LZMA_OUT_READ
  25764. + if (dictionarySize - distanceLimit > (UInt32)len)
  25765. + distanceLimit += len;
  25766. + else
  25767. + distanceLimit = dictionarySize;
  25768. + #endif
  25769. +
  25770. + do
  25771. + {
  25772. + #ifdef _LZMA_OUT_READ
  25773. + UInt32 pos = dictionaryPos - rep0;
  25774. + if (pos >= dictionarySize)
  25775. + pos += dictionarySize;
  25776. + previousByte = dictionary[pos];
  25777. + dictionary[dictionaryPos] = previousByte;
  25778. + if (++dictionaryPos == dictionarySize)
  25779. + dictionaryPos = 0;
  25780. + #else
  25781. + previousByte = outStream[nowPos - rep0];
  25782. + #endif
  25783. + len--;
  25784. + outStream[nowPos++] = previousByte;
  25785. + }
  25786. + while(len != 0 && nowPos < outSize);
  25787. + }
  25788. + }
  25789. + RC_NORMALIZE;
  25790. +
  25791. + #ifdef _LZMA_OUT_READ
  25792. + vs->Range = Range;
  25793. + vs->Code = Code;
  25794. + vs->DictionaryPos = dictionaryPos;
  25795. + vs->GlobalPos = globalPos + (UInt32)nowPos;
  25796. + vs->DistanceLimit = distanceLimit;
  25797. + vs->Reps[0] = rep0;
  25798. + vs->Reps[1] = rep1;
  25799. + vs->Reps[2] = rep2;
  25800. + vs->Reps[3] = rep3;
  25801. + vs->State = state;
  25802. + vs->RemainLen = len;
  25803. + vs->TempDictionary[0] = tempDictionary[0];
  25804. + #endif
  25805. +
  25806. + #ifdef _LZMA_IN_CB
  25807. + vs->Buffer = Buffer;
  25808. + vs->BufferLim = BufferLim;
  25809. + #else
  25810. + *inSizeProcessed = (SizeT)(Buffer - inStream);
  25811. + #endif
  25812. + *outSizeProcessed = nowPos;
  25813. + return LZMA_RESULT_OK;
  25814. +}
  25815. diff -rduNp linux-2.6.22.1.oorig/init/LzmaDecode.h linux-2.6.22.1/init/LzmaDecode.h
  25816. --- linux-2.6.22.1.oorig/init/LzmaDecode.h 1970-01-01 01:00:00.000000000 +0100
  25817. +++ linux-2.6.22.1/init/LzmaDecode.h 2007-07-24 14:17:46.000000000 +0200
  25818. @@ -0,0 +1,131 @@
  25819. +/*
  25820. + LzmaDecode.h
  25821. + LZMA Decoder interface
  25822. +
  25823. + LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
  25824. + http://www.7-zip.org/
  25825. +
  25826. + LZMA SDK is licensed under two licenses:
  25827. + 1) GNU Lesser General Public License (GNU LGPL)
  25828. + 2) Common Public License (CPL)
  25829. + It means that you can select one of these two licenses and
  25830. + follow rules of that license.
  25831. +
  25832. + SPECIAL EXCEPTION:
  25833. + Igor Pavlov, as the author of this code, expressly permits you to
  25834. + statically or dynamically link your code (or bind by name) to the
  25835. + interfaces of this file without subjecting your linked code to the
  25836. + terms of the CPL or GNU LGPL. Any modifications or additions
  25837. + to this file, however, are subject to the LGPL or CPL terms.
  25838. +*/
  25839. +
  25840. +#ifndef __LZMADECODE_H
  25841. +#define __LZMADECODE_H
  25842. +
  25843. +/* #define _LZMA_IN_CB */
  25844. +/* Use callback for input data */
  25845. +
  25846. +/* #define _LZMA_OUT_READ */
  25847. +/* Use read function for output data */
  25848. +
  25849. +/* #define _LZMA_PROB32 */
  25850. +/* It can increase speed on some 32-bit CPUs,
  25851. + but memory usage will be doubled in that case */
  25852. +
  25853. +/* #define _LZMA_LOC_OPT */
  25854. +/* Enable local speed optimizations inside code */
  25855. +
  25856. +/* #define _LZMA_SYSTEM_SIZE_T */
  25857. +/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
  25858. +
  25859. +#ifndef UInt32
  25860. +#ifdef _LZMA_UINT32_IS_ULONG
  25861. +#define UInt32 unsigned long
  25862. +#else
  25863. +#define UInt32 unsigned int
  25864. +#endif
  25865. +#endif
  25866. +
  25867. +#ifndef SizeT
  25868. +#ifdef _LZMA_SYSTEM_SIZE_T
  25869. +#include <stddef.h>
  25870. +#define SizeT size_t
  25871. +#else
  25872. +#define SizeT UInt32
  25873. +#endif
  25874. +#endif
  25875. +
  25876. +#ifdef _LZMA_PROB32
  25877. +#define CProb UInt32
  25878. +#else
  25879. +#define CProb unsigned short
  25880. +#endif
  25881. +
  25882. +#define LZMA_RESULT_OK 0
  25883. +#define LZMA_RESULT_DATA_ERROR 1
  25884. +
  25885. +#ifdef _LZMA_IN_CB
  25886. +typedef struct _ILzmaInCallback
  25887. +{
  25888. + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
  25889. +} ILzmaInCallback;
  25890. +#endif
  25891. +
  25892. +#define LZMA_BASE_SIZE 1846
  25893. +#define LZMA_LIT_SIZE 768
  25894. +
  25895. +#define LZMA_PROPERTIES_SIZE 5
  25896. +
  25897. +typedef struct _CLzmaProperties
  25898. +{
  25899. + int lc;
  25900. + int lp;
  25901. + int pb;
  25902. + #ifdef _LZMA_OUT_READ
  25903. + UInt32 DictionarySize;
  25904. + #endif
  25905. +}CLzmaProperties;
  25906. +
  25907. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
  25908. +
  25909. +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
  25910. +
  25911. +#define kLzmaNeedInitId (-2)
  25912. +
  25913. +typedef struct _CLzmaDecoderState
  25914. +{
  25915. + CLzmaProperties Properties;
  25916. + CProb *Probs;
  25917. +
  25918. + #ifdef _LZMA_IN_CB
  25919. + const unsigned char *Buffer;
  25920. + const unsigned char *BufferLim;
  25921. + #endif
  25922. +
  25923. + #ifdef _LZMA_OUT_READ
  25924. + unsigned char *Dictionary;
  25925. + UInt32 Range;
  25926. + UInt32 Code;
  25927. + UInt32 DictionaryPos;
  25928. + UInt32 GlobalPos;
  25929. + UInt32 DistanceLimit;
  25930. + UInt32 Reps[4];
  25931. + int State;
  25932. + int RemainLen;
  25933. + unsigned char TempDictionary[4];
  25934. + #endif
  25935. +} CLzmaDecoderState;
  25936. +
  25937. +#ifdef _LZMA_OUT_READ
  25938. +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
  25939. +#endif
  25940. +
  25941. +int LzmaDecode(CLzmaDecoderState *vs,
  25942. + #ifdef _LZMA_IN_CB
  25943. + ILzmaInCallback *inCallback,
  25944. + #else
  25945. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  25946. + #endif
  25947. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
  25948. +
  25949. +#endif
  25950. diff -rduNp linux-2.6.22.1.oorig/init/do_mounts_rd.c linux-2.6.22.1/init/do_mounts_rd.c
  25951. --- linux-2.6.22.1.oorig/init/do_mounts_rd.c 2007-07-10 20:56:30.000000000 +0200
  25952. +++ linux-2.6.22.1/init/do_mounts_rd.c 2007-07-24 14:17:46.000000000 +0200
  25953. @@ -5,7 +5,9 @@
  25954. #include <linux/ext2_fs.h>
  25955. #include <linux/romfs_fs.h>
  25956. #include <linux/cramfs_fs.h>
  25957. +#include <linux/squashfs_fs.h>
  25958. #include <linux/initrd.h>
  25959. +#include <linux/vmalloc.h>
  25960. #include <linux/string.h>
  25961. #include "do_mounts.h"
  25962. @@ -31,6 +33,9 @@ static int __init ramdisk_start_setup(ch
  25963. __setup("ramdisk_start=", ramdisk_start_setup);
  25964. static int __init crd_load(int in_fd, int out_fd);
  25965. +#ifdef CONFIG_LZMA_INITRD
  25966. +static int __init lzma_rd_load(int in_fd, int out_fd);
  25967. +#endif
  25968. /*
  25969. * This routine tries to find a RAM disk image to load, and returns the
  25970. @@ -39,6 +44,7 @@ static int __init crd_load(int in_fd, in
  25971. * numbers could not be found.
  25972. *
  25973. * We currently check for the following magic numbers:
  25974. + * squashfs
  25975. * minix
  25976. * ext2
  25977. * romfs
  25978. @@ -53,6 +59,7 @@ identify_ramdisk_image(int fd, int start
  25979. struct ext2_super_block *ext2sb;
  25980. struct romfs_super_block *romfsb;
  25981. struct cramfs_super *cramfsb;
  25982. + struct squashfs_super_block *squashfsb;
  25983. int nblocks = -1;
  25984. unsigned char *buf;
  25985. @@ -64,6 +71,7 @@ identify_ramdisk_image(int fd, int start
  25986. ext2sb = (struct ext2_super_block *) buf;
  25987. romfsb = (struct romfs_super_block *) buf;
  25988. cramfsb = (struct cramfs_super *) buf;
  25989. + squashfsb = (struct squashfs_super_block *) buf;
  25990. memset(buf, 0xe5, size);
  25991. /*
  25992. @@ -82,6 +90,17 @@ identify_ramdisk_image(int fd, int start
  25993. nblocks = 0;
  25994. goto done;
  25995. }
  25996. + /*
  25997. + * handle lzma compressed initrd, returns nblocks=1 as indication
  25998. + */
  25999. + if( buf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0 && buf[11] == 0
  26000. + && buf[12] == 0 )
  26001. + {
  26002. + printk( KERN_NOTICE "RAMDISK: LZMA image found at block %d\n",
  26003. + start_block);
  26004. + nblocks = 1; // just a convenient return flag
  26005. + goto done;
  26006. + }
  26007. /* romfs is at block zero too */
  26008. if (romfsb->word0 == ROMSB_WORD0 &&
  26009. @@ -101,6 +120,18 @@ identify_ramdisk_image(int fd, int start
  26010. goto done;
  26011. }
  26012. + /* squashfs is at block zero too */
  26013. + if (squashfsb->s_magic == SQUASHFS_MAGIC) {
  26014. + printk(KERN_NOTICE
  26015. + "RAMDISK: squashfs filesystem found at block %d\n",
  26016. + start_block);
  26017. + if (squashfsb->s_major < 3)
  26018. + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
  26019. + else
  26020. + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
  26021. + goto done;
  26022. + }
  26023. +
  26024. /*
  26025. * Read block 1 to test for minix and ext2 superblock
  26026. */
  26027. @@ -172,7 +203,22 @@ int __init rd_load_image(char *from)
  26028. #endif
  26029. goto done;
  26030. }
  26031. -
  26032. +#ifdef CONFIG_LZMA_INITRD
  26033. + /*
  26034. + * handle lzma compressed image
  26035. + */
  26036. + if ( nblocks == 1 )
  26037. + {
  26038. + nblocks = 0;
  26039. + if ( lzma_rd_load(in_fd, out_fd) == 0 )
  26040. + {
  26041. + printk("\nLZMA initrd loaded successfully\n");
  26042. + goto successful_load;
  26043. + }
  26044. + printk(KERN_NOTICE "LZMA initrd is not in the correct format\n");
  26045. + goto done;
  26046. + }
  26047. +#endif
  26048. /*
  26049. * NOTE NOTE: nblocks is not actually blocks but
  26050. * the number of kibibytes of data to load into a ramdisk.
  26051. @@ -393,6 +439,134 @@ static void __init error(char *x)
  26052. unzip_error = 1;
  26053. }
  26054. +#ifdef CONFIG_LZMA_INITRD
  26055. +#define _LZMA_IN_CB
  26056. +#define _LZMA_OUT_READ
  26057. +#include "LzmaDecode.h"
  26058. +#include "LzmaDecode.c"
  26059. +
  26060. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
  26061. +
  26062. +/*
  26063. + * Do the lzma decompression
  26064. + */
  26065. +static int __init lzma_rd_load(int in_fd, int out_fd)
  26066. +{
  26067. + unsigned int i;
  26068. + CLzmaDecoderState state;
  26069. + unsigned char* outputbuffer;
  26070. + unsigned int uncompressedSize = 0;
  26071. + unsigned char* p;
  26072. + unsigned int kBlockSize = 0x10000;
  26073. + unsigned int nowPos = 0;
  26074. + unsigned int outsizeProcessed = 0;
  26075. + int res;
  26076. + ILzmaInCallback callback;
  26077. +
  26078. + insize = 0; /* valid bytes in inbuf */
  26079. + inptr = 0; /* index of next byte to be processed in inbuf */
  26080. + exit_code = 0;
  26081. + crd_infd = in_fd;
  26082. + inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
  26083. + if (inbuf == 0)
  26084. + {
  26085. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma input buffer\n");
  26086. + return -1;
  26087. + }
  26088. +
  26089. + callback.Read = read_byte;
  26090. +
  26091. + /* lzma args */
  26092. + i = get_byte();
  26093. + state.Properties.lc = i % 9, i = i / 9;
  26094. + state.Properties.lp = i % 5, state.Properties.pb = i / 5;
  26095. +
  26096. + /* read dictionary size */
  26097. + p = (char*)&state.Properties.DictionarySize;
  26098. + for (i = 0; i < 4; i++)
  26099. + *p++ = get_byte();
  26100. +
  26101. + /* get uncompressedSize */
  26102. + p= (char*)&uncompressedSize;
  26103. + for (i = 0; i < 4; i++)
  26104. + *p++ = get_byte();
  26105. +
  26106. + /* skip big file */
  26107. + for (i = 0; i < 4; i++)
  26108. + get_byte();
  26109. +
  26110. + printk( KERN_NOTICE "RAMDISK: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
  26111. + state.Properties.lc, state.Properties.lp, state.Properties.pb, state.Properties.DictionarySize, uncompressedSize);
  26112. + outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
  26113. + if (outputbuffer == 0) {
  26114. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma output buffer\n");
  26115. + return -1;
  26116. + }
  26117. +
  26118. + state.Probs = (CProb*)kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
  26119. + if ( state.Probs == 0) {
  26120. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma workspace\n");
  26121. + return -1;
  26122. + }
  26123. +
  26124. +#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
  26125. + state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
  26126. +#else
  26127. + state.Dictionary = vmalloc( state.Properties.DictionarySize);
  26128. +#endif
  26129. + if ( state.Dictionary == 0) {
  26130. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma dictionary\n");
  26131. + return -1;
  26132. + }
  26133. +
  26134. + printk( KERN_NOTICE "LZMA initrd by Ming-Ching Tiew <mctiew@yahoo.com> " );
  26135. +
  26136. + LzmaDecoderInit( &state );
  26137. +
  26138. + for( nowPos =0; nowPos < uncompressedSize ; )
  26139. + {
  26140. + UInt32 blockSize = uncompressedSize - nowPos;
  26141. + if( blockSize > kBlockSize)
  26142. + blockSize = kBlockSize;
  26143. + res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
  26144. + if( res != 0 ) {
  26145. + printk( KERN_ERR "RAMDISK: Lzma decode failure\n");
  26146. + return -1;
  26147. + }
  26148. + if( outsizeProcessed == 0 )
  26149. + {
  26150. + uncompressedSize = nowPos;
  26151. + printk( KERN_NOTICE "RAMDISK nowPos=%d, uncompressedSize=%d\n",
  26152. + nowPos, uncompressedSize );
  26153. + break;
  26154. + }
  26155. + sys_write(out_fd, outputbuffer, outsizeProcessed );
  26156. + nowPos += outsizeProcessed;
  26157. + printk( ".");
  26158. + }
  26159. +
  26160. +#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
  26161. + kfree(state.Dictionary);
  26162. +#else
  26163. + vfree(state.Dictionary);
  26164. +#endif
  26165. + kfree(inbuf);
  26166. + kfree(outputbuffer);
  26167. + kfree(state.Probs);
  26168. + return 0;
  26169. +}
  26170. +
  26171. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
  26172. +{
  26173. + static unsigned char val;
  26174. + *bufferSize = 1;
  26175. + val = get_byte();
  26176. + *buffer = &val;
  26177. + return LZMA_RESULT_OK;
  26178. +}
  26179. +
  26180. +#endif /*CONFIG_LZMA_INITRD*/
  26181. +
  26182. static int __init crd_load(int in_fd, int out_fd)
  26183. {
  26184. int result;
  26185. diff -rduNp linux-2.6.22.1.oorig/init/initramfs.c linux-2.6.22.1/init/initramfs.c
  26186. --- linux-2.6.22.1.oorig/init/initramfs.c 2007-07-10 20:56:30.000000000 +0200
  26187. +++ linux-2.6.22.1/init/initramfs.c 2007-07-24 14:17:46.000000000 +0200
  26188. @@ -6,6 +6,7 @@
  26189. #include <linux/delay.h>
  26190. #include <linux/string.h>
  26191. #include <linux/syscalls.h>
  26192. +#include <linux/vmalloc.h>
  26193. static __initdata char *message;
  26194. static void __init error(char *x)
  26195. @@ -441,6 +442,118 @@ static void __init flush_window(void)
  26196. outcnt = 0;
  26197. }
  26198. +#ifdef CONFIG_LZMA_INITRAM_FS
  26199. +#define _LZMA_IN_CB
  26200. +#define _LZMA_OUT_READ
  26201. +#include "LzmaDecode.h"
  26202. +#ifndef CONFIG_LZMA_INITRD
  26203. + #include "LzmaDecode.c"
  26204. +#endif
  26205. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
  26206. +{
  26207. + static unsigned char val;
  26208. + *bufferSize = 1;
  26209. + val = get_byte();
  26210. + *buffer = &val;
  26211. + return LZMA_RESULT_OK;
  26212. +}
  26213. +
  26214. +static int __init lzma_unzip(void)
  26215. +{
  26216. + unsigned int i;
  26217. + CLzmaDecoderState state;
  26218. + unsigned char* outputbuffer;
  26219. + unsigned int uncompressedSize = 0;
  26220. + unsigned char* p;
  26221. + unsigned int kBlockSize = 0x10000;
  26222. + unsigned int nowPos = 0;
  26223. + unsigned int outsizeProcessed = 0;
  26224. + int res;
  26225. + ILzmaInCallback callback;
  26226. +
  26227. + callback.Read = read_byte;
  26228. +
  26229. + // lzma args
  26230. + i = get_byte();
  26231. + state.Properties.lc = i % 9, i = i / 9;
  26232. + state.Properties.lp = i % 5, state.Properties.pb = i / 5;
  26233. +
  26234. + // read dictionary size
  26235. + p = (char*)&state.Properties.DictionarySize;
  26236. + for (i = 0; i < 4; i++)
  26237. + *p++ = get_byte();
  26238. +
  26239. + // get uncompressedSize
  26240. + p= (char*)&uncompressedSize;
  26241. + for (i = 0; i < 4; i++)
  26242. + *p++ = get_byte();
  26243. +
  26244. + // skip big file
  26245. + for (i = 0; i < 4; i++)
  26246. + get_byte();
  26247. +
  26248. + printk( KERN_NOTICE "initramfs: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
  26249. + state.Properties.lc,state.Properties.lp,state.Properties.pb,state.Properties.DictionarySize, uncompressedSize);
  26250. + outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
  26251. + if (outputbuffer == 0) {
  26252. + printk(KERN_ERR "initramfs: Couldn't allocate lzma output buffer\n");
  26253. + return -1;
  26254. + }
  26255. +
  26256. + state.Probs = (CProb*) kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
  26257. + if ( state.Probs == 0) {
  26258. + printk(KERN_ERR "initramfs: Couldn't allocate lzma workspace\n");
  26259. + return -1;
  26260. + }
  26261. +
  26262. +#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
  26263. + state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
  26264. +#else
  26265. + state.Dictionary = vmalloc( state.Properties.DictionarySize);
  26266. +#endif
  26267. + if ( state.Dictionary == 0) {
  26268. + printk(KERN_ERR "initramfs: Couldn't allocate lzma dictionary\n");
  26269. + return -1;
  26270. + }
  26271. +
  26272. + printk( KERN_NOTICE "LZMA initramfs by Ming-Ching Tiew <mctiew@yahoo.com> " );
  26273. +
  26274. + LzmaDecoderInit( &state );
  26275. +
  26276. + for( nowPos =0; nowPos < uncompressedSize ; )
  26277. + {
  26278. + UInt32 blockSize = uncompressedSize - nowPos;
  26279. + if( blockSize > kBlockSize)
  26280. + blockSize = kBlockSize;
  26281. + res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
  26282. + if( res != 0 ) {
  26283. + panic( KERN_ERR "initramfs: Lzma decode failure\n");
  26284. + return -1;
  26285. + }
  26286. + if( outsizeProcessed == 0 )
  26287. + {
  26288. + uncompressedSize = nowPos;
  26289. + printk( KERN_NOTICE "initramfs: nowPos=%d, uncompressedSize=%d\n",
  26290. + nowPos, uncompressedSize );
  26291. + break;
  26292. + }
  26293. + flush_buffer(outputbuffer, outsizeProcessed);
  26294. + nowPos += outsizeProcessed;
  26295. + printk( ".");
  26296. + }
  26297. +
  26298. +#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
  26299. + kfree(state.Dictionary);
  26300. +#else
  26301. + vfree(state.Dictionary);
  26302. +#endif
  26303. + kfree(outputbuffer);
  26304. + kfree(state.Probs);
  26305. + return 0;
  26306. +}
  26307. +
  26308. +#endif /*CONFIG LZMA_INITRAM_FS*/
  26309. +
  26310. static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
  26311. {
  26312. int written;
  26313. @@ -475,12 +588,31 @@ static char * __init unpack_to_rootfs(ch
  26314. inptr = 0;
  26315. outcnt = 0; /* bytes in output buffer */
  26316. bytes_out = 0;
  26317. - crc = (ulg)0xffffffffL; /* shift register contents */
  26318. - makecrc();
  26319. - gunzip();
  26320. - if (state != Reset)
  26321. + if( inbuf[0] == 037 && ((inbuf[1] == 0213) || (inbuf[1] == 0236)))
  26322. + {
  26323. + printk( KERN_NOTICE "detected gzip initramfs\n");
  26324. + crc = (ulg)0xffffffffL; /* shift register contents */
  26325. + makecrc();
  26326. + gunzip();
  26327. + if (state != Reset)
  26328. error("junk in gzipped archive");
  26329. - this_header = saved_offset + inptr;
  26330. + }
  26331. +#ifdef CONFIG_LZMA_INITRAM_FS
  26332. + else if( inbuf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0
  26333. + && buf[11] == 0 && buf[12] == 0 )
  26334. + {
  26335. + printk( KERN_NOTICE "detected lzma initramfs\n");
  26336. + lzma_unzip();
  26337. + }
  26338. +#endif
  26339. + else
  26340. + {
  26341. + // skip forward ?
  26342. + crc = (ulg)0xffffffffL; /* shift register contents */
  26343. + makecrc();
  26344. + gunzip();
  26345. + }
  26346. + this_header = saved_offset + inptr;
  26347. buf += inptr;
  26348. len -= inptr;
  26349. }
  26350. diff -rduNp linux-2.6.22.1.oorig/kernel/Makefile linux-2.6.22.1/kernel/Makefile
  26351. --- linux-2.6.22.1.oorig/kernel/Makefile 2007-07-10 20:56:30.000000000 +0200
  26352. +++ linux-2.6.22.1/kernel/Makefile 2007-07-24 14:17:46.000000000 +0200
  26353. @@ -66,7 +66,7 @@ $(obj)/configs.o: $(obj)/config_data.h
  26354. # config_data.h contains the same information as ikconfig.h but gzipped.
  26355. # Info from config_data can be extracted from /proc/config*
  26356. targets += config_data.gz
  26357. -$(obj)/config_data.gz: .config FORCE
  26358. +$(obj)/config_data.gz: .miniconfig FORCE
  26359. $(call if_changed,gzip)
  26360. quiet_cmd_ikconfiggz = IKCFG $@
  26361. diff -rduNp linux-2.6.22.1.oorig/kernel/configs.c linux-2.6.22.1/kernel/configs.c
  26362. --- linux-2.6.22.1.oorig/kernel/configs.c 2007-07-10 20:56:30.000000000 +0200
  26363. +++ linux-2.6.22.1/kernel/configs.c 2007-07-24 14:17:46.000000000 +0200
  26364. @@ -79,7 +79,7 @@ static int __init ikconfig_init(void)
  26365. struct proc_dir_entry *entry;
  26366. /* create the current config file */
  26367. - entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
  26368. + entry = create_proc_entry("miniconfig.gz", S_IFREG | S_IRUGO,
  26369. &proc_root);
  26370. if (!entry)
  26371. return -ENOMEM;
  26372. @@ -95,7 +95,7 @@ static int __init ikconfig_init(void)
  26373. static void __exit ikconfig_cleanup(void)
  26374. {
  26375. - remove_proc_entry("config.gz", &proc_root);
  26376. + remove_proc_entry("miniconfig.gz", &proc_root);
  26377. }
  26378. module_init(ikconfig_init);
  26379. diff -rduNp linux-2.6.22.1.oorig/kernel/time/clocksource.c linux-2.6.22.1/kernel/time/clocksource.c
  26380. --- linux-2.6.22.1.oorig/kernel/time/clocksource.c 2007-07-10 20:56:30.000000000 +0200
  26381. +++ linux-2.6.22.1/kernel/time/clocksource.c 2007-07-24 14:17:46.000000000 +0200
  26382. @@ -87,8 +87,8 @@ static void clocksource_ratewd(struct cl
  26383. if (delta > -WATCHDOG_THRESHOLD && delta < WATCHDOG_THRESHOLD)
  26384. return;
  26385. - printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
  26386. - cs->name, delta);
  26387. +/* printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
  26388. + cs->name, delta); */
  26389. cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
  26390. clocksource_change_rating(cs, 0);
  26391. cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
  26392. diff -rduNp linux-2.6.22.1.oorig/miniconfig.sh linux-2.6.22.1/miniconfig.sh
  26393. --- linux-2.6.22.1.oorig/miniconfig.sh 1970-01-01 01:00:00.000000000 +0100
  26394. +++ linux-2.6.22.1/miniconfig.sh 2007-07-24 14:17:46.000000000 +0200
  26395. @@ -0,0 +1,2 @@
  26396. +#!/bin/sh -f
  26397. +make allnoconfig KCONFIG_ALLCONFIG=.miniconfig
  26398. diff -rduNp linux-2.6.22.1.oorig/scripts/Makefile.lib linux-2.6.22.1/scripts/Makefile.lib
  26399. --- linux-2.6.22.1.oorig/scripts/Makefile.lib 2007-07-10 20:56:30.000000000 +0200
  26400. +++ linux-2.6.22.1/scripts/Makefile.lib 2007-07-24 14:17:46.000000000 +0200
  26401. @@ -162,4 +162,9 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS)
  26402. quiet_cmd_gzip = GZIP $@
  26403. cmd_gzip = gzip -f -9 < $< > $@
  26404. +# LZMA
  26405. +#
  26406. +quiet_cmd_lzma = LZMA $@
  26407. +cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
  26408. +
  26409. diff -rduNp linux-2.6.22.1.oorig/scripts/gen_lzma_initramfs_list.sh linux-2.6.22.1/scripts/gen_lzma_initramfs_list.sh
  26410. --- linux-2.6.22.1.oorig/scripts/gen_lzma_initramfs_list.sh 1970-01-01 01:00:00.000000000 +0100
  26411. +++ linux-2.6.22.1/scripts/gen_lzma_initramfs_list.sh 2007-07-24 14:17:46.000000000 +0200
  26412. @@ -0,0 +1,292 @@
  26413. +#!/bin/bash
  26414. +# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
  26415. +# Copyright (c) 2006 Sam Ravnborg <sam@ravnborg.org>
  26416. +#
  26417. +# Released under the terms of the GNU GPL
  26418. +#
  26419. +# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
  26420. +# the cpio archive, and gzip to pack it.
  26421. +# The script may also be used to generate the inputfile used for gen_init_cpio
  26422. +# This script assumes that gen_init_cpio is located in usr/ directory
  26423. +
  26424. +# error out on errors
  26425. +set -e
  26426. +
  26427. +usage() {
  26428. +cat << EOF
  26429. +Usage:
  26430. +$0 [-o <file>] [-u <uid>] [-g <gid>] { -s | -d | <cpio_source>} ...
  26431. + -o <file> Create lzma initramfs file named <file> using
  26432. + gen_init_cpio and lzma
  26433. + -u <uid> User ID to map to user ID 0 (root).
  26434. + <uid> is only meaningful if <cpio_source>
  26435. + is a directory.
  26436. + -g <gid> Group ID to map to group ID 0 (root).
  26437. + <gid> is only meaningful if <cpio_source>
  26438. + is a directory.
  26439. + <cpio_source> File list or directory for cpio archive.
  26440. + If <cpio_source> is a .cpio file it will be used
  26441. + as direct input to initramfs.
  26442. + -s Create lzma file with small dictionary size
  26443. + -d Output the default cpio list.
  26444. +
  26445. +All options except -o and -l may be repeated and are interpreted
  26446. +sequentially and immediately. -u and -g states are preserved across
  26447. +<cpio_source> options so an explicit "-u 0 -g 0" is required
  26448. +to reset the root/group mapping.
  26449. +EOF
  26450. +}
  26451. +
  26452. +list_default_initramfs() {
  26453. + # echo usr/kinit/kinit
  26454. + :
  26455. +}
  26456. +
  26457. +default_initramfs() {
  26458. + cat <<-EOF >> ${output}
  26459. + # This is a very simple, default initramfs
  26460. +
  26461. + dir /dev 0755 0 0
  26462. + nod /dev/console 0600 0 0 c 5 1
  26463. + dir /root 0700 0 0
  26464. + # file /kinit usr/kinit/kinit 0755 0 0
  26465. + # slink /init kinit 0755 0 0
  26466. + EOF
  26467. +}
  26468. +
  26469. +filetype() {
  26470. + local argv1="$1"
  26471. +
  26472. + # symlink test must come before file test
  26473. + if [ -L "${argv1}" ]; then
  26474. + echo "slink"
  26475. + elif [ -f "${argv1}" ]; then
  26476. + echo "file"
  26477. + elif [ -d "${argv1}" ]; then
  26478. + echo "dir"
  26479. + elif [ -b "${argv1}" -o -c "${argv1}" ]; then
  26480. + echo "nod"
  26481. + elif [ -p "${argv1}" ]; then
  26482. + echo "pipe"
  26483. + elif [ -S "${argv1}" ]; then
  26484. + echo "sock"
  26485. + else
  26486. + echo "invalid"
  26487. + fi
  26488. + return 0
  26489. +}
  26490. +
  26491. +list_print_mtime() {
  26492. + :
  26493. +}
  26494. +
  26495. +print_mtime() {
  26496. + local my_mtime="0"
  26497. +
  26498. + if [ -e "$1" ]; then
  26499. + my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
  26500. + fi
  26501. +
  26502. + echo "# Last modified: ${my_mtime}" >> ${output}
  26503. + echo "" >> ${output}
  26504. +}
  26505. +
  26506. +list_parse() {
  26507. + echo "$1 \\"
  26508. +}
  26509. +
  26510. +# for each file print a line in following format
  26511. +# <filetype> <name> <path to file> <octal mode> <uid> <gid>
  26512. +# for links, devices etc the format differs. See gen_init_cpio for details
  26513. +parse() {
  26514. + local location="$1"
  26515. + local name="${location/${srcdir}//}"
  26516. + # change '//' into '/'
  26517. + name="${name//\/\///}"
  26518. + local mode="$2"
  26519. + local uid="$3"
  26520. + local gid="$4"
  26521. + local ftype=$(filetype "${location}")
  26522. + # remap uid/gid to 0 if necessary
  26523. + [ "$uid" -eq "$root_uid" ] && uid=0
  26524. + [ "$gid" -eq "$root_gid" ] && gid=0
  26525. + local str="${mode} ${uid} ${gid}"
  26526. +
  26527. + [ "${ftype}" == "invalid" ] && return 0
  26528. + [ "${location}" == "${srcdir}" ] && return 0
  26529. +
  26530. + case "${ftype}" in
  26531. + "file")
  26532. + str="${ftype} ${name} ${location} ${str}"
  26533. + ;;
  26534. + "nod")
  26535. + local dev_type=
  26536. + local maj=$(LC_ALL=C ls -l "${location}" | \
  26537. + gawk '{sub(/,/, "", $5); print $5}')
  26538. + local min=$(LC_ALL=C ls -l "${location}" | \
  26539. + gawk '{print $6}')
  26540. +
  26541. + if [ -b "${location}" ]; then
  26542. + dev_type="b"
  26543. + else
  26544. + dev_type="c"
  26545. + fi
  26546. + str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
  26547. + ;;
  26548. + "slink")
  26549. + local target=$(LC_ALL=C ls -l "${location}" | \
  26550. + gawk '{print $11}')
  26551. + str="${ftype} ${name} ${target} ${str}"
  26552. + ;;
  26553. + *)
  26554. + str="${ftype} ${name} ${str}"
  26555. + ;;
  26556. + esac
  26557. +
  26558. + echo "${str}" >> ${output}
  26559. +
  26560. + return 0
  26561. +}
  26562. +
  26563. +unknown_option() {
  26564. + printf "ERROR: unknown option \"$arg\"\n" >&2
  26565. + printf "If the filename validly begins with '-', " >&2
  26566. + printf "then it must be prefixed\n" >&2
  26567. + printf "by './' so that it won't be interpreted as an option." >&2
  26568. + printf "\n" >&2
  26569. + usage >&2
  26570. + exit 1
  26571. +}
  26572. +
  26573. +list_header() {
  26574. + :
  26575. +}
  26576. +
  26577. +header() {
  26578. + printf "\n#####################\n# $1\n" >> ${output}
  26579. +}
  26580. +
  26581. +# process one directory (incl sub-directories)
  26582. +dir_filelist() {
  26583. + ${dep_list}header "$1"
  26584. +
  26585. + srcdir=$(echo "$1" | sed -e 's://*:/:g')
  26586. + dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
  26587. +
  26588. + # If $dirlist is only one line, then the directory is empty
  26589. + if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
  26590. + ${dep_list}print_mtime "$1"
  26591. +
  26592. + echo "${dirlist}" | \
  26593. + while read x; do
  26594. + ${dep_list}parse ${x}
  26595. + done
  26596. + fi
  26597. +}
  26598. +
  26599. +# if only one file is specified and it is .cpio file then use it direct as fs
  26600. +# if a directory is specified then add all files in given direcotry to fs
  26601. +# if a regular file is specified assume it is in gen_initramfs format
  26602. +input_file() {
  26603. + source="$1"
  26604. + if [ -f "$1" ]; then
  26605. + ${dep_list}header "$1"
  26606. + is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
  26607. + if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
  26608. + cpio_file=$1
  26609. + [ ! -z ${dep_list} ] && echo "$1"
  26610. + return 0
  26611. + fi
  26612. + if [ -z ${dep_list} ]; then
  26613. + print_mtime "$1" >> ${output}
  26614. + cat "$1" >> ${output}
  26615. + else
  26616. + cat "$1" | while read type dir file perm ; do
  26617. + if [ "$type" == "file" ]; then
  26618. + echo "$file \\";
  26619. + fi
  26620. + done
  26621. + fi
  26622. + elif [ -d "$1" ]; then
  26623. + dir_filelist "$1"
  26624. + else
  26625. + echo " ${prog}: Cannot open '$1'" >&2
  26626. + exit 1
  26627. + fi
  26628. +}
  26629. +
  26630. +prog=$0
  26631. +root_uid=0
  26632. +root_gid=0
  26633. +dep_list=
  26634. +cpio_file=
  26635. +cpio_list=
  26636. +output="/dev/stdout"
  26637. +output_file=""
  26638. +opt=""
  26639. +
  26640. +arg="$1"
  26641. +case "$arg" in
  26642. + "-l") # files included in initramfs - used by kbuild
  26643. + dep_list="list_"
  26644. + echo "deps_initramfs := \\"
  26645. + shift
  26646. + ;;
  26647. + "-o") # generate lzma-ed cpio image named $1
  26648. + shift
  26649. + output_file="$1"
  26650. + cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
  26651. + output=${cpio_list}
  26652. + shift
  26653. + ;;
  26654. +esac
  26655. +while [ $# -gt 0 ]; do
  26656. + arg="$1"
  26657. + shift
  26658. + case "$arg" in
  26659. + "-u") # map $1 to uid=0 (root)
  26660. + root_uid="$1"
  26661. + shift
  26662. + ;;
  26663. + "-g") # map $1 to gid=0 (root)
  26664. + root_gid="$1"
  26665. + shift
  26666. + ;;
  26667. + "-s")
  26668. + opt="-d16"
  26669. + ;;
  26670. + "-d") # display default initramfs list
  26671. + default_list="$arg"
  26672. + ${dep_list}default_initramfs
  26673. + ;;
  26674. + "-h")
  26675. + usage
  26676. + exit 0
  26677. + ;;
  26678. + *)
  26679. + case "$arg" in
  26680. + "-"*)
  26681. + unknown_option
  26682. + ;;
  26683. + *) # input file/dir - process it
  26684. + input_file "$arg" "$#"
  26685. + ;;
  26686. + esac
  26687. + ;;
  26688. + esac
  26689. +done
  26690. +
  26691. +# If output_file is set we will generate cpio archive and lzma it
  26692. +# we are carefull to delete tmp files
  26693. +if [ ! -z ${output_file} ]; then
  26694. + if [ -z ${cpio_file} ]; then
  26695. + cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
  26696. + usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
  26697. + else
  26698. + cpio_tfile=${cpio_file}
  26699. + fi
  26700. + rm ${cpio_list}
  26701. + lzma e ${cpio_tfile} ${output_file} ${opt}
  26702. + [ -z ${cpio_file} ] && rm ${cpio_tfile}
  26703. +fi
  26704. +exit 0
  26705. diff -rduNp linux-2.6.22.1.oorig/shrinkconfig.sh linux-2.6.22.1/shrinkconfig.sh
  26706. --- linux-2.6.22.1.oorig/shrinkconfig.sh 1970-01-01 01:00:00.000000000 +0100
  26707. +++ linux-2.6.22.1/shrinkconfig.sh 2007-07-24 14:17:46.000000000 +0200
  26708. @@ -0,0 +1,79 @@
  26709. +#! /bin/bash
  26710. +
  26711. +# shrinkconfig copyright 2006 by Rob Landley <rob@landley.net>
  26712. +# Licensed under the GNU General Public License version 2.
  26713. +
  26714. +if [ $# -ne 1 ]
  26715. +then
  26716. + echo "Turns current .config into a miniconfig file."
  26717. + echo "Usage: shrinkconfig mini.config"
  26718. + exit 1
  26719. +fi
  26720. +
  26721. +if [ ! -f .config ]
  26722. +then
  26723. + echo "Need a .config file to shrink."
  26724. + exit 1
  26725. +fi
  26726. +LENGTH=$(wc -l < .config)
  26727. +
  26728. +OUTPUT="$1"
  26729. +cp .config "$OUTPUT"
  26730. +if [ $? -ne 0 ]
  26731. +then
  26732. + echo "Couldn't create $OUTPUT"
  26733. + exit 1
  26734. +fi
  26735. +
  26736. +# If we get interrupted, clean up the mess
  26737. +
  26738. +KERNELOUTPUT=""
  26739. +
  26740. +function cleanup
  26741. +{
  26742. + echo
  26743. + echo "Interrupted."
  26744. + [ ! -z "$KERNELOUTPUT" ] && rm -rf "$KERNELOUTPUT"
  26745. + rm "$OUTPUT"
  26746. + exit 1
  26747. +}
  26748. +
  26749. +trap cleanup HUP INT QUIT TERM
  26750. +
  26751. +# Since the "O=" argument to make doesn't work recursively, we need to jump
  26752. +# through a few hoops to avoid overwriting the .config that we're shrinking.
  26753. +
  26754. +# If we're building out of tree, we'll have absolute paths to source and build
  26755. +# directories in the Makefile.
  26756. +
  26757. +KERNELSRC=$(sed -n -e 's/KERNELSRC[^/]*:=[^/]*//p' Makefile)
  26758. +[ -z "$KERNELSRC" ] && KERNELSRC=$(pwd)
  26759. +KERNELOUTPUT=`pwd`/.config.minitemp
  26760. +
  26761. +mkdir -p "$KERNELOUTPUT" || exit 1
  26762. +
  26763. +echo "Shrinking .config to $OUTPUT..."
  26764. +
  26765. +for I in $(seq 1 $LENGTH)
  26766. +do
  26767. + echo -n -e "\r"$I/$LENGTH lines $(wc -c < "$OUTPUT") bytes
  26768. +
  26769. + sed -n "${I}!p" "$OUTPUT" > "$KERNELOUTPUT"/.config.test
  26770. + # Do a config with this file
  26771. + make -C "$KERNELSRC" O="$KERNELOUTPUT" allnoconfig KCONFIG_ALLCONFIG="$KERNELOUTPUT"/.config.test > /dev/null
  26772. +
  26773. + # Compare. The date changes, so expect a small difference each time.
  26774. + D=$(diff "$KERNELOUTPUT"/.config .config | wc -l)
  26775. + if [ $D -eq 4 ]
  26776. + then
  26777. + mv "$KERNELOUTPUT"/.config.test "$OUTPUT"
  26778. + LENGTH=$[$LENGTH-1]
  26779. + else
  26780. + I=$[$I + 1]
  26781. + fi
  26782. +done
  26783. +
  26784. +rm -rf "$KERNELOUTPUT"
  26785. +
  26786. +# One extra echo to preserve status line.
  26787. +echo
  26788. diff -rduNp linux-2.6.22.1.oorig/usr/Makefile linux-2.6.22.1/usr/Makefile
  26789. --- linux-2.6.22.1.oorig/usr/Makefile 2007-07-10 20:56:30.000000000 +0200
  26790. +++ linux-2.6.22.1/usr/Makefile 2007-07-24 14:17:46.000000000 +0200
  26791. @@ -19,6 +19,7 @@ $(obj)/initramfs_data.o: $(obj)/initramf
  26792. hostprogs-y := gen_init_cpio
  26793. initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
  26794. +lzma_initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_lzma_initramfs_list.sh
  26795. ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
  26796. $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
  26797. ramfs-args := \
  26798. @@ -36,6 +37,14 @@ endif
  26799. quiet_cmd_initfs = GEN $@
  26800. cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
  26801. +ifdef CONFIG_LZMA_INITRAM_FS_SMALLMEM
  26802. +quiet_cmd_lzma_initfs = LZRAMFS $@
  26803. + cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) -s $(ramfs-input)
  26804. +else
  26805. +quiet_cmd_lzma_initfs = LZRAMFS $@
  26806. + cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) $(ramfs-input)
  26807. +endif
  26808. +
  26809. targets := initramfs_data.cpio.gz
  26810. # do not try to update files included in initramfs
  26811. $(deps_initramfs): ;
  26812. @@ -48,5 +57,9 @@ $(deps_initramfs): klibcdirs
  26813. # 4) arguments to gen_initramfs.sh changes
  26814. $(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
  26815. $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
  26816. +ifdef CONFIG_LZMA_INITRAM_FS
  26817. + $(call if_changed,lzma_initfs)
  26818. +else
  26819. $(call if_changed,initfs)
  26820. +endif