linux-2.6.21.5-001-lzma-vmlinuz.00.patch 705 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017
  1. diff --git a/.miniconfig b/.miniconfig
  2. new file mode 100644
  3. index 0000000..5686e53
  4. --- /dev/null
  5. +++ b/.miniconfig
  6. @@ -0,0 +1,89 @@
  7. +#make allnoconfig KCONFIG_ALLCONFIG=miniconfig
  8. +CONFIG_X86_32=y
  9. +CONFIG_CLOCKSOURCE_WATCHDOG=y
  10. +CONFIG_LOCKDEP_SUPPORT=y
  11. +CONFIG_SEMAPHORE_SLEEPERS=y
  12. +CONFIG_MMU=y
  13. +CONFIG_GENERIC_ISA_DMA=y
  14. +CONFIG_GENERIC_HWEIGHT=y
  15. +CONFIG_DMI=y
  16. +CONFIG_INIT_ENV_ARG_LIMIT=32
  17. +CONFIG_IKCONFIG=y
  18. +CONFIG_IKCONFIG_PROC=y
  19. +CONFIG_SYSFS_DEPRECATED=y
  20. +CONFIG_BLK_DEV_INITRD=y
  21. +CONFIG_SYSCTL=y
  22. +CONFIG_EMBEDDED=y
  23. +CONFIG_PRINTK=y
  24. +CONFIG_BASE_SMALL=1
  25. +CONFIG_BLOCK=y
  26. +CONFIG_IOSCHED_NOOP=y
  27. +CONFIG_DEFAULT_IOSCHED="noop"
  28. +CONFIG_X86_GENERIC=y
  29. +CONFIG_X86_L1_CACHE_SHIFT=7
  30. +CONFIG_GENERIC_CALIBRATE_DELAY=y
  31. +CONFIG_X86_WP_WORKS_OK=y
  32. +CONFIG_X86_BSWAP=y
  33. +CONFIG_X86_CMPXCHG64=y
  34. +CONFIG_X86_INTEL_USERCOPY=y
  35. +CONFIG_X86_TSC=y
  36. +CONFIG_PREEMPT_NONE=y
  37. +CONFIG_VM86=y
  38. +CONFIG_HIGHMEM=y
  39. +CONFIG_FLATMEM=y
  40. +CONFIG_MTRR=y
  41. +CONFIG_HZ_250=y
  42. +CONFIG_PHYSICAL_ALIGN=0x100000
  43. +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
  44. +CONFIG_PM=y
  45. +CONFIG_ACPI=y
  46. +CONFIG_ACPI_SLEEP=y
  47. +CONFIG_ACPI_BLACKLIST_YEAR=0
  48. +CONFIG_ACPI_EC=y
  49. +CONFIG_ACPI_SYSTEM=y
  50. +CONFIG_PCI=y
  51. +CONFIG_PCI_GOANY=y
  52. +CONFIG_PCI_DIRECT=y
  53. +CONFIG_BINFMT_ELF=y
  54. +CONFIG_STANDALONE=y
  55. +CONFIG_BLK_DEV_LOOP=y
  56. +CONFIG_IDE=y
  57. +CONFIG_IDE_MAX_HWIFS=2
  58. +CONFIG_BLK_DEV_IDE=y
  59. +CONFIG_BLK_DEV_IDEDISK=y
  60. +CONFIG_IDEDISK_MULTI_MODE=y
  61. +CONFIG_BLK_DEV_IDECD=y
  62. +CONFIG_IDE_GENERIC=y
  63. +CONFIG_INPUT_MOUSEDEV=y
  64. +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
  65. +CONFIG_INPUT_KEYBOARD=y
  66. +CONFIG_KEYBOARD_ATKBD=y
  67. +CONFIG_SERIO=y
  68. +CONFIG_VT=y
  69. +CONFIG_VT_CONSOLE=y
  70. +CONFIG_UNIX98_PTYS=y
  71. +CONFIG_VGA_CONSOLE=y
  72. +CONFIG_USB_ARCH_HAS_HCD=y
  73. +CONFIG_USB_ARCH_HAS_EHCI=y
  74. +CONFIG_EXT2_FS=y
  75. +CONFIG_DNOTIFY=y
  76. +CONFIG_ISO9660_FS=y
  77. +CONFIG_FAT_FS=y
  78. +CONFIG_VFAT_FS=y
  79. +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
  80. +CONFIG_PROC_FS=y
  81. +CONFIG_PROC_SYSCTL=y
  82. +CONFIG_SYSFS=y
  83. +CONFIG_RAMFS=y
  84. +CONFIG_SQUASHFS=y
  85. +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
  86. +CONFIG_MSDOS_PARTITION=y
  87. +CONFIG_NLS_DEFAULT="iso8859-1"
  88. +CONFIG_AUFS=y
  89. +CONFIG_AUFS_FAKE_DM=y
  90. +CONFIG_EARLY_PRINTK=y
  91. +CONFIG_DOUBLEFAULT=y
  92. +CONFIG_ZLIB_INFLATE=y
  93. +CONFIG_HAS_IOPORT=y
  94. +CONFIG_GENERIC_IRQ_PROBE=y
  95. +CONFIG_KTIME_SCALAR=y
  96. diff --git a/Makefile b/Makefile
  97. index d970cb1..a369204 100644
  98. --- a/Makefile
  99. +++ b/Makefile
  100. @@ -188,7 +188,7 @@ CROSS_COMPILE ?=
  101. # Architecture as present in compile.h
  102. UTS_MACHINE := $(ARCH)
  103. -KCONFIG_CONFIG ?= .config
  104. +KCONFIG_CONFIG ?= .miniconfig
  105. # SHELL used by kbuild
  106. CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
  107. diff --git a/arch/i386/boot/compressed/LzmaDecode.c b/arch/i386/boot/compressed/LzmaDecode.c
  108. new file mode 100644
  109. index 0000000..21bf40b
  110. --- /dev/null
  111. +++ b/arch/i386/boot/compressed/LzmaDecode.c
  112. @@ -0,0 +1,588 @@
  113. +/*
  114. + LzmaDecode.c
  115. + LZMA Decoder (optimized for Speed version)
  116. +
  117. + LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
  118. + http://www.7-zip.org/
  119. +
  120. + LZMA SDK is licensed under two licenses:
  121. + 1) GNU Lesser General Public License (GNU LGPL)
  122. + 2) Common Public License (CPL)
  123. + It means that you can select one of these two licenses and
  124. + follow rules of that license.
  125. +
  126. + SPECIAL EXCEPTION:
  127. + Igor Pavlov, as the author of this Code, expressly permits you to
  128. + statically or dynamically link your Code (or bind by name) to the
  129. + interfaces of this file without subjecting your linked Code to the
  130. + terms of the CPL or GNU LGPL. Any modifications or additions
  131. + to this file, however, are subject to the LGPL or CPL terms.
  132. +*/
  133. +
  134. +#include "LzmaDecode.h"
  135. +
  136. +#ifndef Byte
  137. +#define Byte unsigned char
  138. +#endif
  139. +
  140. +#define kNumTopBits 24
  141. +#define kTopValue ((UInt32)1 << kNumTopBits)
  142. +
  143. +#define kNumBitModelTotalBits 11
  144. +#define kBitModelTotal (1 << kNumBitModelTotalBits)
  145. +#define kNumMoveBits 5
  146. +
  147. +#define RC_READ_BYTE (*Buffer++)
  148. +
  149. +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
  150. + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
  151. +
  152. +#ifdef _LZMA_IN_CB
  153. +
  154. +#define RC_TEST { if (Buffer == BufferLim) \
  155. + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
  156. + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
  157. +
  158. +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
  159. +
  160. +#else
  161. +
  162. +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
  163. +
  164. +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
  165. +
  166. +#endif
  167. +
  168. +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
  169. +
  170. +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
  171. +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
  172. +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
  173. +
  174. +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
  175. + { UpdateBit0(p); mi <<= 1; A0; } else \
  176. + { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
  177. +
  178. +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
  179. +
  180. +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
  181. + { int i = numLevels; res = 1; \
  182. + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
  183. + res -= (1 << numLevels); }
  184. +
  185. +
  186. +#define kNumPosBitsMax 4
  187. +#define kNumPosStatesMax (1 << kNumPosBitsMax)
  188. +
  189. +#define kLenNumLowBits 3
  190. +#define kLenNumLowSymbols (1 << kLenNumLowBits)
  191. +#define kLenNumMidBits 3
  192. +#define kLenNumMidSymbols (1 << kLenNumMidBits)
  193. +#define kLenNumHighBits 8
  194. +#define kLenNumHighSymbols (1 << kLenNumHighBits)
  195. +
  196. +#define LenChoice 0
  197. +#define LenChoice2 (LenChoice + 1)
  198. +#define LenLow (LenChoice2 + 1)
  199. +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
  200. +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
  201. +#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
  202. +
  203. +
  204. +#define kNumStates 12
  205. +#define kNumLitStates 7
  206. +
  207. +#define kStartPosModelIndex 4
  208. +#define kEndPosModelIndex 14
  209. +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
  210. +
  211. +#define kNumPosSlotBits 6
  212. +#define kNumLenToPosStates 4
  213. +
  214. +#define kNumAlignBits 4
  215. +#define kAlignTableSize (1 << kNumAlignBits)
  216. +
  217. +#define kMatchMinLen 2
  218. +
  219. +#define IsMatch 0
  220. +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
  221. +#define IsRepG0 (IsRep + kNumStates)
  222. +#define IsRepG1 (IsRepG0 + kNumStates)
  223. +#define IsRepG2 (IsRepG1 + kNumStates)
  224. +#define IsRep0Long (IsRepG2 + kNumStates)
  225. +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
  226. +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
  227. +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
  228. +#define LenCoder (Align + kAlignTableSize)
  229. +#define RepLenCoder (LenCoder + kNumLenProbs)
  230. +#define Literal (RepLenCoder + kNumLenProbs)
  231. +
  232. +#if Literal != LZMA_BASE_SIZE
  233. +StopCompilingDueBUG
  234. +#endif
  235. +
  236. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
  237. +{
  238. + unsigned char prop0;
  239. + if (size < LZMA_PROPERTIES_SIZE)
  240. + return LZMA_RESULT_DATA_ERROR;
  241. + prop0 = propsData[0];
  242. + if (prop0 >= (9 * 5 * 5))
  243. + return LZMA_RESULT_DATA_ERROR;
  244. + {
  245. + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
  246. + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
  247. + propsRes->lc = prop0;
  248. + /*
  249. + unsigned char remainder = (unsigned char)(prop0 / 9);
  250. + propsRes->lc = prop0 % 9;
  251. + propsRes->pb = remainder / 5;
  252. + propsRes->lp = remainder % 5;
  253. + */
  254. + }
  255. +
  256. + #ifdef _LZMA_OUT_READ
  257. + {
  258. + int i;
  259. + propsRes->DictionarySize = 0;
  260. + for (i = 0; i < 4; i++)
  261. + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
  262. + if (propsRes->DictionarySize == 0)
  263. + propsRes->DictionarySize = 1;
  264. + }
  265. + #endif
  266. + return LZMA_RESULT_OK;
  267. +}
  268. +
  269. +#define kLzmaStreamWasFinishedId (-1)
  270. +
  271. +int LzmaDecode(CLzmaDecoderState *vs,
  272. + #ifdef _LZMA_IN_CB
  273. + ILzmaInCallback *InCallback,
  274. + #else
  275. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  276. + #endif
  277. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
  278. +{
  279. + CProb *p = vs->Probs;
  280. + SizeT nowPos = 0;
  281. + Byte previousByte = 0;
  282. + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
  283. + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
  284. + int lc = vs->Properties.lc;
  285. +
  286. + #ifdef _LZMA_OUT_READ
  287. +
  288. + UInt32 Range = vs->Range;
  289. + UInt32 Code = vs->Code;
  290. + #ifdef _LZMA_IN_CB
  291. + const Byte *Buffer = vs->Buffer;
  292. + const Byte *BufferLim = vs->BufferLim;
  293. + #else
  294. + const Byte *Buffer = inStream;
  295. + const Byte *BufferLim = inStream + inSize;
  296. + #endif
  297. + int state = vs->State;
  298. + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
  299. + int len = vs->RemainLen;
  300. + UInt32 globalPos = vs->GlobalPos;
  301. + UInt32 distanceLimit = vs->DistanceLimit;
  302. +
  303. + Byte *dictionary = vs->Dictionary;
  304. + UInt32 dictionarySize = vs->Properties.DictionarySize;
  305. + UInt32 dictionaryPos = vs->DictionaryPos;
  306. +
  307. + Byte tempDictionary[4];
  308. +
  309. + #ifndef _LZMA_IN_CB
  310. + *inSizeProcessed = 0;
  311. + #endif
  312. + *outSizeProcessed = 0;
  313. + if (len == kLzmaStreamWasFinishedId)
  314. + return LZMA_RESULT_OK;
  315. +
  316. + if (dictionarySize == 0)
  317. + {
  318. + dictionary = tempDictionary;
  319. + dictionarySize = 1;
  320. + tempDictionary[0] = vs->TempDictionary[0];
  321. + }
  322. +
  323. + if (len == kLzmaNeedInitId)
  324. + {
  325. + {
  326. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  327. + UInt32 i;
  328. + for (i = 0; i < numProbs; i++)
  329. + p[i] = kBitModelTotal >> 1;
  330. + rep0 = rep1 = rep2 = rep3 = 1;
  331. + state = 0;
  332. + globalPos = 0;
  333. + distanceLimit = 0;
  334. + dictionaryPos = 0;
  335. + dictionary[dictionarySize - 1] = 0;
  336. + #ifdef _LZMA_IN_CB
  337. + RC_INIT;
  338. + #else
  339. + RC_INIT(inStream, inSize);
  340. + #endif
  341. + }
  342. + len = 0;
  343. + }
  344. + while(len != 0 && nowPos < outSize)
  345. + {
  346. + UInt32 pos = dictionaryPos - rep0;
  347. + if (pos >= dictionarySize)
  348. + pos += dictionarySize;
  349. + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
  350. + if (++dictionaryPos == dictionarySize)
  351. + dictionaryPos = 0;
  352. + len--;
  353. + }
  354. + if (dictionaryPos == 0)
  355. + previousByte = dictionary[dictionarySize - 1];
  356. + else
  357. + previousByte = dictionary[dictionaryPos - 1];
  358. +
  359. + #else /* if !_LZMA_OUT_READ */
  360. +
  361. + int state = 0;
  362. + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
  363. + int len = 0;
  364. + const Byte *Buffer;
  365. + const Byte *BufferLim;
  366. + UInt32 Range;
  367. + UInt32 Code;
  368. +
  369. + #ifndef _LZMA_IN_CB
  370. + *inSizeProcessed = 0;
  371. + #endif
  372. + *outSizeProcessed = 0;
  373. +
  374. + {
  375. + UInt32 i;
  376. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  377. + for (i = 0; i < numProbs; i++)
  378. + p[i] = kBitModelTotal >> 1;
  379. + }
  380. +
  381. + #ifdef _LZMA_IN_CB
  382. + RC_INIT;
  383. + #else
  384. + RC_INIT(inStream, inSize);
  385. + #endif
  386. +
  387. + #endif /* _LZMA_OUT_READ */
  388. +
  389. + while(nowPos < outSize)
  390. + {
  391. + CProb *prob;
  392. + UInt32 bound;
  393. + int posState = (int)(
  394. + (nowPos
  395. + #ifdef _LZMA_OUT_READ
  396. + + globalPos
  397. + #endif
  398. + )
  399. + & posStateMask);
  400. +
  401. + prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
  402. + IfBit0(prob)
  403. + {
  404. + int symbol = 1;
  405. + UpdateBit0(prob)
  406. + prob = p + Literal + (LZMA_LIT_SIZE *
  407. + (((
  408. + (nowPos
  409. + #ifdef _LZMA_OUT_READ
  410. + + globalPos
  411. + #endif
  412. + )
  413. + & literalPosMask) << lc) + (previousByte >> (8 - lc))));
  414. +
  415. + if (state >= kNumLitStates)
  416. + {
  417. + int matchByte;
  418. + #ifdef _LZMA_OUT_READ
  419. + UInt32 pos = dictionaryPos - rep0;
  420. + if (pos >= dictionarySize)
  421. + pos += dictionarySize;
  422. + matchByte = dictionary[pos];
  423. + #else
  424. + matchByte = outStream[nowPos - rep0];
  425. + #endif
  426. + do
  427. + {
  428. + int bit;
  429. + CProb *probLit;
  430. + matchByte <<= 1;
  431. + bit = (matchByte & 0x100);
  432. + probLit = prob + 0x100 + bit + symbol;
  433. + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
  434. + }
  435. + while (symbol < 0x100);
  436. + }
  437. + while (symbol < 0x100)
  438. + {
  439. + CProb *probLit = prob + symbol;
  440. + RC_GET_BIT(probLit, symbol)
  441. + }
  442. + previousByte = (Byte)symbol;
  443. +
  444. + outStream[nowPos++] = previousByte;
  445. + #ifdef _LZMA_OUT_READ
  446. + if (distanceLimit < dictionarySize)
  447. + distanceLimit++;
  448. +
  449. + dictionary[dictionaryPos] = previousByte;
  450. + if (++dictionaryPos == dictionarySize)
  451. + dictionaryPos = 0;
  452. + #endif
  453. + if (state < 4) state = 0;
  454. + else if (state < 10) state -= 3;
  455. + else state -= 6;
  456. + }
  457. + else
  458. + {
  459. + UpdateBit1(prob);
  460. + prob = p + IsRep + state;
  461. + IfBit0(prob)
  462. + {
  463. + UpdateBit0(prob);
  464. + rep3 = rep2;
  465. + rep2 = rep1;
  466. + rep1 = rep0;
  467. + state = state < kNumLitStates ? 0 : 3;
  468. + prob = p + LenCoder;
  469. + }
  470. + else
  471. + {
  472. + UpdateBit1(prob);
  473. + prob = p + IsRepG0 + state;
  474. + IfBit0(prob)
  475. + {
  476. + UpdateBit0(prob);
  477. + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
  478. + IfBit0(prob)
  479. + {
  480. + #ifdef _LZMA_OUT_READ
  481. + UInt32 pos;
  482. + #endif
  483. + UpdateBit0(prob);
  484. +
  485. + #ifdef _LZMA_OUT_READ
  486. + if (distanceLimit == 0)
  487. + #else
  488. + if (nowPos == 0)
  489. + #endif
  490. + return LZMA_RESULT_DATA_ERROR;
  491. +
  492. + state = state < kNumLitStates ? 9 : 11;
  493. + #ifdef _LZMA_OUT_READ
  494. + pos = dictionaryPos - rep0;
  495. + if (pos >= dictionarySize)
  496. + pos += dictionarySize;
  497. + previousByte = dictionary[pos];
  498. + dictionary[dictionaryPos] = previousByte;
  499. + if (++dictionaryPos == dictionarySize)
  500. + dictionaryPos = 0;
  501. + #else
  502. + previousByte = outStream[nowPos - rep0];
  503. + #endif
  504. + outStream[nowPos++] = previousByte;
  505. + #ifdef _LZMA_OUT_READ
  506. + if (distanceLimit < dictionarySize)
  507. + distanceLimit++;
  508. + #endif
  509. +
  510. + continue;
  511. + }
  512. + else
  513. + {
  514. + UpdateBit1(prob);
  515. + }
  516. + }
  517. + else
  518. + {
  519. + UInt32 distance;
  520. + UpdateBit1(prob);
  521. + prob = p + IsRepG1 + state;
  522. + IfBit0(prob)
  523. + {
  524. + UpdateBit0(prob);
  525. + distance = rep1;
  526. + }
  527. + else
  528. + {
  529. + UpdateBit1(prob);
  530. + prob = p + IsRepG2 + state;
  531. + IfBit0(prob)
  532. + {
  533. + UpdateBit0(prob);
  534. + distance = rep2;
  535. + }
  536. + else
  537. + {
  538. + UpdateBit1(prob);
  539. + distance = rep3;
  540. + rep3 = rep2;
  541. + }
  542. + rep2 = rep1;
  543. + }
  544. + rep1 = rep0;
  545. + rep0 = distance;
  546. + }
  547. + state = state < kNumLitStates ? 8 : 11;
  548. + prob = p + RepLenCoder;
  549. + }
  550. + {
  551. + int numBits, offset;
  552. + CProb *probLen = prob + LenChoice;
  553. + IfBit0(probLen)
  554. + {
  555. + UpdateBit0(probLen);
  556. + probLen = prob + LenLow + (posState << kLenNumLowBits);
  557. + offset = 0;
  558. + numBits = kLenNumLowBits;
  559. + }
  560. + else
  561. + {
  562. + UpdateBit1(probLen);
  563. + probLen = prob + LenChoice2;
  564. + IfBit0(probLen)
  565. + {
  566. + UpdateBit0(probLen);
  567. + probLen = prob + LenMid + (posState << kLenNumMidBits);
  568. + offset = kLenNumLowSymbols;
  569. + numBits = kLenNumMidBits;
  570. + }
  571. + else
  572. + {
  573. + UpdateBit1(probLen);
  574. + probLen = prob + LenHigh;
  575. + offset = kLenNumLowSymbols + kLenNumMidSymbols;
  576. + numBits = kLenNumHighBits;
  577. + }
  578. + }
  579. + RangeDecoderBitTreeDecode(probLen, numBits, len);
  580. + len += offset;
  581. + }
  582. +
  583. + if (state < 4)
  584. + {
  585. + int posSlot;
  586. + state += kNumLitStates;
  587. + prob = p + PosSlot +
  588. + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
  589. + kNumPosSlotBits);
  590. + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
  591. + if (posSlot >= kStartPosModelIndex)
  592. + {
  593. + int numDirectBits = ((posSlot >> 1) - 1);
  594. + rep0 = (2 | ((UInt32)posSlot & 1));
  595. + if (posSlot < kEndPosModelIndex)
  596. + {
  597. + rep0 <<= numDirectBits;
  598. + prob = p + SpecPos + rep0 - posSlot - 1;
  599. + }
  600. + else
  601. + {
  602. + numDirectBits -= kNumAlignBits;
  603. + do
  604. + {
  605. + RC_NORMALIZE
  606. + Range >>= 1;
  607. + rep0 <<= 1;
  608. + if (Code >= Range)
  609. + {
  610. + Code -= Range;
  611. + rep0 |= 1;
  612. + }
  613. + }
  614. + while (--numDirectBits != 0);
  615. + prob = p + Align;
  616. + rep0 <<= kNumAlignBits;
  617. + numDirectBits = kNumAlignBits;
  618. + }
  619. + {
  620. + int i = 1;
  621. + int mi = 1;
  622. + do
  623. + {
  624. + CProb *prob3 = prob + mi;
  625. + RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
  626. + i <<= 1;
  627. + }
  628. + while(--numDirectBits != 0);
  629. + }
  630. + }
  631. + else
  632. + rep0 = posSlot;
  633. + if (++rep0 == (UInt32)(0))
  634. + {
  635. + /* it's for stream version */
  636. + len = kLzmaStreamWasFinishedId;
  637. + break;
  638. + }
  639. + }
  640. +
  641. + len += kMatchMinLen;
  642. + #ifdef _LZMA_OUT_READ
  643. + if (rep0 > distanceLimit)
  644. + #else
  645. + if (rep0 > nowPos)
  646. + #endif
  647. + return LZMA_RESULT_DATA_ERROR;
  648. +
  649. + #ifdef _LZMA_OUT_READ
  650. + if (dictionarySize - distanceLimit > (UInt32)len)
  651. + distanceLimit += len;
  652. + else
  653. + distanceLimit = dictionarySize;
  654. + #endif
  655. +
  656. + do
  657. + {
  658. + #ifdef _LZMA_OUT_READ
  659. + UInt32 pos = dictionaryPos - rep0;
  660. + if (pos >= dictionarySize)
  661. + pos += dictionarySize;
  662. + previousByte = dictionary[pos];
  663. + dictionary[dictionaryPos] = previousByte;
  664. + if (++dictionaryPos == dictionarySize)
  665. + dictionaryPos = 0;
  666. + #else
  667. + previousByte = outStream[nowPos - rep0];
  668. + #endif
  669. + len--;
  670. + outStream[nowPos++] = previousByte;
  671. + }
  672. + while(len != 0 && nowPos < outSize);
  673. + }
  674. + }
  675. + RC_NORMALIZE;
  676. +
  677. + #ifdef _LZMA_OUT_READ
  678. + vs->Range = Range;
  679. + vs->Code = Code;
  680. + vs->DictionaryPos = dictionaryPos;
  681. + vs->GlobalPos = globalPos + (UInt32)nowPos;
  682. + vs->DistanceLimit = distanceLimit;
  683. + vs->Reps[0] = rep0;
  684. + vs->Reps[1] = rep1;
  685. + vs->Reps[2] = rep2;
  686. + vs->Reps[3] = rep3;
  687. + vs->State = state;
  688. + vs->RemainLen = len;
  689. + vs->TempDictionary[0] = tempDictionary[0];
  690. + #endif
  691. +
  692. + #ifdef _LZMA_IN_CB
  693. + vs->Buffer = Buffer;
  694. + vs->BufferLim = BufferLim;
  695. + #else
  696. + *inSizeProcessed = (SizeT)(Buffer - inStream);
  697. + #endif
  698. + *outSizeProcessed = nowPos;
  699. + return LZMA_RESULT_OK;
  700. +}
  701. diff --git a/arch/i386/boot/compressed/LzmaDecode.h b/arch/i386/boot/compressed/LzmaDecode.h
  702. new file mode 100644
  703. index 0000000..213062a
  704. --- /dev/null
  705. +++ b/arch/i386/boot/compressed/LzmaDecode.h
  706. @@ -0,0 +1,131 @@
  707. +/*
  708. + LzmaDecode.h
  709. + LZMA Decoder interface
  710. +
  711. + LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
  712. + http://www.7-zip.org/
  713. +
  714. + LZMA SDK is licensed under two licenses:
  715. + 1) GNU Lesser General Public License (GNU LGPL)
  716. + 2) Common Public License (CPL)
  717. + It means that you can select one of these two licenses and
  718. + follow rules of that license.
  719. +
  720. + SPECIAL EXCEPTION:
  721. + Igor Pavlov, as the author of this code, expressly permits you to
  722. + statically or dynamically link your code (or bind by name) to the
  723. + interfaces of this file without subjecting your linked code to the
  724. + terms of the CPL or GNU LGPL. Any modifications or additions
  725. + to this file, however, are subject to the LGPL or CPL terms.
  726. +*/
  727. +
  728. +#ifndef __LZMADECODE_H
  729. +#define __LZMADECODE_H
  730. +
  731. +/* #define _LZMA_IN_CB */
  732. +/* Use callback for input data */
  733. +
  734. +/* #define _LZMA_OUT_READ */
  735. +/* Use read function for output data */
  736. +
  737. +/* #define _LZMA_PROB32 */
  738. +/* It can increase speed on some 32-bit CPUs,
  739. + but memory usage will be doubled in that case */
  740. +
  741. +/* #define _LZMA_LOC_OPT */
  742. +/* Enable local speed optimizations inside code */
  743. +
  744. +/* #define _LZMA_SYSTEM_SIZE_T */
  745. +/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
  746. +
  747. +#ifndef UInt32
  748. +#ifdef _LZMA_UINT32_IS_ULONG
  749. +#define UInt32 unsigned long
  750. +#else
  751. +#define UInt32 unsigned int
  752. +#endif
  753. +#endif
  754. +
  755. +#ifndef SizeT
  756. +#ifdef _LZMA_SYSTEM_SIZE_T
  757. +#include <stddef.h>
  758. +#define SizeT size_t
  759. +#else
  760. +#define SizeT UInt32
  761. +#endif
  762. +#endif
  763. +
  764. +#ifdef _LZMA_PROB32
  765. +#define CProb UInt32
  766. +#else
  767. +#define CProb unsigned short
  768. +#endif
  769. +
  770. +#define LZMA_RESULT_OK 0
  771. +#define LZMA_RESULT_DATA_ERROR 1
  772. +
  773. +#ifdef _LZMA_IN_CB
  774. +typedef struct _ILzmaInCallback
  775. +{
  776. + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
  777. +} ILzmaInCallback;
  778. +#endif
  779. +
  780. +#define LZMA_BASE_SIZE 1846
  781. +#define LZMA_LIT_SIZE 768
  782. +
  783. +#define LZMA_PROPERTIES_SIZE 5
  784. +
  785. +typedef struct _CLzmaProperties
  786. +{
  787. + int lc;
  788. + int lp;
  789. + int pb;
  790. + #ifdef _LZMA_OUT_READ
  791. + UInt32 DictionarySize;
  792. + #endif
  793. +}CLzmaProperties;
  794. +
  795. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
  796. +
  797. +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
  798. +
  799. +#define kLzmaNeedInitId (-2)
  800. +
  801. +typedef struct _CLzmaDecoderState
  802. +{
  803. + CLzmaProperties Properties;
  804. + CProb *Probs;
  805. +
  806. + #ifdef _LZMA_IN_CB
  807. + const unsigned char *Buffer;
  808. + const unsigned char *BufferLim;
  809. + #endif
  810. +
  811. + #ifdef _LZMA_OUT_READ
  812. + unsigned char *Dictionary;
  813. + UInt32 Range;
  814. + UInt32 Code;
  815. + UInt32 DictionaryPos;
  816. + UInt32 GlobalPos;
  817. + UInt32 DistanceLimit;
  818. + UInt32 Reps[4];
  819. + int State;
  820. + int RemainLen;
  821. + unsigned char TempDictionary[4];
  822. + #endif
  823. +} CLzmaDecoderState;
  824. +
  825. +#ifdef _LZMA_OUT_READ
  826. +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
  827. +#endif
  828. +
  829. +int LzmaDecode(CLzmaDecoderState *vs,
  830. + #ifdef _LZMA_IN_CB
  831. + ILzmaInCallback *inCallback,
  832. + #else
  833. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  834. + #endif
  835. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
  836. +
  837. +#endif
  838. diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
  839. index a661217..fb40869 100644
  840. --- a/arch/i386/boot/compressed/Makefile
  841. +++ b/arch/i386/boot/compressed/Makefile
  842. @@ -4,15 +4,16 @@
  843. # create a compressed vmlinux image from the original vmlinux
  844. #
  845. -targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
  846. - vmlinux.bin.all vmlinux.relocs
  847. +tragets := head.o lzma_misc.o piggy.o \
  848. + vmlinux.bin.all vmlinux.relocs \
  849. + vmlinux vmlinux.bin vmlinux.bin.gz
  850. EXTRA_AFLAGS := -traditional
  851. LDFLAGS_vmlinux := -T
  852. -CFLAGS_misc.o += -fPIC
  853. +CFLAGS_lzma_misc.o += -fPIC
  854. hostprogs-y := relocs
  855. -$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
  856. +$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/lzma_misc.o $(obj)/piggy.o FORCE
  857. $(call if_changed,ld)
  858. @:
  859. @@ -33,10 +34,10 @@ $(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
  860. ifdef CONFIG_RELOCATABLE
  861. $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
  862. - $(call if_changed,gzip)
  863. + $(call if_changed,lzma)
  864. else
  865. $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
  866. - $(call if_changed,gzip)
  867. + $(call if_changed,lzma)
  868. endif
  869. LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
  870. diff --git a/arch/i386/boot/compressed/lzma_misc.c b/arch/i386/boot/compressed/lzma_misc.c
  871. new file mode 100644
  872. index 0000000..4f5f7f9
  873. --- /dev/null
  874. +++ b/arch/i386/boot/compressed/lzma_misc.c
  875. @@ -0,0 +1,290 @@
  876. +/*
  877. + * lzma_misc.c
  878. + *
  879. + * Decompress LZMA compressed vmlinuz
  880. + * Version 0.9 Copyright (c) Ming-Ching Tiew mctiew@yahoo.com
  881. + * Program adapted from misc.c for 2.6.20.1 kernel
  882. + * Please refer to misc.c for authorship and copyright.
  883. + * Date: 25 March 2007
  884. + * Source released under GPL
  885. + */
  886. +
  887. +#undef CONFIG_PARAVIRT
  888. +#include <linux/linkage.h>
  889. +#include <linux/vmalloc.h>
  890. +#include <linux/screen_info.h>
  891. +#include <asm/io.h>
  892. +#include <asm/page.h>
  893. +#include <asm/boot.h>
  894. +
  895. +/* WARNING!!
  896. + * This code is compiled with -fPIC and it is relocated dynamically
  897. + * at run time, but no relocation processing is performed.
  898. + * This means that it is not safe to place pointers in static structures.
  899. + */
  900. +
  901. +#define OF(args) args
  902. +#define STATIC static
  903. +
  904. +#undef memset
  905. +#undef memcpy
  906. +
  907. +typedef unsigned char uch;
  908. +typedef unsigned short ush;
  909. +typedef unsigned long ulg;
  910. +
  911. +#define WSIZE 0x80000000 /* Window size must be at least 32k,
  912. + * and a power of two
  913. + * We don't actually have a window just
  914. + * a huge output buffer so I report
  915. + * a 2G windows size, as that should
  916. + * always be larger than our output buffer.
  917. + */
  918. +
  919. +static uch *inbuf; /* input buffer */
  920. +static uch *window; /* Sliding window buffer, (and final output buffer) */
  921. +
  922. +static unsigned insize; /* valid bytes in inbuf */
  923. +static unsigned inptr; /* index of next byte to be processed in inbuf */
  924. +
  925. +/* gzip flag byte */
  926. +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
  927. +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  928. +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
  929. +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
  930. +#define COMMENT 0x10 /* bit 4 set: file comment present */
  931. +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
  932. +#define RESERVED 0xC0 /* bit 6,7: reserved */
  933. +
  934. +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
  935. +
  936. +/* Diagnostic functions */
  937. +#ifdef DEBUG
  938. +# define Assert(cond,msg) {if(!(cond)) error(msg);}
  939. +# define Trace(x) fprintf x
  940. +# define Tracev(x) {if (verbose) fprintf x ;}
  941. +# define Tracevv(x) {if (verbose>1) fprintf x ;}
  942. +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
  943. +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
  944. +#else
  945. +# define Assert(cond,msg)
  946. +# define Trace(x)
  947. +# define Tracev(x)
  948. +# define Tracevv(x)
  949. +# define Tracec(c,x)
  950. +# define Tracecv(c,x)
  951. +#endif
  952. +
  953. +static int fill_inbuf(void);
  954. +static void error(char *m);
  955. +
  956. +/*
  957. + * This is set up by the setup-routine at boot-time
  958. + */
  959. +static unsigned char *real_mode; /* Pointer to real-mode data */
  960. +
  961. +#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
  962. +#ifndef STANDARD_MEMORY_BIOS_CALL
  963. +#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
  964. +#endif
  965. +#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
  966. +
  967. +extern unsigned char input_data[];
  968. +extern int input_len;
  969. +
  970. +static long bytes_out = 0;
  971. +
  972. +static void *memcpy(void *dest, const void *src, unsigned n);
  973. +
  974. +static void putstr(const char *);
  975. +
  976. +static unsigned long free_mem_ptr;
  977. +static unsigned long free_mem_end_ptr;
  978. +
  979. +#define HEAP_SIZE 0x3000
  980. +
  981. +static char *vidmem = (char *)0xb8000;
  982. +static int vidport;
  983. +static int lines, cols;
  984. +
  985. +#ifdef CONFIG_X86_NUMAQ
  986. +void *xquad_portio;
  987. +#endif
  988. +
  989. +static void scroll(void)
  990. +{
  991. + int i;
  992. +
  993. + memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
  994. + for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
  995. + vidmem[i] = ' ';
  996. +}
  997. +
  998. +static void putstr(const char *s)
  999. +{
  1000. + int x,y,pos;
  1001. + char c;
  1002. +
  1003. + x = RM_SCREEN_INFO.orig_x;
  1004. + y = RM_SCREEN_INFO.orig_y;
  1005. +
  1006. + while ( ( c = *s++ ) != '\0' ) {
  1007. + if ( c == '\n' ) {
  1008. + x = 0;
  1009. + if ( ++y >= lines ) {
  1010. + scroll();
  1011. + y--;
  1012. + }
  1013. + } else {
  1014. + vidmem [ ( x + cols * y ) * 2 ] = c;
  1015. + if ( ++x >= cols ) {
  1016. + x = 0;
  1017. + if ( ++y >= lines ) {
  1018. + scroll();
  1019. + y--;
  1020. + }
  1021. + }
  1022. + }
  1023. + }
  1024. +
  1025. + RM_SCREEN_INFO.orig_x = x;
  1026. + RM_SCREEN_INFO.orig_y = y;
  1027. +
  1028. + pos = (x + cols * y) * 2; /* Update cursor position */
  1029. + outb_p(14, vidport);
  1030. + outb_p(0xff & (pos >> 9), vidport+1);
  1031. + outb_p(15, vidport);
  1032. + outb_p(0xff & (pos >> 1), vidport+1);
  1033. +}
  1034. +
  1035. +static void* memcpy(void* dest, const void* src, unsigned n)
  1036. +{
  1037. + int i;
  1038. + char *d = (char *)dest, *s = (char *)src;
  1039. +
  1040. + for (i=0;i<n;i++) d[i] = s[i];
  1041. + return dest;
  1042. +}
  1043. +
  1044. +/* ===========================================================================
  1045. + * Fill the input buffer. This is called only when the buffer is empty
  1046. + * and at least one byte is really needed.
  1047. + */
  1048. +static int fill_inbuf(void)
  1049. +{
  1050. + error("ran out of input data");
  1051. + return 0;
  1052. +}
  1053. +
  1054. +/* ===========================================================================
  1055. + */
  1056. +static void error(char *x)
  1057. +{
  1058. + putstr("\n\n");
  1059. + putstr(x);
  1060. + putstr("\n\n -- System halted");
  1061. +
  1062. + while(1); /* Halt */
  1063. +}
  1064. +
  1065. +#define _LZMA_IN_CB
  1066. +#include "LzmaDecode.h"
  1067. +#include "LzmaDecode.c"
  1068. +
  1069. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
  1070. +
  1071. +/*
  1072. + * Do the lzma decompression
  1073. + */
  1074. +static int lzma_unzip(uch* output)
  1075. +{
  1076. +
  1077. + unsigned int i;
  1078. + CLzmaDecoderState state;
  1079. + unsigned int uncompressedSize = 0;
  1080. + unsigned char* p;
  1081. +
  1082. + ILzmaInCallback callback;
  1083. + callback.Read = read_byte;
  1084. +
  1085. + // lzma args
  1086. + i = get_byte();
  1087. + state.Properties.lc = i % 9, i = i / 9;
  1088. + state.Properties.lp = i % 5, state.Properties.pb = i / 5;
  1089. +
  1090. + // skip dictionary size
  1091. + for (i = 0; i < 4; i++)
  1092. + get_byte();
  1093. + // get uncompressed size
  1094. + p= (char*)&uncompressedSize;
  1095. + for (i = 0; i < 4; i++)
  1096. + *p++ = get_byte();
  1097. +
  1098. + // skip high order bytes
  1099. + for (i = 0; i < 4; i++)
  1100. + get_byte();
  1101. +
  1102. + // Just point it beyond
  1103. + state.Probs = (CProb*) ( free_mem_ptr );
  1104. + // decompress kernel
  1105. + if (LzmaDecode( &state, &callback,
  1106. + (unsigned char*)output, uncompressedSize, &i) == LZMA_RESULT_OK)
  1107. + {
  1108. + if ( i != uncompressedSize )
  1109. + error( "kernel corrupted!\n");
  1110. + bytes_out = i;
  1111. + return 0;
  1112. + }
  1113. + return 1;
  1114. +}
  1115. +
  1116. +
  1117. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
  1118. +{
  1119. + static unsigned int i = 0;
  1120. + static unsigned char val;
  1121. + *bufferSize = 1;
  1122. + val = get_byte();
  1123. + *buffer = &val;
  1124. + return LZMA_RESULT_OK;
  1125. +}
  1126. +
  1127. +asmlinkage void decompress_kernel(void *rmode, unsigned long end,
  1128. + uch *input_data, unsigned long input_len, uch *output)
  1129. +{
  1130. + real_mode = rmode;
  1131. +
  1132. + if (RM_SCREEN_INFO.orig_video_mode == 7) {
  1133. + vidmem = (char *) 0xb0000;
  1134. + vidport = 0x3b4;
  1135. + } else {
  1136. + vidmem = (char *) 0xb8000;
  1137. + vidport = 0x3d4;
  1138. + }
  1139. +
  1140. + lines = RM_SCREEN_INFO.orig_video_lines;
  1141. + cols = RM_SCREEN_INFO.orig_video_cols;
  1142. +
  1143. + window = output; /* Output buffer (Normally at 1M) */
  1144. + free_mem_ptr = end; /* Heap */
  1145. + free_mem_end_ptr = end + HEAP_SIZE;
  1146. + inbuf = input_data; /* Input buffer */
  1147. + insize = input_len;
  1148. + inptr = 0;
  1149. +
  1150. + if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
  1151. + error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
  1152. + if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
  1153. + error("Destination address too large");
  1154. +#ifndef CONFIG_RELOCATABLE
  1155. + if ((u32)output != LOAD_PHYSICAL_ADDR)
  1156. + error("Wrong destination address");
  1157. +#endif
  1158. + if( lzma_unzip(output) != 0 )
  1159. + {
  1160. + error("inflate error\n");
  1161. + }
  1162. + putstr("Ok, booting the kernel.\n");
  1163. +
  1164. + return;
  1165. +}
  1166. diff --git a/arch/i386/boot/compressed/vmlinux.scr b/arch/i386/boot/compressed/vmlinux.scr
  1167. index 707a88f..9d67263 100644
  1168. --- a/arch/i386/boot/compressed/vmlinux.scr
  1169. +++ b/arch/i386/boot/compressed/vmlinux.scr
  1170. @@ -3,8 +3,8 @@ SECTIONS
  1171. .data.compressed : {
  1172. input_len = .;
  1173. LONG(input_data_end - input_data) input_data = .;
  1174. + output_len = . + 5;
  1175. *(.data)
  1176. - output_len = . - 4;
  1177. input_data_end = .;
  1178. }
  1179. }
  1180. diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
  1181. index 17ee97f..64b7bda 100644
  1182. --- a/drivers/block/Kconfig
  1183. +++ b/drivers/block/Kconfig
  1184. @@ -406,6 +406,47 @@ config BLK_DEV_RAM_BLOCKSIZE
  1185. setups function - apparently needed by the rd_load_image routine
  1186. that supposes the filesystem in the image uses a 1024 blocksize.
  1187. +config LZMA_INITRD
  1188. + boolean "Allow LZMA compression on initrd"
  1189. + depends on BLK_DEV_INITRD=y
  1190. + default "y"
  1191. + help
  1192. + Use lzma compression on initrd, example 'lzma e initrd initrd.7z -d16'.
  1193. + If you have sufficient memory, you could compress using bigger dictionary size,
  1194. + 'lzma e initrd initrd.7z'.
  1195. +
  1196. +config LZMA_INITRD_KMALLOC_ONLY
  1197. + boolean "Use only kmalloc, do not use vmalloc on lzma initrd"
  1198. + depends on LZMA_INITRD=y
  1199. + default "n"
  1200. + help
  1201. + Set to y if you do not want to use vmalloc, ie use only kmalloc.
  1202. +
  1203. +config LZMA_INITRAM_FS
  1204. + boolean "Allow LZMA compression on initramfs"
  1205. + depends on BLK_DEV_RAM=y
  1206. + default "y"
  1207. + help
  1208. + Use lzma compression on initramfs, example 'lzma e initramfs.cpio initramfs.cpio.lzma'.
  1209. +
  1210. +config LZMA_INITRAM_FS_SMALLMEM
  1211. + boolean "Use lzma compression with small dictonary size."
  1212. + depends on LZMA_INITRAM_FS=y
  1213. + default "y"
  1214. + help
  1215. + Use lzma compression on initramfs with small dictionary size, example
  1216. + 'lzma e initramfs.cpio initramfs.cpio.lzma -d16'.
  1217. + Affects only the initramfs.cpio in the ~usr directory, which is compiled into
  1218. + the kernel. If you prepared initramfs.cpio for use with bootloader, you would
  1219. + need to specify the commandline options (-d16) yourself.
  1220. +
  1221. +config LZMA_INITRAM_FS_KMALLOC_ONLY
  1222. + boolean "Use only kmalloc, do not use vmalloc on lzma initramfs"
  1223. + depends on LZMA_INITRAM_FS=y
  1224. + default "n"
  1225. + help
  1226. + Set to y if you do not want to use vmalloc, ie use only kmalloc.
  1227. +
  1228. config CDROM_PKTCDVD
  1229. tristate "Packet writing on CD/DVD media"
  1230. depends on !UML
  1231. diff --git a/fs/Kconfig b/fs/Kconfig
  1232. index 3c4886b..bdcc6fb 100644
  1233. --- a/fs/Kconfig
  1234. +++ b/fs/Kconfig
  1235. @@ -1371,6 +1371,71 @@ config CRAMFS
  1236. If unsure, say N.
  1237. +config SQUASHFS
  1238. + tristate "SquashFS 3.2 - Squashed file system support"
  1239. + select ZLIB_INFLATE
  1240. + help
  1241. + Saying Y here includes support for SquashFS 3.2 (a Compressed Read-Only File
  1242. + System). Squashfs is a highly compressed read-only filesystem for Linux.
  1243. + It uses zlib compression to compress both files, inodes and directories.
  1244. + Inodes in the system are very small and all blocks are packed to minimise
  1245. + data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
  1246. + SquashFS 3.1 supports 64 bit filesystems and files (larger than 4GB), full
  1247. + uid/gid information, hard links and timestamps.
  1248. +
  1249. + Squashfs is intended for general read-only filesystem use, for archival
  1250. + use (i.e. in cases where a .tar.gz file may be used), and in embedded
  1251. + systems where low overhead is needed. Further information and filesystem tools
  1252. + are available from http://squashfs.sourceforge.net.
  1253. +
  1254. + If you want to compile this as a module ( = code which can be
  1255. + inserted in and removed from the running kernel whenever you want),
  1256. + say M here and read <file:Documentation/modules.txt>. The module
  1257. + will be called squashfs. Note that the root file system (the one
  1258. + containing the directory /) cannot be compiled as a module.
  1259. +
  1260. + If unsure, say N.
  1261. +
  1262. +config SQUASHFS_EMBEDDED
  1263. +
  1264. + bool "Additional options for memory-constrained systems"
  1265. + depends on SQUASHFS
  1266. + default n
  1267. + help
  1268. + Saying Y here allows you to specify cache sizes and how Squashfs
  1269. + allocates memory. This is only intended for memory constrained
  1270. + systems.
  1271. +
  1272. + If unsure, say N.
  1273. +
  1274. +config SQUASHFS_FRAGMENT_CACHE_SIZE
  1275. + int "Number of fragments cached" if SQUASHFS_EMBEDDED
  1276. + depends on SQUASHFS
  1277. + default "3"
  1278. + help
  1279. + By default SquashFS caches the last 3 fragments read from
  1280. + the filesystem. Increasing this amount may mean SquashFS
  1281. + has to re-read fragments less often from disk, at the expense
  1282. + of extra system memory. Decreasing this amount will mean
  1283. + SquashFS uses less memory at the expense of extra reads from disk.
  1284. +
  1285. + Note there must be at least one cached fragment. Anything
  1286. + much more than three will probably not make much difference.
  1287. +
  1288. +config SQUASHFS_VMALLOC
  1289. + bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
  1290. + depends on SQUASHFS
  1291. + default n
  1292. + help
  1293. + By default SquashFS uses kmalloc to obtain fragment cache memory.
  1294. + Kmalloc memory is the standard kernel allocator, but it can fail
  1295. + on memory constrained systems. Because of the way Vmalloc works,
  1296. + Vmalloc can succeed when kmalloc fails. Specifying this option
  1297. + will make SquashFS always use Vmalloc to allocate the
  1298. + fragment cache memory.
  1299. +
  1300. + If unsure, say N.
  1301. +
  1302. config VXFS_FS
  1303. tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
  1304. depends on BLOCK
  1305. @@ -2057,3 +2122,4 @@ source "fs/dlm/Kconfig"
  1306. endmenu
  1307. +source "fs/aufs/Kconfig"
  1308. diff --git a/fs/Makefile b/fs/Makefile
  1309. index 9edf411..557766f 100644
  1310. --- a/fs/Makefile
  1311. +++ b/fs/Makefile
  1312. @@ -68,6 +68,7 @@ obj-$(CONFIG_JBD) += jbd/
  1313. obj-$(CONFIG_JBD2) += jbd2/
  1314. obj-$(CONFIG_EXT2_FS) += ext2/
  1315. obj-$(CONFIG_CRAMFS) += cramfs/
  1316. +obj-$(CONFIG_SQUASHFS) += squashfs/
  1317. obj-$(CONFIG_RAMFS) += ramfs/
  1318. obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
  1319. obj-$(CONFIG_CODA_FS) += coda/
  1320. @@ -114,3 +115,4 @@ obj-$(CONFIG_HPPFS) += hppfs/
  1321. obj-$(CONFIG_DEBUG_FS) += debugfs/
  1322. obj-$(CONFIG_OCFS2_FS) += ocfs2/
  1323. obj-$(CONFIG_GFS2_FS) += gfs2/
  1324. +obj-$(CONFIG_AUFS) += aufs/
  1325. diff --git a/fs/aufs/Kconfig b/fs/aufs/Kconfig
  1326. new file mode 100644
  1327. index 0000000..3a2121c
  1328. --- /dev/null
  1329. +++ b/fs/aufs/Kconfig
  1330. @@ -0,0 +1,73 @@
  1331. +config AUFS
  1332. + tristate "Another unionfs"
  1333. + help
  1334. + Aufs is a stackable unification filesystem such as Unionfs,
  1335. + which unifies several directories and provides a merged single
  1336. + directory.
  1337. + In the early days, aufs was entirely re-designed and
  1338. + re-implemented Unionfs Version 1.x series. After many original
  1339. + ideas, approaches and improvements, it becomes totally
  1340. + different from Unionfs while keeping the basic features.
  1341. + See Unionfs for the basic features.
  1342. +
  1343. +if AUFS
  1344. +comment "These options are generated automatically for "#UTS_RELEASE
  1345. +
  1346. +config AUFS_FAKE_DM
  1347. + bool "Use simplified (fake) nameidata"
  1348. + depends on AUFS
  1349. + default y
  1350. + help
  1351. + Faking nameidata (VFS internal data), you can get better performance
  1352. + in some cases.
  1353. +
  1354. +choice
  1355. + prompt "Maximum number of branches"
  1356. + depends on AUFS
  1357. + default AUFS_BRANCH_MAX_127
  1358. + help
  1359. + 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.
  1360. +config AUFS_BRANCH_MAX_127
  1361. + bool "127"
  1362. + help
  1363. + 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.
  1364. +config AUFS_BRANCH_MAX_511
  1365. + bool "511"
  1366. + help
  1367. + 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.
  1368. +config AUFS_BRANCH_MAX_1023
  1369. + bool "1023"
  1370. + help
  1371. + 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.
  1372. +
  1373. +config AUFS_BRANCH_MAX_32767
  1374. + bool "32767"
  1375. + help
  1376. + 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.
  1377. +endchoice
  1378. +config AUFS_DEBUG
  1379. + bool "Debug aufs"
  1380. + depends on AUFS
  1381. + default y
  1382. + help
  1383. + Enable this to compile aufs internal debug code.
  1384. + The performance will be damaged.
  1385. +
  1386. +config AUFS_COMPAT
  1387. + bool "Compatibility with Unionfs (obsolete)"
  1388. + depends on AUFS
  1389. + default n
  1390. + help
  1391. + This makes aufs compatible with unionfs-style mount options and some
  1392. + behaviours.
  1393. + The dirs= mount option and =nfsro branch permission flag are always
  1394. + interpreted as br: mount option and =ro flag respectively. The
  1395. + 'debug', 'delete' and 'imap' mount options are ignored.
  1396. + If you disable this option, you will get,
  1397. + - aufs issues a warning about the ignored mount options
  1398. + - the default branch permission flag is set. RW for the first branch,
  1399. + and RO for the rests.
  1400. + - the name of a internal file which represents the directory is
  1401. + 'opaque', becomes '.wh..wh..opq'
  1402. + - the 'diropq=w' mount option is set by default
  1403. +endif
  1404. diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile
  1405. new file mode 100755
  1406. index 0000000..0ee3cd0
  1407. --- /dev/null
  1408. +++ b/fs/aufs/Makefile
  1409. @@ -0,0 +1,18 @@
  1410. +# AUFS Makefile for the Linux 2.6.16 and later
  1411. +# $Id: Makefile,v 1.29 2007/04/23 00:59:50 sfjro Exp $
  1412. +
  1413. +obj-$(CONFIG_AUFS) += aufs.o
  1414. +aufs-y := module.o super.o sbinfo.o xino.o \
  1415. + branch.o cpup.o whout.o plink.o wkq.o dcsub.o vfsub.o \
  1416. + opts.o \
  1417. + dentry.o dinfo.o \
  1418. + file.o f_op.o finfo.o \
  1419. + dir.o vdir.o \
  1420. + inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o iinfo.o \
  1421. + misc.o
  1422. +#xattr.o
  1423. +aufs-$(CONFIG_AUFS_SYSAUFS) += sysaufs.o
  1424. +aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
  1425. +aufs-$(CONFIG_AUFS_EXPORT) += export.o
  1426. +#aufs-$(CONFIG_DEBUGFS) += dbgfs.o
  1427. +aufs-$(CONFIG_AUFS_DEBUG) += debug.o
  1428. diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h
  1429. new file mode 100755
  1430. index 0000000..79b3b87
  1431. --- /dev/null
  1432. +++ b/fs/aufs/aufs.h
  1433. @@ -0,0 +1,64 @@
  1434. +/*
  1435. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  1436. + *
  1437. + * This program, aufs is free software; you can redistribute it and/or modify
  1438. + * it under the terms of the GNU General Public License as published by
  1439. + * the Free Software Foundation; either version 2 of the License, or
  1440. + * (at your option) any later version.
  1441. + *
  1442. + * This program is distributed in the hope that it will be useful,
  1443. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1444. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1445. + * GNU General Public License for more details.
  1446. + *
  1447. + * You should have received a copy of the GNU General Public License
  1448. + * along with this program; if not, write to the Free Software
  1449. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  1450. + */
  1451. +
  1452. +/* $Id: aufs.h,v 1.24 2007/05/14 03:41:51 sfjro Exp $ */
  1453. +
  1454. +#ifndef __AUFS_H__
  1455. +#define __AUFS_H__
  1456. +
  1457. +#ifdef __KERNEL__
  1458. +
  1459. +#include <linux/version.h>
  1460. +
  1461. +/* limited support before 2.6.16, curretly 2.6.15 only. */
  1462. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
  1463. +#define atomic_long_t atomic_t
  1464. +#define atomic_long_set atomic_set
  1465. +#define timespec_to_ns(ts) ({(long long)(ts)->tv_sec;})
  1466. +#define D_CHILD d_child
  1467. +#else
  1468. +#define D_CHILD d_u.d_child
  1469. +#endif
  1470. +
  1471. +/* ---------------------------------------------------------------------- */
  1472. +
  1473. +#include "debug.h"
  1474. +
  1475. +#include "branch.h"
  1476. +#include "cpup.h"
  1477. +#include "dcsub.h"
  1478. +#include "dentry.h"
  1479. +#include "dir.h"
  1480. +#include "file.h"
  1481. +#include "inode.h"
  1482. +#include "misc.h"
  1483. +#include "module.h"
  1484. +#include "opts.h"
  1485. +#include "super.h"
  1486. +#include "sysaufs.h"
  1487. +#include "vfsub.h"
  1488. +#include "whout.h"
  1489. +#include "wkq.h"
  1490. +//#include "xattr.h"
  1491. +
  1492. +#if defined(CONFIG_AUFS_MODULE) && !defined(CONFIG_AUFS_KSIZE_PATCH)
  1493. +#define ksize(p) (-1U)
  1494. +#endif
  1495. +
  1496. +#endif /* __KERNEL__ */
  1497. +#endif /* __AUFS_H__ */
  1498. diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c
  1499. new file mode 100755
  1500. index 0000000..f1ce008
  1501. --- /dev/null
  1502. +++ b/fs/aufs/branch.c
  1503. @@ -0,0 +1,818 @@
  1504. +/*
  1505. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  1506. + *
  1507. + * This program, aufs is free software; you can redistribute it and/or modify
  1508. + * it under the terms of the GNU General Public License as published by
  1509. + * the Free Software Foundation; either version 2 of the License, or
  1510. + * (at your option) any later version.
  1511. + *
  1512. + * This program is distributed in the hope that it will be useful,
  1513. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1514. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1515. + * GNU General Public License for more details.
  1516. + *
  1517. + * You should have received a copy of the GNU General Public License
  1518. + * along with this program; if not, write to the Free Software
  1519. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  1520. + */
  1521. +
  1522. +/* $Id: branch.c,v 1.49 2007/05/14 03:38:23 sfjro Exp $ */
  1523. +
  1524. +//#include <linux/fs.h>
  1525. +//#include <linux/namei.h>
  1526. +#include "aufs.h"
  1527. +
  1528. +static void free_branch(struct aufs_branch *br)
  1529. +{
  1530. + TraceEnter();
  1531. +
  1532. + if (br->br_xino)
  1533. + fput(br->br_xino);
  1534. + dput(br->br_wh);
  1535. + dput(br->br_plink);
  1536. + mntput(br->br_mnt);
  1537. + DEBUG_ON(br_count(br) || atomic_read(&br->br_wh_running));
  1538. + kfree(br);
  1539. +}
  1540. +
  1541. +/*
  1542. + * frees all branches
  1543. + */
  1544. +void free_branches(struct aufs_sbinfo *sbinfo)
  1545. +{
  1546. + aufs_bindex_t bmax;
  1547. + struct aufs_branch **br;
  1548. +
  1549. + TraceEnter();
  1550. + bmax = sbinfo->si_bend + 1;
  1551. + br = sbinfo->si_branch;
  1552. + while (bmax--)
  1553. + free_branch(*br++);
  1554. +}
  1555. +
  1556. +/*
  1557. + * find the index of a branch which is specified by @br_id.
  1558. + */
  1559. +int find_brindex(struct super_block *sb, aufs_bindex_t br_id)
  1560. +{
  1561. + aufs_bindex_t bindex, bend;
  1562. +
  1563. + TraceEnter();
  1564. +
  1565. + bend = sbend(sb);
  1566. + for (bindex = 0; bindex <= bend; bindex++)
  1567. + if (sbr_id(sb, bindex) == br_id)
  1568. + return bindex;
  1569. + return -1;
  1570. +}
  1571. +
  1572. +/*
  1573. + * test if the @br is readonly or not.
  1574. + */
  1575. +int br_rdonly(struct aufs_branch *br)
  1576. +{
  1577. + return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
  1578. + || !br_writable(br->br_perm))
  1579. + ? -EROFS : 0;
  1580. +}
  1581. +
  1582. +/*
  1583. + * returns writable branch index, otherwise an error.
  1584. + * todo: customizable writable-branch-policy
  1585. + */
  1586. +static int find_rw_parent(struct dentry *dentry, aufs_bindex_t bend)
  1587. +{
  1588. + int err;
  1589. + aufs_bindex_t bindex, candidate;
  1590. + struct super_block *sb;
  1591. + struct dentry *parent, *hidden_parent;
  1592. +
  1593. + err = bend;
  1594. + sb = dentry->d_sb;
  1595. + parent = dget_parent(dentry);
  1596. +#if 1 // branch policy
  1597. + hidden_parent = au_h_dptr_i(parent, bend);
  1598. + if (hidden_parent && !br_rdonly(stobr(sb, bend)))
  1599. + goto out; /* success */
  1600. +#endif
  1601. +
  1602. + candidate = -1;
  1603. + for (bindex = dbstart(parent); bindex <= bend; bindex++) {
  1604. + hidden_parent = au_h_dptr_i(parent, bindex);
  1605. + if (hidden_parent && !br_rdonly(stobr(sb, bindex))) {
  1606. +#if 0 // branch policy
  1607. + if (candidate == -1)
  1608. + candidate = bindex;
  1609. + if (!au_test_perm(hidden_parent->d_inode, MAY_WRITE))
  1610. + return bindex;
  1611. +#endif
  1612. + err = bindex;
  1613. + goto out; /* success */
  1614. + }
  1615. + }
  1616. +#if 0 // branch policy
  1617. + err = candidate;
  1618. + if (candidate != -1)
  1619. + goto out; /* success */
  1620. +#endif
  1621. + err = -EROFS;
  1622. +
  1623. + out:
  1624. + dput(parent);
  1625. + return err;
  1626. +}
  1627. +
  1628. +int find_rw_br(struct super_block *sb, aufs_bindex_t bend)
  1629. +{
  1630. + aufs_bindex_t bindex;
  1631. +
  1632. + for (bindex = bend; bindex >= 0; bindex--)
  1633. + if (!br_rdonly(stobr(sb, bindex)))
  1634. + return bindex;
  1635. + return -EROFS;
  1636. +}
  1637. +
  1638. +int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend)
  1639. +{
  1640. + int err;
  1641. +
  1642. + err = find_rw_parent(dentry, bend);
  1643. + if (err >= 0)
  1644. + return err;
  1645. + return find_rw_br(dentry->d_sb, bend);
  1646. +}
  1647. +
  1648. +/* ---------------------------------------------------------------------- */
  1649. +
  1650. +/*
  1651. + * test if two hidden_dentries have overlapping branches.
  1652. + */
  1653. +//todo: try is_subdir()
  1654. +static int do_is_overlap(struct super_block *sb, struct dentry *hidden_d1,
  1655. + struct dentry *hidden_d2)
  1656. +{
  1657. + struct dentry *d;
  1658. +
  1659. + d = hidden_d1;
  1660. + do {
  1661. + if (unlikely(d == hidden_d2))
  1662. + return 1;
  1663. + d = d->d_parent; // dget_parent()
  1664. + } while (!IS_ROOT(d));
  1665. +
  1666. + return (d == hidden_d2);
  1667. +}
  1668. +
  1669. +#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
  1670. +#include <linux/loop.h>
  1671. +static int is_overlap_loopback(struct super_block *sb, struct dentry *hidden_d1,
  1672. + struct dentry *hidden_d2)
  1673. +{
  1674. + struct inode *hidden_inode;
  1675. + struct loop_device *l;
  1676. +
  1677. + hidden_inode = hidden_d1->d_inode;
  1678. + if (MAJOR(hidden_inode->i_sb->s_dev) != LOOP_MAJOR)
  1679. + return 0;
  1680. +
  1681. + l = hidden_inode->i_sb->s_bdev->bd_disk->private_data;
  1682. + hidden_d1 = l->lo_backing_file->f_dentry;
  1683. + if (unlikely(hidden_d1->d_sb == sb))
  1684. + return 1;
  1685. + return do_is_overlap(sb, hidden_d1, hidden_d2);
  1686. +}
  1687. +#else
  1688. +#define is_overlap_loopback(sb, hidden_d1, hidden_d2) 0
  1689. +#endif
  1690. +
  1691. +static int is_overlap(struct super_block *sb, struct dentry *hidden_d1,
  1692. + struct dentry *hidden_d2)
  1693. +{
  1694. + LKTRTrace("d1 %.*s, d2 %.*s\n", DLNPair(hidden_d1), DLNPair(hidden_d2));
  1695. + if (unlikely(hidden_d1 == hidden_d2))
  1696. + return 1;
  1697. + return do_is_overlap(sb, hidden_d1, hidden_d2)
  1698. + || do_is_overlap(sb, hidden_d2, hidden_d1)
  1699. + || is_overlap_loopback(sb, hidden_d1, hidden_d2)
  1700. + || is_overlap_loopback(sb, hidden_d2, hidden_d1);
  1701. +}
  1702. +
  1703. +/* ---------------------------------------------------------------------- */
  1704. +
  1705. +static int init_br_wh(struct super_block *sb, aufs_bindex_t bindex,
  1706. + struct aufs_branch *br, int new_perm,
  1707. + struct dentry *h_root, struct vfsmount *h_mnt)
  1708. +{
  1709. + int err, old_perm;
  1710. + struct inode *dir = sb->s_root->d_inode,
  1711. + *h_dir = h_root->d_inode;
  1712. + const int new = (bindex < 0);
  1713. +
  1714. + LKTRTrace("b%d, new_perm %d\n", bindex, new_perm);
  1715. +
  1716. + if (new)
  1717. + hi_lock_parent(h_dir);
  1718. + else
  1719. + hdir_lock(h_dir, dir, bindex);
  1720. +
  1721. + br_wh_write_lock(br);
  1722. + old_perm = br->br_perm;
  1723. + br->br_perm = new_perm;
  1724. + err = init_wh(h_root, br, au_do_nfsmnt(h_mnt), sb);
  1725. + br->br_perm = old_perm;
  1726. + br_wh_write_unlock(br);
  1727. +
  1728. + if (new)
  1729. + i_unlock(h_dir);
  1730. + else
  1731. + hdir_unlock(h_dir, dir, bindex);
  1732. +
  1733. + TraceErr(err);
  1734. + return err;
  1735. +}
  1736. +
  1737. +/* ---------------------------------------------------------------------- */
  1738. +
  1739. +/*
  1740. + * returns a newly allocated branch. @new_nbranch is a number of branches
  1741. + * after adding a branch.
  1742. + */
  1743. +static struct aufs_branch *alloc_addbr(struct super_block *sb, int new_nbranch)
  1744. +{
  1745. + struct aufs_branch **branchp, *add_branch;
  1746. + int sz;
  1747. + void *p;
  1748. + struct dentry *root;
  1749. + struct inode *inode;
  1750. + struct aufs_hinode *hinodep;
  1751. + struct aufs_hdentry *hdentryp;
  1752. +
  1753. + LKTRTrace("new_nbranch %d\n", new_nbranch);
  1754. + SiMustWriteLock(sb);
  1755. + root = sb->s_root;
  1756. + DiMustWriteLock(root);
  1757. + inode = root->d_inode;
  1758. + IiMustWriteLock(inode);
  1759. +
  1760. + add_branch = kmalloc(sizeof(*add_branch), GFP_KERNEL);
  1761. + //if (LktrCond) {kfree(add_branch); add_branch = NULL;}
  1762. + if (unlikely(!add_branch))
  1763. + goto out;
  1764. +
  1765. + sz = sizeof(*branchp) * (new_nbranch - 1);
  1766. + if (unlikely(!sz))
  1767. + sz = sizeof(*branchp);
  1768. + p = stosi(sb)->si_branch;
  1769. + branchp = au_kzrealloc(p, sz, sizeof(*branchp) * new_nbranch,
  1770. + GFP_KERNEL);
  1771. + //if (LktrCond) branchp = NULL;
  1772. + if (unlikely(!branchp))
  1773. + goto out;
  1774. + stosi(sb)->si_branch = branchp;
  1775. +
  1776. + sz = sizeof(*hdentryp) * (new_nbranch - 1);
  1777. + if (unlikely(!sz))
  1778. + sz = sizeof(*hdentryp);
  1779. + p = dtodi(root)->di_hdentry;
  1780. + hdentryp = au_kzrealloc(p, sz, sizeof(*hdentryp) * new_nbranch,
  1781. + GFP_KERNEL);
  1782. + //if (LktrCond) hdentryp = NULL;
  1783. + if (unlikely(!hdentryp))
  1784. + goto out;
  1785. + dtodi(root)->di_hdentry = hdentryp;
  1786. +
  1787. + sz = sizeof(*hinodep) * (new_nbranch - 1);
  1788. + if (unlikely(!sz))
  1789. + sz = sizeof(*hinodep);
  1790. + p = itoii(inode)->ii_hinode;
  1791. + hinodep = au_kzrealloc(p, sz, sizeof(*hinodep) * new_nbranch,
  1792. + GFP_KERNEL);
  1793. + //if (LktrCond) hinodep = NULL; // unavailable test
  1794. + if (unlikely(!hinodep))
  1795. + goto out;
  1796. + itoii(inode)->ii_hinode = hinodep;
  1797. + return add_branch; /* success */
  1798. +
  1799. + out:
  1800. + kfree(add_branch);
  1801. + TraceErr(-ENOMEM);
  1802. + return ERR_PTR(-ENOMEM);
  1803. +}
  1804. +
  1805. +/*
  1806. + * test if the branch permission is legal or not.
  1807. + */
  1808. +static int test_br(struct super_block *sb, struct inode *inode, int brperm,
  1809. + char *path)
  1810. +{
  1811. + int err;
  1812. +
  1813. + err = 0;
  1814. + if (unlikely(br_writable(brperm) && IS_RDONLY(inode))) {
  1815. + Err("write permission for readonly fs or inode, %s\n", path);
  1816. + err = -EINVAL;
  1817. + }
  1818. +
  1819. + TraceErr(err);
  1820. + return err;
  1821. +}
  1822. +
  1823. +/*
  1824. + * retunrs,,,
  1825. + * 0: success, the caller will add it
  1826. + * plus: success, it is already unified, the caller should ignore it
  1827. + * minus: error
  1828. + */
  1829. +static int test_add(struct super_block *sb, struct opt_add *add, int remount)
  1830. +{
  1831. + int err;
  1832. + struct dentry *root;
  1833. + struct inode *inode, *hidden_inode;
  1834. + aufs_bindex_t bend, bindex;
  1835. +
  1836. + LKTRTrace("%s, remo%d\n", add->path, remount);
  1837. +
  1838. + root = sb->s_root;
  1839. + if (unlikely(au_find_dbindex(root, add->nd.dentry) != -1)) {
  1840. + err = 1;
  1841. + if (!remount) {
  1842. + err = -EINVAL;
  1843. + Err("%s duplicated\n", add->path);
  1844. + }
  1845. + goto out;
  1846. + }
  1847. +
  1848. + err = -ENOSPC; //-E2BIG;
  1849. + bend = sbend(sb);
  1850. + //if (LktrCond) bend = AUFS_BRANCH_MAX;
  1851. + if (unlikely(AUFS_BRANCH_MAX <= add->bindex
  1852. + || AUFS_BRANCH_MAX - 1 <= bend)) {
  1853. + Err("number of branches exceeded %s\n", add->path);
  1854. + goto out;
  1855. + }
  1856. +
  1857. + err = -EDOM;
  1858. + if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
  1859. + Err("bad index %d\n", add->bindex);
  1860. + goto out;
  1861. + }
  1862. +
  1863. + inode = add->nd.dentry->d_inode;
  1864. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  1865. + err = -ENOENT;
  1866. + if (unlikely(!inode->i_nlink)) {
  1867. + Err("no existence %s\n", add->path);
  1868. + goto out;
  1869. + }
  1870. +
  1871. + err = -EINVAL;
  1872. + if (unlikely(inode->i_sb == sb)) {
  1873. + Err("%s must be outside\n", add->path);
  1874. + goto out;
  1875. + }
  1876. +
  1877. +#if 1 //ndef CONFIG_AUFS_ROBR
  1878. + if (unlikely(au_is_aufs(inode->i_sb)
  1879. + || !strcmp(au_sbtype(inode->i_sb), "unionfs"))) {
  1880. + Err("nested " AUFS_NAME " %s\n", add->path);
  1881. + goto out;
  1882. + }
  1883. +#endif
  1884. +
  1885. +#ifdef AuNoNfsBranch
  1886. + if (unlikely(au_is_nfs(inode->i_sb))) {
  1887. + Err(AuNoNfsBranchMsg ". %s\n", add->path);
  1888. + goto out;
  1889. + }
  1890. +#endif
  1891. +
  1892. + err = test_br(sb, add->nd.dentry->d_inode, add->perm, add->path);
  1893. + if (unlikely(err))
  1894. + goto out;
  1895. +
  1896. + if (unlikely(bend == -1))
  1897. + return 0; /* success */
  1898. +
  1899. + hidden_inode = au_h_dptr(root)->d_inode;
  1900. + if (unlikely(au_flag_test(sb, AuFlag_WARN_PERM)
  1901. + && ((hidden_inode->i_mode & S_IALLUGO)
  1902. + != (inode->i_mode & S_IALLUGO)
  1903. + || hidden_inode->i_uid != inode->i_uid
  1904. + || hidden_inode->i_gid != inode->i_gid)))
  1905. + Warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
  1906. + add->path,
  1907. + inode->i_uid, inode->i_gid, (inode->i_mode & S_IALLUGO),
  1908. + hidden_inode->i_uid, hidden_inode->i_gid,
  1909. + (hidden_inode->i_mode & S_IALLUGO));
  1910. +
  1911. + err = -EINVAL;
  1912. + for (bindex = 0; bindex <= bend; bindex++)
  1913. + if (unlikely(is_overlap(sb, add->nd.dentry,
  1914. + au_h_dptr_i(root, bindex)))) {
  1915. + Err("%s is overlapped\n", add->path);
  1916. + goto out;
  1917. + }
  1918. + err = 0;
  1919. +
  1920. + out:
  1921. + TraceErr(err);
  1922. + return err;
  1923. +}
  1924. +
  1925. +int br_add(struct super_block *sb, struct opt_add *add, int remount)
  1926. +{
  1927. + int err, sz;
  1928. + aufs_bindex_t bend, add_bindex;
  1929. + struct dentry *root;
  1930. + struct aufs_iinfo *iinfo;
  1931. + struct aufs_sbinfo *sbinfo;
  1932. + struct aufs_dinfo *dinfo;
  1933. + struct inode *root_inode;
  1934. + unsigned long long maxb;
  1935. + struct aufs_branch **branchp, *add_branch;
  1936. + struct aufs_hdentry *hdentryp;
  1937. + struct aufs_hinode *hinodep;
  1938. +
  1939. + LKTRTrace("b%d, %s, 0x%x, %.*s\n", add->bindex, add->path,
  1940. + add->perm, DLNPair(add->nd.dentry));
  1941. + SiMustWriteLock(sb);
  1942. + root = sb->s_root;
  1943. + DiMustWriteLock(root);
  1944. + root_inode = root->d_inode;
  1945. + IMustLock(root_inode);
  1946. + IiMustWriteLock(root_inode);
  1947. +
  1948. + err = test_add(sb, add, remount);
  1949. + if (unlikely(err < 0))
  1950. + goto out;
  1951. + if (unlikely(err))
  1952. + return 0; /* success */
  1953. +
  1954. + bend = sbend(sb);
  1955. + add_branch = alloc_addbr(sb, bend + 2);
  1956. + err = PTR_ERR(add_branch);
  1957. + if (IS_ERR(add_branch))
  1958. + goto out;
  1959. +
  1960. + err = 0;
  1961. + rw_init_nolock(&add_branch->br_wh_rwsem);
  1962. + add_branch->br_wh = add_branch->br_plink = NULL;
  1963. + if (unlikely(br_writable(add->perm))) {
  1964. + err = init_br_wh(sb, /*bindex*/-1, add_branch, add->perm,
  1965. + add->nd.dentry, add->nd.mnt);
  1966. + if (unlikely(err)) {
  1967. + kfree(add_branch);
  1968. + goto out;
  1969. + }
  1970. + }
  1971. + add_branch->br_xino = NULL;
  1972. + add_branch->br_mnt = mntget(add->nd.mnt);
  1973. + atomic_set(&add_branch->br_wh_running, 0);
  1974. + add_branch->br_id = new_br_id(sb);
  1975. + add_branch->br_perm = add->perm;
  1976. + atomic_set(&add_branch->br_count, 0);
  1977. +
  1978. + sbinfo = stosi(sb);
  1979. + dinfo = dtodi(root);
  1980. + iinfo = itoii(root_inode);
  1981. +
  1982. + add_bindex = add->bindex;
  1983. + sz = sizeof(*(sbinfo->si_branch)) * (bend + 1 - add_bindex);
  1984. + branchp = sbinfo->si_branch + add_bindex;
  1985. + memmove(branchp + 1, branchp, sz);
  1986. + *branchp = add_branch;
  1987. + sz = sizeof(*hdentryp) * (bend + 1 - add_bindex);
  1988. + hdentryp = dinfo->di_hdentry + add_bindex;
  1989. + memmove(hdentryp + 1, hdentryp, sz);
  1990. + hdentryp->hd_dentry = NULL;
  1991. + sz = sizeof(*hinodep) * (bend + 1 - add_bindex);
  1992. + hinodep = iinfo->ii_hinode + add_bindex;
  1993. + memmove(hinodep + 1, hinodep, sz);
  1994. + hinodep->hi_inode = NULL;
  1995. + hinodep->hi_notify = NULL;
  1996. +
  1997. + sbinfo->si_bend++;
  1998. + dinfo->di_bend++;
  1999. + iinfo->ii_bend++;
  2000. + if (unlikely(bend == -1)) {
  2001. + dinfo->di_bstart = 0;
  2002. + iinfo->ii_bstart = 0;
  2003. + }
  2004. + set_h_dptr(root, add_bindex, dget(add->nd.dentry));
  2005. + set_h_iptr(root_inode, add_bindex, igrab(add->nd.dentry->d_inode), 0);
  2006. + if (!add_bindex)
  2007. + au_cpup_attr_all(root_inode);
  2008. + else
  2009. + au_add_nlink(root_inode, add->nd.dentry->d_inode);
  2010. + maxb = add->nd.dentry->d_sb->s_maxbytes;
  2011. + if (sb->s_maxbytes < maxb)
  2012. + sb->s_maxbytes = maxb;
  2013. +
  2014. + if (au_flag_test(sb, AuFlag_XINO)) {
  2015. + struct file *base_file = stobr(sb, 0)->br_xino;
  2016. + if (!add_bindex)
  2017. + base_file = stobr(sb, 1)->br_xino;
  2018. + err = xino_init(sb, add_bindex, base_file, /*do_test*/1);
  2019. + if (unlikely(err)) {
  2020. + DEBUG_ON(add_branch->br_xino);
  2021. + Err("ignored xino err %d, force noxino\n", err);
  2022. + err = 0;
  2023. + au_flag_clr(sb, AuFlag_XINO);
  2024. + }
  2025. + }
  2026. +
  2027. + out:
  2028. + TraceErr(err);
  2029. + return err;
  2030. +}
  2031. +
  2032. +/* ---------------------------------------------------------------------- */
  2033. +
  2034. +/*
  2035. + * test if the branch is deletable or not.
  2036. + */
  2037. +static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
  2038. +{
  2039. + int err, i, j, sigen;
  2040. + struct au_dcsub_pages dpages;
  2041. +
  2042. + LKTRTrace("b%d\n", bindex);
  2043. + SiMustWriteLock(root->d_sb);
  2044. + DiMustWriteLock(root);
  2045. +
  2046. + err = au_dpages_init(&dpages, GFP_KERNEL);
  2047. + if (unlikely(err))
  2048. + goto out;
  2049. + err = au_dcsub_pages(&dpages, root, NULL, NULL);
  2050. + if (unlikely(err))
  2051. + goto out_dpages;
  2052. +
  2053. + sigen = au_sigen(root->d_sb);
  2054. + DiMustNoWaiters(root);
  2055. + IiMustNoWaiters(root->d_inode);
  2056. + di_write_unlock(root);
  2057. + for (i = 0; !err && i < dpages.ndpage; i++) {
  2058. + struct au_dpage *dpage;
  2059. + dpage = dpages.dpages + i;
  2060. + for (j = 0; !err && j < dpage->ndentry; j++) {
  2061. + struct dentry *d;
  2062. +
  2063. + d = dpage->dentries[j];
  2064. + if (au_digen(d) == sigen)
  2065. + di_read_lock_child(d, AUFS_I_RLOCK);
  2066. + else {
  2067. + di_write_lock_child(d);
  2068. + err = au_reval_dpath(d, sigen);
  2069. + if (!err)
  2070. + di_downgrade_lock(d, AUFS_I_RLOCK);
  2071. + else {
  2072. + di_write_unlock(d);
  2073. + break;
  2074. + }
  2075. + }
  2076. +
  2077. + if (au_h_dptr_i(d, bindex)
  2078. + && (!S_ISDIR(d->d_inode->i_mode)
  2079. + || dbstart(d) == dbend(d)))
  2080. + err = -EBUSY;
  2081. + di_read_unlock(d, AUFS_I_RLOCK);
  2082. + if (err)
  2083. + LKTRTrace("%.*s\n", DLNPair(d));
  2084. + }
  2085. + }
  2086. + di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
  2087. +
  2088. + out_dpages:
  2089. + au_dpages_free(&dpages);
  2090. + out:
  2091. + TraceErr(err);
  2092. + return err;
  2093. +}
  2094. +
  2095. +int br_del(struct super_block *sb, struct opt_del *del, int remount)
  2096. +{
  2097. + int err, do_wh, rerr;
  2098. + struct dentry *root;
  2099. + struct inode *inode, *hidden_dir;
  2100. + aufs_bindex_t bindex, bend, br_id;
  2101. + struct aufs_sbinfo *sbinfo;
  2102. + struct aufs_dinfo *dinfo;
  2103. + struct aufs_iinfo *iinfo;
  2104. + struct aufs_branch *br;
  2105. +
  2106. + LKTRTrace("%s, %.*s\n", del->path, DLNPair(del->h_root));
  2107. + SiMustWriteLock(sb);
  2108. + root = sb->s_root;
  2109. + DiMustWriteLock(root);
  2110. + inode = root->d_inode;
  2111. + IiMustWriteLock(inode);
  2112. +
  2113. + bindex = au_find_dbindex(root, del->h_root);
  2114. + if (unlikely(bindex < 0)) {
  2115. + if (remount)
  2116. + return 0; /* success */
  2117. + err = -ENOENT;
  2118. + Err("%s no such branch\n", del->path);
  2119. + goto out;
  2120. + }
  2121. + LKTRTrace("bindex b%d\n", bindex);
  2122. +
  2123. + err = -EBUSY;
  2124. + bend = sbend(sb);
  2125. + br = stobr(sb, bindex);
  2126. + if (unlikely(!bend || br_count(br))) {
  2127. + LKTRTrace("bend %d, br_count %d\n", bend, br_count(br));
  2128. + goto out;
  2129. + }
  2130. +
  2131. + do_wh = 0;
  2132. + hidden_dir = del->h_root->d_inode;
  2133. + if (unlikely(br->br_wh || br->br_plink)) {
  2134. +#if 0
  2135. + /* remove whiteout base */
  2136. + err = init_br_wh(sb, bindex, br, AuBr_RO, del->h_root,
  2137. + br->br_mnt);
  2138. + if (unlikely(err))
  2139. + goto out;
  2140. +#else
  2141. + dput(br->br_wh);
  2142. + dput(br->br_plink);
  2143. + br->br_wh = br->br_plink = NULL;
  2144. +#endif
  2145. + do_wh = 1;
  2146. + }
  2147. +
  2148. + err = test_children_busy(root, bindex);
  2149. + if (unlikely(err)) {
  2150. + if (unlikely(do_wh))
  2151. + goto out_wh;
  2152. + goto out;
  2153. + }
  2154. +
  2155. + err = 0;
  2156. + sbinfo = stosi(sb);
  2157. + dinfo = dtodi(root);
  2158. + iinfo = itoii(inode);
  2159. +
  2160. + dput(au_h_dptr_i(root, bindex));
  2161. + aufs_hiput(iinfo->ii_hinode + bindex);
  2162. + br_id = br->br_id;
  2163. + free_branch(br);
  2164. +
  2165. + //todo: realloc and shrink memeory
  2166. + if (bindex < bend) {
  2167. + const aufs_bindex_t n = bend - bindex;
  2168. + struct aufs_branch **brp;
  2169. + struct aufs_hdentry *hdp;
  2170. + struct aufs_hinode *hip;
  2171. +
  2172. + brp = sbinfo->si_branch + bindex;
  2173. + memmove(brp, brp + 1, sizeof(*brp) * n);
  2174. + hdp = dinfo->di_hdentry + bindex;
  2175. + memmove(hdp, hdp + 1, sizeof(*hdp) * n);
  2176. + hip = iinfo->ii_hinode + bindex;
  2177. + memmove(hip, hip + 1, sizeof(*hip) * n);
  2178. + }
  2179. + sbinfo->si_branch[0 + bend] = NULL;
  2180. + dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
  2181. + iinfo->ii_hinode[0 + bend].hi_inode = NULL;
  2182. + iinfo->ii_hinode[0 + bend].hi_notify = NULL;
  2183. +
  2184. + sbinfo->si_bend--;
  2185. + dinfo->di_bend--;
  2186. + iinfo->ii_bend--;
  2187. + if (!bindex)
  2188. + au_cpup_attr_all(inode);
  2189. + else
  2190. + au_sub_nlink(inode, del->h_root->d_inode);
  2191. + if (au_flag_test(sb, AuFlag_PLINK))
  2192. + half_refresh_plink(sb, br_id);
  2193. +
  2194. + if (sb->s_maxbytes == del->h_root->d_sb->s_maxbytes) {
  2195. + bend--;
  2196. + sb->s_maxbytes = 0;
  2197. + for (bindex = 0; bindex <= bend; bindex++) {
  2198. + unsigned long long maxb;
  2199. + maxb = sbr_sb(sb, bindex)->s_maxbytes;
  2200. + if (sb->s_maxbytes < maxb)
  2201. + sb->s_maxbytes = maxb;
  2202. + }
  2203. + }
  2204. + goto out; /* success */
  2205. +
  2206. + out_wh:
  2207. + /* revert */
  2208. + rerr = init_br_wh(sb, bindex, br, br->br_perm, del->h_root, br->br_mnt);
  2209. + if (rerr)
  2210. + Warn("failed re-creating base whiteout, %s. (%d)\n",
  2211. + del->path, rerr);
  2212. + out:
  2213. + TraceErr(err);
  2214. + return err;
  2215. +}
  2216. +
  2217. +static int do_need_sigen_inc(int a, int b)
  2218. +{
  2219. + return (br_whable(a) && !br_whable(b));
  2220. +}
  2221. +
  2222. +static int need_sigen_inc(int old, int new)
  2223. +{
  2224. + return (do_need_sigen_inc(old, new)
  2225. + || do_need_sigen_inc(new, old));
  2226. +}
  2227. +
  2228. +int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
  2229. + int *do_update)
  2230. +{
  2231. + int err;
  2232. + struct dentry *root;
  2233. + aufs_bindex_t bindex;
  2234. + struct aufs_branch *br;
  2235. + struct inode *hidden_dir;
  2236. +
  2237. + LKTRTrace("%s, %.*s, 0x%x\n",
  2238. + mod->path, DLNPair(mod->h_root), mod->perm);
  2239. + SiMustWriteLock(sb);
  2240. + root = sb->s_root;
  2241. + DiMustWriteLock(root);
  2242. + IiMustWriteLock(root->d_inode);
  2243. +
  2244. + bindex = au_find_dbindex(root, mod->h_root);
  2245. + if (unlikely(bindex < 0)) {
  2246. + if (remount)
  2247. + return 0; /* success */
  2248. + err = -ENOENT;
  2249. + Err("%s no such branch\n", mod->path);
  2250. + goto out;
  2251. + }
  2252. + LKTRTrace("bindex b%d\n", bindex);
  2253. +
  2254. + hidden_dir = mod->h_root->d_inode;
  2255. + err = test_br(sb, hidden_dir, mod->perm, mod->path);
  2256. + if (unlikely(err))
  2257. + goto out;
  2258. +
  2259. + br = stobr(sb, bindex);
  2260. + if (unlikely(br->br_perm == mod->perm))
  2261. + return 0; /* success */
  2262. +
  2263. + if (br_writable(br->br_perm)) {
  2264. +#if 1
  2265. + /* remove whiteout base */
  2266. + //todo: mod->perm?
  2267. + err = init_br_wh(sb, bindex, br, AuBr_RO, mod->h_root,
  2268. + br->br_mnt);
  2269. + if (unlikely(err))
  2270. + goto out;
  2271. +#else
  2272. + dput(br->br_wh);
  2273. + dput(br->br_plink);
  2274. + br->br_wh = br->br_plink = NULL;
  2275. +#endif
  2276. +
  2277. + if (!br_writable(mod->perm)) {
  2278. + /* rw --> ro, file might be mmapped */
  2279. + struct file *file, *hf;
  2280. +
  2281. +#if 1 // test here
  2282. + DiMustNoWaiters(root);
  2283. + IiMustNoWaiters(root->d_inode);
  2284. + di_write_unlock(root);
  2285. +
  2286. + // no need file_list_lock() since sbinfo is locked
  2287. + //file_list_lock();
  2288. + list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
  2289. + LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
  2290. + fi_read_lock(file);
  2291. + if (!S_ISREG(file->f_dentry->d_inode->i_mode)
  2292. + || !(file->f_mode & FMODE_WRITE)
  2293. + || fbstart(file) != bindex) {
  2294. + FiMustNoWaiters(file);
  2295. + fi_read_unlock(file);
  2296. + continue;
  2297. + }
  2298. +
  2299. + // todo: already flushed?
  2300. + hf = au_h_fptr(file);
  2301. + hf->f_flags = au_file_roflags(hf->f_flags);
  2302. + hf->f_mode &= ~FMODE_WRITE;
  2303. + FiMustNoWaiters(file);
  2304. + fi_read_unlock(file);
  2305. + }
  2306. + //file_list_unlock();
  2307. +
  2308. + /* aufs_write_lock() calls ..._child() */
  2309. + di_write_lock_child(root);
  2310. +#endif
  2311. + }
  2312. + }
  2313. +
  2314. + *do_update |= need_sigen_inc(br->br_perm, mod->perm);
  2315. + br->br_perm = mod->perm;
  2316. + return err; /* success */
  2317. +
  2318. + out:
  2319. + TraceErr(err);
  2320. + return err;
  2321. +}
  2322. diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h
  2323. new file mode 100755
  2324. index 0000000..2557836
  2325. --- /dev/null
  2326. +++ b/fs/aufs/branch.h
  2327. @@ -0,0 +1,235 @@
  2328. +/*
  2329. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  2330. + *
  2331. + * This program, aufs is free software; you can redistribute it and/or modify
  2332. + * it under the terms of the GNU General Public License as published by
  2333. + * the Free Software Foundation; either version 2 of the License, or
  2334. + * (at your option) any later version.
  2335. + *
  2336. + * This program is distributed in the hope that it will be useful,
  2337. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2338. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2339. + * GNU General Public License for more details.
  2340. + *
  2341. + * You should have received a copy of the GNU General Public License
  2342. + * along with this program; if not, write to the Free Software
  2343. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  2344. + */
  2345. +
  2346. +/* $Id: branch.h,v 1.30 2007/05/14 03:41:51 sfjro Exp $ */
  2347. +
  2348. +#ifndef __AUFS_BRANCH_H__
  2349. +#define __AUFS_BRANCH_H__
  2350. +
  2351. +#ifdef __KERNEL__
  2352. +
  2353. +#include <linux/fs.h>
  2354. +#include <linux/mount.h>
  2355. +#include <linux/version.h>
  2356. +#include <linux/aufs_type.h>
  2357. +#include "misc.h"
  2358. +#include "super.h"
  2359. +
  2360. +/* protected by superblock rwsem */
  2361. +struct aufs_branch {
  2362. + struct file *br_xino;
  2363. + readf_t br_xino_read;
  2364. + writef_t br_xino_write;
  2365. +
  2366. + aufs_bindex_t br_id;
  2367. +
  2368. + int br_perm;
  2369. + struct vfsmount *br_mnt;
  2370. + atomic_t br_count;
  2371. +
  2372. + /* whiteout base */
  2373. + struct aufs_rwsem br_wh_rwsem;
  2374. + struct dentry *br_wh;
  2375. + atomic_t br_wh_running;
  2376. +
  2377. + /* pseudo-link dir */
  2378. + struct dentry *br_plink;
  2379. +};
  2380. +
  2381. +/* ---------------------------------------------------------------------- */
  2382. +
  2383. +/* branch permission and attribute */
  2384. +enum {
  2385. + AuBr_RW, /* writable, linkable wh */
  2386. + AuBr_RO, /* readonly, no wh */
  2387. + AuBr_RR, /* natively readonly, no wh */
  2388. +
  2389. + AuBr_RWNoLinkWH, /* un-linkable whiteouts */
  2390. +
  2391. + AuBr_ROWH,
  2392. + AuBr_RRWH, /* whiteout-able */
  2393. +
  2394. + AuBr_Last
  2395. +};
  2396. +
  2397. +static inline int br_writable(int brperm)
  2398. +{
  2399. + return (brperm == AuBr_RW
  2400. + || brperm == AuBr_RWNoLinkWH);
  2401. +}
  2402. +
  2403. +static inline int br_whable(int brperm)
  2404. +{
  2405. + return (brperm == AuBr_RW
  2406. + || brperm == AuBr_ROWH
  2407. + || brperm == AuBr_RRWH);
  2408. +}
  2409. +
  2410. +static inline int br_linkable_wh(int brperm)
  2411. +{
  2412. + return (brperm == AuBr_RW);
  2413. +}
  2414. +
  2415. +/* ---------------------------------------------------------------------- */
  2416. +
  2417. +#define _AuNoNfsBranchMsg "NFS branch is not supported"
  2418. +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,15)
  2419. +#define AuNoNfsBranch
  2420. +#define AuNoNfsBranchMsg _AuNoNfsBranchMsg
  2421. +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) \
  2422. + && !defined(CONFIG_AUFS_LHASH_PATCH)
  2423. +#define AuNoNfsBranch
  2424. +#define AuNoNfsBranchMsg _AuNoNfsBranchMsg \
  2425. + ", try lhash.patch and CONFIG_AUFS_LHASH_PATCH"
  2426. +#endif
  2427. +
  2428. +/* ---------------------------------------------------------------------- */
  2429. +
  2430. +struct aufs_sbinfo;
  2431. +void free_branches(struct aufs_sbinfo *sinfo);
  2432. +int br_rdonly(struct aufs_branch *br);
  2433. +int find_brindex(struct super_block *sb, aufs_bindex_t br_id);
  2434. +int find_rw_br(struct super_block *sb, aufs_bindex_t bend);
  2435. +int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend);
  2436. +struct opt_add;
  2437. +int br_add(struct super_block *sb, struct opt_add *add, int remount);
  2438. +struct opt_del;
  2439. +int br_del(struct super_block *sb, struct opt_del *del, int remount);
  2440. +struct opt_mod;
  2441. +int br_mod(struct super_block *sb, struct opt_mod *mod, int remount,
  2442. + int *do_update);
  2443. +
  2444. +/* ---------------------------------------------------------------------- */
  2445. +
  2446. +static inline int br_count(struct aufs_branch *br)
  2447. +{
  2448. + return atomic_read(&br->br_count);
  2449. +}
  2450. +
  2451. +static inline void br_get(struct aufs_branch *br)
  2452. +{
  2453. + atomic_inc(&br->br_count);
  2454. +}
  2455. +
  2456. +static inline void br_put(struct aufs_branch *br)
  2457. +{
  2458. + atomic_dec(&br->br_count);
  2459. +}
  2460. +
  2461. +/* ---------------------------------------------------------------------- */
  2462. +
  2463. +/* Superblock to branch */
  2464. +static inline aufs_bindex_t sbr_id(struct super_block *sb, aufs_bindex_t bindex)
  2465. +{
  2466. + return stobr(sb, bindex)->br_id;
  2467. +}
  2468. +
  2469. +static inline
  2470. +struct vfsmount *sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
  2471. +{
  2472. + return stobr(sb, bindex)->br_mnt;
  2473. +}
  2474. +
  2475. +static inline
  2476. +struct super_block *sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
  2477. +{
  2478. + return sbr_mnt(sb, bindex)->mnt_sb;
  2479. +}
  2480. +
  2481. +#if 0
  2482. +static inline int sbr_count(struct super_block *sb, aufs_bindex_t bindex)
  2483. +{
  2484. + return br_count(stobr(sb, bindex));
  2485. +}
  2486. +
  2487. +static inline void sbr_get(struct super_block *sb, aufs_bindex_t bindex)
  2488. +{
  2489. + br_get(stobr(sb, bindex));
  2490. +}
  2491. +#endif
  2492. +
  2493. +static inline void sbr_put(struct super_block *sb, aufs_bindex_t bindex)
  2494. +{
  2495. + br_put(stobr(sb, bindex));
  2496. +}
  2497. +
  2498. +static inline int sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
  2499. +{
  2500. + return stobr(sb, bindex)->br_perm;
  2501. +}
  2502. +
  2503. +static inline int sbr_is_whable(struct super_block *sb, aufs_bindex_t bindex)
  2504. +{
  2505. + return br_whable(sbr_perm(sb, bindex));
  2506. +}
  2507. +
  2508. +/* ---------------------------------------------------------------------- */
  2509. +
  2510. +#ifdef CONFIG_AUFS_LHASH_PATCH
  2511. +static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
  2512. +{
  2513. + if (!au_is_nfs(h_mnt->mnt_sb))
  2514. + return NULL;
  2515. + return h_mnt;
  2516. +}
  2517. +
  2518. +/* it doesn't mntget() */
  2519. +static inline
  2520. +struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
  2521. +{
  2522. + return au_do_nfsmnt(sbr_mnt(sb, bindex));
  2523. +}
  2524. +#else
  2525. +static inline struct vfsmount *au_do_nfsmnt(struct vfsmount *h_mnt)
  2526. +{
  2527. + return NULL;
  2528. +}
  2529. +
  2530. +static inline
  2531. +struct vfsmount *au_nfsmnt(struct super_block *sb, aufs_bindex_t bindex)
  2532. +{
  2533. + return NULL;
  2534. +}
  2535. +#endif /* CONFIG_AUFS_LHASH_PATCH */
  2536. +
  2537. +/* ---------------------------------------------------------------------- */
  2538. +
  2539. +/*
  2540. + * br_wh_read_lock, br_wh_write_lock
  2541. + * br_wh_read_unlock, br_wh_write_unlock, br_wh_downgrade_lock
  2542. + */
  2543. +SimpleRwsemFuncs(br_wh, struct aufs_branch *br, br->br_wh_rwsem);
  2544. +
  2545. +/* to debug easier, do not make them inlined functions */
  2546. +#define BrWhMustReadLock(br) do { \
  2547. + /* SiMustAnyLock(sb); */ \
  2548. + RwMustReadLock(&(br)->br_wh_rwsem); \
  2549. +} while (0)
  2550. +
  2551. +#define BrWhMustWriteLock(br) do { \
  2552. + /* SiMustAnyLock(sb); */ \
  2553. + RwMustWriteLock(&(br)->br_wh_rwsem); \
  2554. +} while (0)
  2555. +
  2556. +#define BrWhMustAnyLock(br) do { \
  2557. + /* SiMustAnyLock(sb); */ \
  2558. + RwMustAnyLock(&(br)->br_wh_rwsem); \
  2559. +} while (0)
  2560. +
  2561. +#endif /* __KERNEL__ */
  2562. +#endif /* __AUFS_BRANCH_H__ */
  2563. diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
  2564. new file mode 100755
  2565. index 0000000..6636f40
  2566. --- /dev/null
  2567. +++ b/fs/aufs/cpup.c
  2568. @@ -0,0 +1,773 @@
  2569. +/*
  2570. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  2571. + *
  2572. + * This program, aufs is free software; you can redistribute it and/or modify
  2573. + * it under the terms of the GNU General Public License as published by
  2574. + * the Free Software Foundation; either version 2 of the License, or
  2575. + * (at your option) any later version.
  2576. + *
  2577. + * This program is distributed in the hope that it will be useful,
  2578. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2579. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  2580. + * GNU General Public License for more details.
  2581. + *
  2582. + * You should have received a copy of the GNU General Public License
  2583. + * along with this program; if not, write to the Free Software
  2584. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  2585. + */
  2586. +
  2587. +/* $Id: cpup.c,v 1.37 2007/05/14 03:41:52 sfjro Exp $ */
  2588. +
  2589. +#include <asm/uaccess.h>
  2590. +#include "aufs.h"
  2591. +
  2592. +/* violent cpup_attr_*() functions don't care inode lock */
  2593. +void au_cpup_attr_timesizes(struct inode *inode)
  2594. +{
  2595. + struct inode *hidden_inode;
  2596. +
  2597. + LKTRTrace("i%lu\n", inode->i_ino);
  2598. + //IMustLock(inode);
  2599. + hidden_inode = au_h_iptr(inode);
  2600. + DEBUG_ON(!hidden_inode);
  2601. + //IMustLock(!hidden_inode);
  2602. +
  2603. + inode->i_atime = hidden_inode->i_atime;
  2604. + inode->i_mtime = hidden_inode->i_mtime;
  2605. + inode->i_ctime = hidden_inode->i_ctime;
  2606. + spin_lock(&inode->i_lock);
  2607. + i_size_write(inode, i_size_read(hidden_inode));
  2608. + inode->i_blocks = hidden_inode->i_blocks;
  2609. + spin_unlock(&inode->i_lock);
  2610. +}
  2611. +
  2612. +void au_cpup_attr_nlink(struct inode *inode)
  2613. +{
  2614. + struct inode *h_inode;
  2615. +
  2616. + LKTRTrace("i%lu\n", inode->i_ino);
  2617. + //IMustLock(inode);
  2618. + DEBUG_ON(!inode->i_mode);
  2619. +
  2620. + h_inode = au_h_iptr(inode);
  2621. + inode->i_nlink = h_inode->i_nlink;
  2622. +
  2623. + /*
  2624. + * fewer nlink makes find(1) noisy, but larger nlink doesn't.
  2625. + * it may includes whplink directory.
  2626. + */
  2627. + if (unlikely(S_ISDIR(h_inode->i_mode))) {
  2628. + aufs_bindex_t bindex, bend;
  2629. + bend = ibend(inode);
  2630. + for (bindex = ibstart(inode) + 1; bindex <= bend; bindex++) {
  2631. + h_inode = au_h_iptr_i(inode, bindex);
  2632. + if (h_inode)
  2633. + au_add_nlink(inode, h_inode);
  2634. + }
  2635. + }
  2636. +}
  2637. +
  2638. +void au_cpup_attr_changable(struct inode *inode)
  2639. +{
  2640. + struct inode *hidden_inode;
  2641. +
  2642. + LKTRTrace("i%lu\n", inode->i_ino);
  2643. + //IMustLock(inode);
  2644. + hidden_inode = au_h_iptr(inode);
  2645. + DEBUG_ON(!hidden_inode);
  2646. +
  2647. + inode->i_mode = hidden_inode->i_mode;
  2648. + inode->i_uid = hidden_inode->i_uid;
  2649. + inode->i_gid = hidden_inode->i_gid;
  2650. + au_cpup_attr_timesizes(inode);
  2651. +
  2652. + //??
  2653. + inode->i_flags = hidden_inode->i_flags;
  2654. +}
  2655. +
  2656. +void au_cpup_igen(struct inode *inode, struct inode *h_inode)
  2657. +{
  2658. + inode->i_generation = h_inode->i_generation;
  2659. + itoii(inode)->ii_hsb1 = h_inode->i_sb;
  2660. +}
  2661. +
  2662. +void au_cpup_attr_all(struct inode *inode)
  2663. +{
  2664. + struct inode *hidden_inode;
  2665. +
  2666. + LKTRTrace("i%lu\n", inode->i_ino);
  2667. + //IMustLock(inode);
  2668. + hidden_inode = au_h_iptr(inode);
  2669. + DEBUG_ON(!hidden_inode);
  2670. +
  2671. + au_cpup_attr_changable(inode);
  2672. + if (inode->i_nlink > 0)
  2673. + au_cpup_attr_nlink(inode);
  2674. +
  2675. + switch (inode->i_mode & S_IFMT) {
  2676. + case S_IFBLK:
  2677. + case S_IFCHR:
  2678. + inode->i_rdev = hidden_inode->i_rdev;
  2679. + }
  2680. + inode->i_blkbits = hidden_inode->i_blkbits;
  2681. + au_cpup_attr_blksize(inode, hidden_inode);
  2682. + au_cpup_igen(inode, hidden_inode);
  2683. +}
  2684. +
  2685. +/* ---------------------------------------------------------------------- */
  2686. +
  2687. +/* Note: dt_dentry and dt_hidden_dentry are not dget/dput-ed */
  2688. +
  2689. +/* keep the timestamps of the parent dir when cpup */
  2690. +void dtime_store(struct dtime *dt, struct dentry *dentry,
  2691. + struct dentry *hidden_dentry)
  2692. +{
  2693. + struct inode *inode;
  2694. +
  2695. + TraceEnter();
  2696. + DEBUG_ON(!dentry || !hidden_dentry || !hidden_dentry->d_inode);
  2697. +
  2698. + dt->dt_dentry = dentry;
  2699. + dt->dt_h_dentry = hidden_dentry;
  2700. + inode = hidden_dentry->d_inode;
  2701. + dt->dt_atime = inode->i_atime;
  2702. + dt->dt_mtime = inode->i_mtime;
  2703. + //smp_mb();
  2704. +}
  2705. +
  2706. +// todo: remove extra parameter
  2707. +void dtime_revert(struct dtime *dt, int h_parent_is_locked)
  2708. +{
  2709. + struct iattr attr;
  2710. + int err;
  2711. + struct dentry *dentry;
  2712. +
  2713. + LKTRTrace("h_parent locked %d\n", h_parent_is_locked);
  2714. +
  2715. + attr.ia_atime = dt->dt_atime;
  2716. + attr.ia_mtime = dt->dt_mtime;
  2717. + attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
  2718. + | ATTR_ATIME | ATTR_ATIME_SET;
  2719. + //smp_mb();
  2720. + dentry = NULL;
  2721. + if (!h_parent_is_locked /* && !IS_ROOT(dt->dt_dentry) */)
  2722. + dentry = dt->dt_dentry;
  2723. + err = vfsub_notify_change(dt->dt_h_dentry, &attr,
  2724. + need_dlgt(dt->dt_dentry->d_sb));
  2725. + if (unlikely(err))
  2726. + Warn("restoring timestamps failed(%d). ignored\n", err);
  2727. +}
  2728. +
  2729. +/* ---------------------------------------------------------------------- */
  2730. +
  2731. +static int cpup_iattr(struct dentry *hidden_dst, struct dentry *hidden_src,
  2732. + int dlgt)
  2733. +{
  2734. + int err;
  2735. + struct iattr ia;
  2736. + struct inode *hidden_isrc, *hidden_idst;
  2737. +
  2738. + LKTRTrace("%.*s\n", DLNPair(hidden_dst));
  2739. + hidden_idst = hidden_dst->d_inode;
  2740. + //IMustLock(hidden_idst);
  2741. + hidden_isrc = hidden_src->d_inode;
  2742. + //IMustLock(hidden_isrc);
  2743. +
  2744. + ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
  2745. + | ATTR_ATIME | ATTR_MTIME
  2746. + | ATTR_ATIME_SET | ATTR_MTIME_SET;
  2747. + ia.ia_mode = hidden_isrc->i_mode;
  2748. + ia.ia_uid = hidden_isrc->i_uid;
  2749. + ia.ia_gid = hidden_isrc->i_gid;
  2750. + ia.ia_atime = hidden_isrc->i_atime;
  2751. + ia.ia_mtime = hidden_isrc->i_mtime;
  2752. + err = vfsub_notify_change(hidden_dst, &ia, dlgt);
  2753. + //if (LktrCond) err = -1;
  2754. + if (!err)
  2755. + hidden_idst->i_flags = hidden_isrc->i_flags; //??
  2756. +
  2757. + TraceErr(err);
  2758. + return err;
  2759. +}
  2760. +
  2761. +/*
  2762. + * to support a sparse file which is opened with O_APPEND,
  2763. + * we need to close the file.
  2764. + */
  2765. +static int cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
  2766. + aufs_bindex_t bsrc, loff_t len)
  2767. +{
  2768. + int err, i, sparse;
  2769. + struct super_block *sb;
  2770. + struct inode *hidden_inode;
  2771. + enum {SRC, DST};
  2772. + struct {
  2773. + aufs_bindex_t bindex;
  2774. + unsigned int flags;
  2775. + struct dentry *dentry;
  2776. + struct file *file;
  2777. + void *label, *label_file;
  2778. + } *h, hidden[] = {
  2779. + {
  2780. + .bindex = bsrc,
  2781. + .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
  2782. + .file = NULL,
  2783. + .label = &&out,
  2784. + .label_file = &&out_src_file
  2785. + },
  2786. + {
  2787. + .bindex = bdst,
  2788. + .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
  2789. + .file = NULL,
  2790. + .label = &&out_src_file,
  2791. + .label_file = &&out_dst_file
  2792. + }
  2793. + };
  2794. +
  2795. + LKTRTrace("dentry %.*s, bdst %d, bsrc %d, len %lld\n",
  2796. + DLNPair(dentry), bdst, bsrc, len);
  2797. + DEBUG_ON(bsrc <= bdst);
  2798. + DEBUG_ON(!len);
  2799. + sb = dentry->d_sb;
  2800. + DEBUG_ON(test_ro(sb, bdst, dentry->d_inode));
  2801. + // bsrc branch can be ro/rw.
  2802. +
  2803. + h = hidden;
  2804. + for (i = 0; i < 2; i++, h++) {
  2805. + h->dentry = au_h_dptr_i(dentry, h->bindex);
  2806. + DEBUG_ON(!h->dentry);
  2807. + hidden_inode = h->dentry->d_inode;
  2808. + DEBUG_ON(!hidden_inode || !S_ISREG(hidden_inode->i_mode));
  2809. + h->file = hidden_open(dentry, h->bindex, h->flags);
  2810. + //if (LktrCond)
  2811. + //{fput(h->file); sbr_put(sb, h->bindex); h->file = ERR_PTR(-1);}
  2812. + err = PTR_ERR(h->file);
  2813. + if (IS_ERR(h->file))
  2814. + goto *h->label;
  2815. + err = -EINVAL;
  2816. + if (unlikely(!h->file->f_op))
  2817. + goto *h->label_file;
  2818. + }
  2819. +
  2820. + /* stop updating while we copyup */
  2821. + IMustLock(hidden[SRC].dentry->d_inode);
  2822. + sparse = 0;
  2823. + err = au_copy_file(hidden[DST].file, hidden[SRC].file, len, sb,
  2824. + &sparse);
  2825. +
  2826. + /* sparse file: update i_blocks next time */
  2827. + if (unlikely(!err && sparse))
  2828. + d_drop(dentry);
  2829. +
  2830. + out_dst_file:
  2831. + fput(hidden[DST].file);
  2832. + sbr_put(sb, hidden[DST].bindex);
  2833. + out_src_file:
  2834. + fput(hidden[SRC].file);
  2835. + sbr_put(sb, hidden[SRC].bindex);
  2836. + out:
  2837. + TraceErr(err);
  2838. + return err;
  2839. +}
  2840. +
  2841. +// unnecessary?
  2842. +unsigned int au_flags_cpup(unsigned int init, struct dentry *parent)
  2843. +{
  2844. + if (unlikely(parent && IS_ROOT(parent)))
  2845. + init |= CPUP_LOCKED_GHDIR;
  2846. + return init;
  2847. +}
  2848. +
  2849. +/* return with hidden dst inode is locked */
  2850. +static int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
  2851. + aufs_bindex_t bsrc, loff_t len, unsigned int flags,
  2852. + int dlgt)
  2853. +{
  2854. + int err, isdir, symlen;
  2855. + struct dentry *hidden_src, *hidden_dst, *hidden_parent, *parent;
  2856. + struct inode *hidden_inode, *hidden_dir, *dir;
  2857. + struct dtime dt;
  2858. + umode_t mode;
  2859. + char *sym;
  2860. + mm_segment_t old_fs;
  2861. + const int do_dt = flags & CPUP_DTIME;
  2862. + struct super_block *sb;
  2863. +
  2864. + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
  2865. + DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
  2866. + flags);
  2867. + sb = dentry->d_sb;
  2868. + DEBUG_ON(bdst >= bsrc || test_ro(sb, bdst, NULL));
  2869. + // bsrc branch can be ro/rw.
  2870. +
  2871. + hidden_src = au_h_dptr_i(dentry, bsrc);
  2872. + DEBUG_ON(!hidden_src);
  2873. + hidden_inode = hidden_src->d_inode;
  2874. + DEBUG_ON(!hidden_inode);
  2875. +
  2876. + /* stop refrencing while we are creating */
  2877. + //parent = dget_parent(dentry);
  2878. + parent = dentry->d_parent;
  2879. + dir = parent->d_inode;
  2880. + hidden_dst = au_h_dptr_i(dentry, bdst);
  2881. + DEBUG_ON(hidden_dst && hidden_dst->d_inode);
  2882. + //hidden_parent = dget_parent(hidden_dst);
  2883. + hidden_parent = hidden_dst->d_parent;
  2884. + hidden_dir = hidden_parent->d_inode;
  2885. + IMustLock(hidden_dir);
  2886. +
  2887. + if (do_dt)
  2888. + dtime_store(&dt, parent, hidden_parent);
  2889. +
  2890. + isdir = 0;
  2891. + mode = hidden_inode->i_mode;
  2892. + switch (mode & S_IFMT) {
  2893. + case S_IFREG:
  2894. + /* stop updating while we are referencing */
  2895. + IMustLock(hidden_inode);
  2896. + err = vfsub_create(hidden_dir, hidden_dst, mode | S_IWUSR, NULL,
  2897. + dlgt);
  2898. + //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
  2899. + if (!err) {
  2900. + loff_t l = i_size_read(hidden_inode);
  2901. + if (len == -1 || l < len)
  2902. + len = l;
  2903. + if (len) {
  2904. + err = cpup_regular(dentry, bdst, bsrc, len);
  2905. + //if (LktrCond) err = -1;
  2906. + }
  2907. + if (unlikely(err)) {
  2908. + int rerr;
  2909. + rerr = vfsub_unlink(hidden_dir, hidden_dst,
  2910. + dlgt);
  2911. + if (rerr) {
  2912. + IOErr("failed unlinking cpup-ed %.*s"
  2913. + "(%d, %d)\n",
  2914. + DLNPair(hidden_dst), err, rerr);
  2915. + err = -EIO;
  2916. + }
  2917. + }
  2918. + }
  2919. + break;
  2920. + case S_IFDIR:
  2921. + isdir = 1;
  2922. + err = vfsub_mkdir(hidden_dir, hidden_dst, mode, dlgt);
  2923. + //if (LktrCond) {vfs_rmdir(hidden_dir, hidden_dst); err = -1;}
  2924. + if (!err) {
  2925. + /* setattr case: dir is not locked */
  2926. + if (0 && ibstart(dir) == bdst)
  2927. + au_cpup_attr_nlink(dir);
  2928. + au_cpup_attr_nlink(dentry->d_inode);
  2929. + }
  2930. + break;
  2931. + case S_IFLNK:
  2932. + err = -ENOMEM;
  2933. + sym = __getname();
  2934. + //if (LktrCond) {__putname(sym); sym = NULL;}
  2935. + if (unlikely(!sym))
  2936. + break;
  2937. + old_fs = get_fs();
  2938. + set_fs(KERNEL_DS);
  2939. + err = symlen = hidden_inode->i_op->readlink
  2940. + (hidden_src, (char __user*)sym, PATH_MAX);
  2941. + //if (LktrCond) err = symlen = -1;
  2942. + set_fs(old_fs);
  2943. + if (symlen > 0) {
  2944. + sym[symlen] = 0;
  2945. + err = vfsub_symlink(hidden_dir, hidden_dst, sym, mode,
  2946. + dlgt);
  2947. + //if (LktrCond)
  2948. + //{vfs_unlink(hidden_dir, hidden_dst); err = -1;}
  2949. + }
  2950. + __putname(sym);
  2951. + break;
  2952. + case S_IFCHR:
  2953. + case S_IFBLK:
  2954. + DEBUG_ON(!capable(CAP_MKNOD));
  2955. + /*FALLTHROUGH*/
  2956. + case S_IFIFO:
  2957. + case S_IFSOCK:
  2958. + err = vfsub_mknod(hidden_dir, hidden_dst, mode,
  2959. + hidden_inode->i_rdev, dlgt);
  2960. + //if (LktrCond) {vfs_unlink(hidden_dir, hidden_dst); err = -1;}
  2961. + break;
  2962. + default:
  2963. + IOErr("Unknown inode type 0%o\n", mode);
  2964. + err = -EIO;
  2965. + }
  2966. +
  2967. + if (do_dt)
  2968. + dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
  2969. + //dput(parent);
  2970. + //dput(hidden_parent);
  2971. + TraceErr(err);
  2972. + return err;
  2973. +}
  2974. +
  2975. +/*
  2976. + * copyup the @dentry from @bsrc to @bdst.
  2977. + * the caller must set the both of hidden dentries.
  2978. + * @len is for trucating when it is -1 copyup the entire file.
  2979. + */
  2980. +int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
  2981. + loff_t len, unsigned int flags)
  2982. +{
  2983. + int err, rerr, isdir, dlgt;
  2984. + struct dentry *hidden_src, *hidden_dst, *parent;//, *h_parent;
  2985. + struct inode *dst_inode, *hidden_dir, *inode, *src_inode;
  2986. + struct super_block *sb;
  2987. + aufs_bindex_t old_ibstart;
  2988. + struct dtime dt;
  2989. +
  2990. + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
  2991. + DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
  2992. + flags);
  2993. + sb = dentry->d_sb;
  2994. + DEBUG_ON(bsrc <= bdst);
  2995. + hidden_dst = au_h_dptr_i(dentry, bdst);
  2996. + DEBUG_ON(!hidden_dst || hidden_dst->d_inode);
  2997. + //h_parent = dget_parent(hidden_dst);
  2998. + //hidden_dir = h_parent->d_inode;
  2999. + hidden_dir = hidden_dst->d_parent->d_inode;
  3000. + IMustLock(hidden_dir);
  3001. + hidden_src = au_h_dptr_i(dentry, bsrc);
  3002. + DEBUG_ON(!hidden_src || !hidden_src->d_inode);
  3003. + inode = dentry->d_inode;
  3004. + IiMustWriteLock(inode);
  3005. +
  3006. + dlgt = need_dlgt(sb);
  3007. + dst_inode = au_h_iptr_i(inode, bdst);
  3008. + if (unlikely(dst_inode)) {
  3009. + if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
  3010. + err = -EIO;
  3011. + IOErr("i%lu exists on a upper branch "
  3012. + "but plink is disabled\n", inode->i_ino);
  3013. + goto out;
  3014. + }
  3015. +
  3016. + if (dst_inode->i_nlink) {
  3017. + hidden_src = lkup_plink(sb, bdst, inode);
  3018. + err = PTR_ERR(hidden_src);
  3019. + if (IS_ERR(hidden_src))
  3020. + goto out;
  3021. + DEBUG_ON(!hidden_src->d_inode);
  3022. + // vfs_link() does lock the inode
  3023. + err = vfsub_link(hidden_src, hidden_dir, hidden_dst, dlgt);
  3024. + dput(hidden_src);
  3025. + goto out;
  3026. + } else
  3027. + /* udba work */
  3028. + au_update_brange(inode, 1);
  3029. + }
  3030. +
  3031. + old_ibstart = ibstart(inode);
  3032. + err = cpup_entry(dentry, bdst, bsrc, len, flags, dlgt);
  3033. + if (unlikely(err))
  3034. + goto out;
  3035. + dst_inode = hidden_dst->d_inode;
  3036. + hi_lock_child2(dst_inode);
  3037. +
  3038. + //todo: test dlgt
  3039. + err = cpup_iattr(hidden_dst, hidden_src, dlgt);
  3040. + //if (LktrCond) err = -1;
  3041. +#if 0 // xattr
  3042. + if (0 && !err)
  3043. + err = cpup_xattrs(hidden_src, hidden_dst);
  3044. +#endif
  3045. + isdir = S_ISDIR(dst_inode->i_mode);
  3046. + if (!err) {
  3047. + if (bdst < old_ibstart)
  3048. + set_ibstart(inode, bdst);
  3049. + set_h_iptr(inode, bdst, igrab(dst_inode),
  3050. + au_hi_flags(inode, isdir));
  3051. + i_unlock(dst_inode);
  3052. + src_inode = hidden_src->d_inode;
  3053. + if (!isdir) {
  3054. + if (src_inode->i_nlink > 1
  3055. + && au_flag_test(sb, AuFlag_PLINK))
  3056. + append_plink(sb, inode, hidden_dst, bdst);
  3057. + else {
  3058. + /* braces are added to stop a warning */
  3059. + ;//xino_write0(sb, bsrc, src_inode->i_ino);
  3060. + /* ignore this error */
  3061. + }
  3062. + }
  3063. + //goto out; /* success */
  3064. + return 0; /* success */
  3065. + }
  3066. +
  3067. + /* revert */
  3068. + i_unlock(dst_inode);
  3069. + parent = dget_parent(dentry);
  3070. + //dtime_store(&dt, parent, h_parent);
  3071. + dtime_store(&dt, parent, hidden_dst->d_parent);
  3072. + dput(parent);
  3073. + if (!isdir)
  3074. + rerr = vfsub_unlink(hidden_dir, hidden_dst, dlgt);
  3075. + else
  3076. + rerr = vfsub_rmdir(hidden_dir, hidden_dst, dlgt);
  3077. + //rerr = -1;
  3078. + dtime_revert(&dt, flags & CPUP_LOCKED_GHDIR);
  3079. + if (rerr) {
  3080. + IOErr("failed removing broken entry(%d, %d)\n", err, rerr);
  3081. + err = -EIO;
  3082. + }
  3083. +
  3084. + out:
  3085. + //dput(h_parent);
  3086. + TraceErr(err);
  3087. + return err;
  3088. +}
  3089. +
  3090. +struct cpup_single_args {
  3091. + int *errp;
  3092. + struct dentry *dentry;
  3093. + aufs_bindex_t bdst, bsrc;
  3094. + loff_t len;
  3095. + unsigned int flags;
  3096. +};
  3097. +
  3098. +static void call_cpup_single(void *args)
  3099. +{
  3100. + struct cpup_single_args *a = args;
  3101. + *a->errp = cpup_single(a->dentry, a->bdst, a->bsrc, a->len, a->flags);
  3102. +}
  3103. +
  3104. +int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
  3105. + aufs_bindex_t bsrc, loff_t len, unsigned int flags)
  3106. +{
  3107. + int err;
  3108. + struct dentry *hidden_dentry;
  3109. + umode_t mode;
  3110. +
  3111. + LKTRTrace("%.*s, i%lu, bdst %d, bsrc %d, len %Ld, flags 0x%x\n",
  3112. + DLNPair(dentry), dentry->d_inode->i_ino, bdst, bsrc, len,
  3113. + flags);
  3114. +
  3115. + hidden_dentry = au_h_dptr_i(dentry, bsrc);
  3116. + mode = hidden_dentry->d_inode->i_mode & S_IFMT;
  3117. + if ((mode != S_IFCHR && mode != S_IFBLK)
  3118. + || capable(CAP_MKNOD))
  3119. + err = cpup_single(dentry, bdst, bsrc, len, flags);
  3120. + else {
  3121. + struct cpup_single_args args = {
  3122. + .errp = &err,
  3123. + .dentry = dentry,
  3124. + .bdst = bdst,
  3125. + .bsrc = bsrc,
  3126. + .len = len,
  3127. + .flags = flags
  3128. + };
  3129. + au_wkq_wait(call_cpup_single, &args, /*dlgt*/0);
  3130. + }
  3131. +
  3132. + TraceErr(err);
  3133. + return err;
  3134. +}
  3135. +
  3136. +/*
  3137. + * copyup the @dentry from the first active hidden branch to @bdst,
  3138. + * using cpup_single().
  3139. + */
  3140. +int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3141. + unsigned int flags)
  3142. +{
  3143. + int err;
  3144. + struct inode *inode;
  3145. + aufs_bindex_t bsrc, bend;
  3146. +
  3147. + LKTRTrace("%.*s, bdst %d, len %Ld, flags 0x%x\n",
  3148. + DLNPair(dentry), bdst, len, flags);
  3149. + inode = dentry->d_inode;
  3150. + DEBUG_ON(!S_ISDIR(inode->i_mode) && dbstart(dentry) < bdst);
  3151. +
  3152. + bend = dbend(dentry);
  3153. + for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
  3154. + if (au_h_dptr_i(dentry, bsrc))
  3155. + break;
  3156. + DEBUG_ON(!au_h_dptr_i(dentry, bsrc));
  3157. +
  3158. + err = lkup_neg(dentry, bdst);
  3159. + //err = -1;
  3160. + if (!err) {
  3161. + err = cpup_single(dentry, bdst, bsrc, len, flags);
  3162. + if (!err)
  3163. + return 0; /* success */
  3164. +
  3165. + /* revert */
  3166. + set_h_dptr(dentry, bdst, NULL);
  3167. + set_dbstart(dentry, bsrc);
  3168. + }
  3169. +
  3170. + TraceErr(err);
  3171. + return err;
  3172. +}
  3173. +
  3174. +struct cpup_simple_args {
  3175. + int *errp;
  3176. + struct dentry *dentry;
  3177. + aufs_bindex_t bdst;
  3178. + loff_t len;
  3179. + unsigned int flags;
  3180. +};
  3181. +
  3182. +static void call_cpup_simple(void *args)
  3183. +{
  3184. + struct cpup_simple_args *a = args;
  3185. + *a->errp = cpup_simple(a->dentry, a->bdst, a->len, a->flags);
  3186. +}
  3187. +
  3188. +int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3189. + unsigned int flags)
  3190. +{
  3191. + int err, do_sio, dlgt;
  3192. + //struct dentry *parent;
  3193. + struct inode *hidden_dir, *dir;
  3194. +
  3195. + LKTRTrace("%.*s, b%d, len %Ld, flags 0x%x\n",
  3196. + DLNPair(dentry), bdst, len, flags);
  3197. +
  3198. + //parent = dget_parent(dentry);
  3199. + //dir = parent->d_inode;
  3200. + dir = dentry->d_parent->d_inode;
  3201. + hidden_dir = au_h_iptr_i(dir, bdst);
  3202. + dlgt = need_dlgt(dir->i_sb);
  3203. + do_sio = au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE, dlgt);
  3204. + if (!do_sio) {
  3205. + umode_t mode = dentry->d_inode->i_mode & S_IFMT;
  3206. + do_sio = ((mode == S_IFCHR || mode == S_IFBLK)
  3207. + && !capable(CAP_MKNOD));
  3208. + }
  3209. + if (!do_sio)
  3210. + err = cpup_simple(dentry, bdst, len, flags);
  3211. + else {
  3212. + struct cpup_simple_args args = {
  3213. + .errp = &err,
  3214. + .dentry = dentry,
  3215. + .bdst = bdst,
  3216. + .len = len,
  3217. + .flags = flags
  3218. + };
  3219. + au_wkq_wait(call_cpup_simple, &args, /*dlgt*/0);
  3220. + }
  3221. +
  3222. + //dput(parent);
  3223. + TraceErr(err);
  3224. + return err;
  3225. +}
  3226. +
  3227. +//todo: dcsub
  3228. +/* cf. revalidate function in file.c */
  3229. +int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked)
  3230. +{
  3231. + int err;
  3232. + struct super_block *sb;
  3233. + struct dentry *d, *parent, *hidden_parent;
  3234. + unsigned int udba;
  3235. +
  3236. + LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
  3237. + DLNPair(dentry), bdst, parent_ino(dentry), locked);
  3238. + sb = dentry->d_sb;
  3239. + DEBUG_ON(test_ro(sb, bdst, NULL));
  3240. + parent = dentry->d_parent;
  3241. + IiMustWriteLock(parent->d_inode);
  3242. + if (unlikely(IS_ROOT(parent)))
  3243. + return 0;
  3244. + if (locked) {
  3245. + DiMustAnyLock(locked);
  3246. + IiMustAnyLock(locked->d_inode);
  3247. + }
  3248. +
  3249. + /* slow loop, keep it simple and stupid */
  3250. + err = 0;
  3251. + udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
  3252. + while (1) {
  3253. + parent = dentry->d_parent; // dget_parent()
  3254. + hidden_parent = au_h_dptr_i(parent, bdst);
  3255. + if (hidden_parent)
  3256. + return 0; /* success */
  3257. +
  3258. + /* find top dir which is needed to cpup */
  3259. + do {
  3260. + d = parent;
  3261. + parent = d->d_parent; // dget_parent()
  3262. + if (parent != locked)
  3263. + di_read_lock_parent3(parent, !AUFS_I_RLOCK);
  3264. + hidden_parent = au_h_dptr_i(parent, bdst);
  3265. + if (parent != locked)
  3266. + di_read_unlock(parent, !AUFS_I_RLOCK);
  3267. + } while (!hidden_parent);
  3268. +
  3269. + if (d != dentry->d_parent)
  3270. + di_write_lock_child3(d);
  3271. +
  3272. + /* somebody else might create while we were sleeping */
  3273. + if (!au_h_dptr_i(d, bdst) || !au_h_dptr_i(d, bdst)->d_inode) {
  3274. + struct inode *h_dir = hidden_parent->d_inode,
  3275. + *dir = parent->d_inode,
  3276. + *h_gdir, *gdir;
  3277. +
  3278. + if (au_h_dptr_i(d, bdst))
  3279. + au_update_dbstart(d);
  3280. + //DEBUG_ON(dbstart(d) <= bdst);
  3281. + if (parent != locked)
  3282. + di_read_lock_parent3(parent, AUFS_I_RLOCK);
  3283. + h_gdir = gdir = NULL;
  3284. + if (unlikely(udba && !IS_ROOT(parent))) {
  3285. + gdir = parent->d_parent->d_inode;
  3286. + h_gdir = hidden_parent->d_parent->d_inode;
  3287. + hgdir_lock(h_gdir, gdir, bdst);
  3288. + }
  3289. + hdir_lock(h_dir, dir, bdst);
  3290. + err = sio_cpup_simple(d, bdst, -1,
  3291. + au_flags_cpup(CPUP_DTIME,
  3292. + parent));
  3293. + //if (LktrCond) err = -1;
  3294. + hdir_unlock(h_dir, dir, bdst);
  3295. + if (unlikely(gdir))
  3296. + hdir_unlock(h_gdir, gdir, bdst);
  3297. + if (parent != locked)
  3298. + di_read_unlock(parent, AUFS_I_RLOCK);
  3299. + }
  3300. +
  3301. + if (d != dentry->d_parent)
  3302. + di_write_unlock(d);
  3303. + if (unlikely(err))
  3304. + break;
  3305. + }
  3306. +
  3307. +// out:
  3308. + TraceErr(err);
  3309. + return err;
  3310. +}
  3311. +
  3312. +int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
  3313. + struct dentry *locked)
  3314. +{
  3315. + int err;
  3316. + struct dentry *parent;
  3317. + struct inode *dir;
  3318. +
  3319. + parent = dentry->d_parent;
  3320. + dir = parent->d_inode;
  3321. + LKTRTrace("%.*s, b%d, parent i%lu, locked %p\n",
  3322. + DLNPair(dentry), bdst, dir->i_ino, locked);
  3323. + DiMustReadLock(parent);
  3324. + IiMustReadLock(dir);
  3325. +
  3326. + if (au_h_iptr_i(dir, bdst))
  3327. + return 0;
  3328. +
  3329. + err = 0;
  3330. + di_read_unlock(parent, AUFS_I_RLOCK);
  3331. + di_write_lock_parent(parent);
  3332. + if (au_h_iptr_i(dir, bdst))
  3333. + goto out;
  3334. +
  3335. + err = cpup_dirs(dentry, bdst, locked);
  3336. +
  3337. + out:
  3338. + di_downgrade_lock(parent, AUFS_I_RLOCK);
  3339. + TraceErr(err);
  3340. + return err;
  3341. +}
  3342. diff --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h
  3343. new file mode 100755
  3344. index 0000000..86557aa
  3345. --- /dev/null
  3346. +++ b/fs/aufs/cpup.h
  3347. @@ -0,0 +1,72 @@
  3348. +/*
  3349. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  3350. + *
  3351. + * This program, aufs is free software; you can redistribute it and/or modify
  3352. + * it under the terms of the GNU General Public License as published by
  3353. + * the Free Software Foundation; either version 2 of the License, or
  3354. + * (at your option) any later version.
  3355. + *
  3356. + * This program is distributed in the hope that it will be useful,
  3357. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3358. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3359. + * GNU General Public License for more details.
  3360. + *
  3361. + * You should have received a copy of the GNU General Public License
  3362. + * along with this program; if not, write to the Free Software
  3363. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3364. + */
  3365. +
  3366. +/* $Id: cpup.h,v 1.15 2007/05/14 03:41:52 sfjro Exp $ */
  3367. +
  3368. +#ifndef __AUFS_CPUP_H__
  3369. +#define __AUFS_CPUP_H__
  3370. +
  3371. +#ifdef __KERNEL__
  3372. +
  3373. +#include <linux/fs.h>
  3374. +#include <linux/version.h>
  3375. +#include <linux/aufs_type.h>
  3376. +
  3377. +static inline
  3378. +void au_cpup_attr_blksize(struct inode *inode, struct inode *h_inode)
  3379. +{
  3380. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
  3381. + inode->i_blksize = h_inode->i_blksize;
  3382. +#endif
  3383. +}
  3384. +
  3385. +void au_cpup_attr_timesizes(struct inode *inode);
  3386. +void au_cpup_attr_nlink(struct inode *inode);
  3387. +void au_cpup_attr_changable(struct inode *inode);
  3388. +void au_cpup_igen(struct inode *inode, struct inode *h_inode);
  3389. +void au_cpup_attr_all(struct inode *inode);
  3390. +
  3391. +#define CPUP_DTIME 1 // do dtime_store/revert
  3392. +// todo: remove this
  3393. +#define CPUP_LOCKED_GHDIR 2 // grand parent hidden dir is locked
  3394. +unsigned int au_flags_cpup(unsigned int init, struct dentry *parent);
  3395. +
  3396. +int cpup_single(struct dentry *dentry, aufs_bindex_t bdst, aufs_bindex_t bsrc,
  3397. + loff_t len, unsigned int flags);
  3398. +int sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
  3399. + aufs_bindex_t bsrc, loff_t len, unsigned int flags);
  3400. +int cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3401. + unsigned int flags);
  3402. +int sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
  3403. + unsigned int flags);
  3404. +
  3405. +int cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst, struct dentry *locked);
  3406. +int test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst,
  3407. + struct dentry *locked);
  3408. +
  3409. +/* keep timestamps when copyup */
  3410. +struct dtime {
  3411. + struct dentry *dt_dentry, *dt_h_dentry;
  3412. + struct timespec dt_atime, dt_mtime;
  3413. +};
  3414. +void dtime_store(struct dtime *dt, struct dentry *dentry,
  3415. + struct dentry *h_dentry);
  3416. +void dtime_revert(struct dtime *dt, int h_parent_is_locked);
  3417. +
  3418. +#endif /* __KERNEL__ */
  3419. +#endif /* __AUFS_CPUP_H__ */
  3420. diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c
  3421. new file mode 100755
  3422. index 0000000..6ec29d3
  3423. --- /dev/null
  3424. +++ b/fs/aufs/dcsub.c
  3425. @@ -0,0 +1,175 @@
  3426. +/*
  3427. + * Copyright (C) 2007 Junjiro Okajima
  3428. + *
  3429. + * This program, aufs is free software; you can redistribute it and/or modify
  3430. + * it under the terms of the GNU General Public License as published by
  3431. + * the Free Software Foundation; either version 2 of the License, or
  3432. + * (at your option) any later version.
  3433. + *
  3434. + * This program is distributed in the hope that it will be useful,
  3435. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3436. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3437. + * GNU General Public License for more details.
  3438. + *
  3439. + * You should have received a copy of the GNU General Public License
  3440. + * along with this program; if not, write to the Free Software
  3441. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3442. + */
  3443. +
  3444. +/* $Id: dcsub.c,v 1.3 2007/05/14 03:41:52 sfjro Exp $ */
  3445. +
  3446. +#include "aufs.h"
  3447. +
  3448. +static void au_dpage_free(struct au_dpage *dpage)
  3449. +{
  3450. + int i;
  3451. +
  3452. + TraceEnter();
  3453. + DEBUG_ON(!dpage);
  3454. +
  3455. + for (i = 0; i < dpage->ndentry; i++)
  3456. + dput(dpage->dentries[i]);
  3457. + free_page((unsigned long)dpage->dentries);
  3458. +}
  3459. +
  3460. +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
  3461. +{
  3462. + int err;
  3463. + void *p;
  3464. +
  3465. + TraceEnter();
  3466. +
  3467. + err = -ENOMEM;
  3468. + dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
  3469. + if (unlikely(!dpages->dpages))
  3470. + goto out;
  3471. + p = (void*)__get_free_page(gfp);
  3472. + if (unlikely(!p))
  3473. + goto out_dpages;
  3474. + dpages->dpages[0].ndentry = 0;
  3475. + dpages->dpages[0].dentries = p;
  3476. + dpages->ndpage = 1;
  3477. + return 0; /* success */
  3478. +
  3479. + out_dpages:
  3480. + kfree(dpages->dpages);
  3481. + out:
  3482. + TraceErr(err);
  3483. + return err;
  3484. +}
  3485. +
  3486. +void au_dpages_free(struct au_dcsub_pages *dpages)
  3487. +{
  3488. + int i;
  3489. +
  3490. + TraceEnter();
  3491. +
  3492. + for (i = 0; i < dpages->ndpage; i++)
  3493. + au_dpage_free(dpages->dpages + i);
  3494. + kfree(dpages->dpages);
  3495. +}
  3496. +
  3497. +static int au_dpages_append(struct au_dcsub_pages *dpages,
  3498. + struct dentry *dentry, gfp_t gfp)
  3499. +{
  3500. + int err, sz;
  3501. + struct au_dpage *dpage;
  3502. + void *p;
  3503. +
  3504. + //TraceEnter();
  3505. +
  3506. + dpage = dpages->dpages + dpages->ndpage - 1;
  3507. + DEBUG_ON(!dpage);
  3508. + sz = PAGE_SIZE/sizeof(dentry);
  3509. + if (unlikely(dpage->ndentry >= sz)) {
  3510. + LKTRLabel(new dpage);
  3511. + err = -ENOMEM;
  3512. + sz = dpages->ndpage * sizeof(*dpages->dpages);
  3513. + p = au_kzrealloc(dpages->dpages, sz,
  3514. + sz + sizeof(*dpages->dpages), gfp);
  3515. + if (unlikely(!p))
  3516. + goto out;
  3517. + dpage = dpages->dpages + dpages->ndpage;
  3518. + p = (void*)__get_free_page(gfp);
  3519. + if (unlikely(!p))
  3520. + goto out;
  3521. + dpage->ndentry = 0;
  3522. + dpage->dentries = p;
  3523. + dpages->ndpage++;
  3524. + }
  3525. +
  3526. + dpage->dentries[dpage->ndentry++] = dget(dentry);
  3527. + return 0; /* success */
  3528. +
  3529. + out:
  3530. + //TraceErr(err);
  3531. + return err;
  3532. +}
  3533. +
  3534. +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
  3535. + au_dpages_test test, void *arg)
  3536. +{
  3537. + int err;
  3538. + struct dentry *this_parent = root;
  3539. + struct list_head *next;
  3540. + struct super_block *sb = root->d_sb;
  3541. +
  3542. + TraceEnter();
  3543. +
  3544. + err = 0;
  3545. + spin_lock(&dcache_lock);
  3546. + repeat:
  3547. + next = this_parent->d_subdirs.next;
  3548. + resume:
  3549. + if (this_parent->d_sb == sb
  3550. + && !IS_ROOT(this_parent)
  3551. + && atomic_read(&this_parent->d_count)
  3552. + && this_parent->d_inode
  3553. + && (!test || test(this_parent, arg))) {
  3554. + err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
  3555. + if (unlikely(err))
  3556. + goto out;
  3557. + }
  3558. +
  3559. + while (next != &this_parent->d_subdirs) {
  3560. + struct list_head *tmp = next;
  3561. + struct dentry *dentry = list_entry(tmp, struct dentry, D_CHILD);
  3562. + next = tmp->next;
  3563. + if (unlikely(/*d_unhashed(dentry) || */!dentry->d_inode))
  3564. + continue;
  3565. + if (!list_empty(&dentry->d_subdirs)) {
  3566. + this_parent = dentry;
  3567. + goto repeat;
  3568. + }
  3569. + if (dentry->d_sb == sb
  3570. + && atomic_read(&dentry->d_count)
  3571. + && (!test || test(dentry, arg))) {
  3572. + err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
  3573. + if (unlikely(err))
  3574. + goto out;
  3575. + }
  3576. + }
  3577. +
  3578. + if (this_parent != root) {
  3579. + next = this_parent->D_CHILD.next;
  3580. + this_parent = this_parent->d_parent;
  3581. + goto resume;
  3582. + }
  3583. + out:
  3584. + spin_unlock(&dcache_lock);
  3585. +#if 0
  3586. + if (!err) {
  3587. + int i, j;
  3588. + j = 0;
  3589. + for (i = 0; i < dpages->ndpage; i++) {
  3590. + if ((dpages->dpages + i)->ndentry)
  3591. + Dbg("%d: %d\n", i, (dpages->dpages + i)->ndentry);
  3592. + j += (dpages->dpages + i)->ndentry;
  3593. + }
  3594. + if (j)
  3595. + Dbg("ndpage %d, %d\n", dpages->ndpage, j);
  3596. + }
  3597. +#endif
  3598. + TraceErr(err);
  3599. + return err;
  3600. +}
  3601. diff --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h
  3602. new file mode 100755
  3603. index 0000000..0ba034b
  3604. --- /dev/null
  3605. +++ b/fs/aufs/dcsub.h
  3606. @@ -0,0 +1,47 @@
  3607. +/*
  3608. + * Copyright (C) 2007 Junjiro Okajima
  3609. + *
  3610. + * This program, aufs is free software; you can redistribute it and/or modify
  3611. + * it under the terms of the GNU General Public License as published by
  3612. + * the Free Software Foundation; either version 2 of the License, or
  3613. + * (at your option) any later version.
  3614. + *
  3615. + * This program is distributed in the hope that it will be useful,
  3616. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3617. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3618. + * GNU General Public License for more details.
  3619. + *
  3620. + * You should have received a copy of the GNU General Public License
  3621. + * along with this program; if not, write to the Free Software
  3622. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3623. + */
  3624. +
  3625. +/* $Id: dcsub.h,v 1.2 2007/05/14 03:41:52 sfjro Exp $ */
  3626. +
  3627. +#ifndef __AUFS_DCSUB_H__
  3628. +#define __AUFS_DCSUB_H__
  3629. +
  3630. +#ifdef __KERNEL__
  3631. +
  3632. +#include <linux/dcache.h>
  3633. +
  3634. +struct au_dpage {
  3635. + int ndentry;
  3636. + struct dentry **dentries;
  3637. +};
  3638. +
  3639. +struct au_dcsub_pages {
  3640. + int ndpage;
  3641. + struct au_dpage *dpages;
  3642. +};
  3643. +
  3644. +/* ---------------------------------------------------------------------- */
  3645. +
  3646. +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
  3647. +void au_dpages_free(struct au_dcsub_pages *dpages);
  3648. +typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
  3649. +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
  3650. + au_dpages_test test, void *arg);
  3651. +
  3652. +#endif /* __KERNEL__ */
  3653. +#endif /* __AUFS_DCSUB_H__ */
  3654. diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c
  3655. new file mode 100755
  3656. index 0000000..99d158b
  3657. --- /dev/null
  3658. +++ b/fs/aufs/debug.c
  3659. @@ -0,0 +1,262 @@
  3660. +/*
  3661. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  3662. + *
  3663. + * This program, aufs is free software; you can redistribute it and/or modify
  3664. + * it under the terms of the GNU General Public License as published by
  3665. + * the Free Software Foundation; either version 2 of the License, or
  3666. + * (at your option) any later version.
  3667. + *
  3668. + * This program is distributed in the hope that it will be useful,
  3669. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3670. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3671. + * GNU General Public License for more details.
  3672. + *
  3673. + * You should have received a copy of the GNU General Public License
  3674. + * along with this program; if not, write to the Free Software
  3675. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3676. + */
  3677. +
  3678. +/* $Id: debug.c,v 1.27 2007/04/30 05:48:23 sfjro Exp $ */
  3679. +
  3680. +#include "aufs.h"
  3681. +
  3682. +atomic_t aufs_cond = ATOMIC_INIT(0);
  3683. +
  3684. +#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
  3685. +#define dpri(fmt, arg...) \
  3686. + do {if (LktrCond) printk(KERN_DEBUG fmt, ##arg);} while (0)
  3687. +#else
  3688. +#define dpri(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
  3689. +#endif
  3690. +
  3691. +/* ---------------------------------------------------------------------- */
  3692. +
  3693. +void au_dpri_whlist(struct aufs_nhash *whlist)
  3694. +{
  3695. + int i;
  3696. + struct hlist_head *head;
  3697. + struct aufs_wh *tpos;
  3698. + struct hlist_node *pos;
  3699. +
  3700. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  3701. + head = whlist->heads + i;
  3702. + hlist_for_each_entry(tpos, pos, head, wh_hash)
  3703. + dpri("b%d, %.*s, %d\n",
  3704. + tpos->wh_bindex,
  3705. + tpos->wh_str.len, tpos->wh_str.name,
  3706. + tpos->wh_str.len);
  3707. + }
  3708. +}
  3709. +
  3710. +void au_dpri_vdir(struct aufs_vdir *vdir)
  3711. +{
  3712. + int i;
  3713. + union aufs_deblk_p p;
  3714. + unsigned char *o;
  3715. +
  3716. + if (!vdir || IS_ERR(vdir)) {
  3717. + dpri("err %ld\n", PTR_ERR(vdir));
  3718. + return;
  3719. + }
  3720. +
  3721. + dpri("nblk %d, deblk %p %d, last{%d, %p}, ver %lu\n",
  3722. + vdir->vd_nblk, vdir->vd_deblk, ksize(vdir->vd_deblk),
  3723. + vdir->vd_last.i, vdir->vd_last.p.p, vdir->vd_version);
  3724. + for (i = 0; i < vdir->vd_nblk; i++) {
  3725. + p.deblk = vdir->vd_deblk[i];
  3726. + o = p.p;
  3727. + dpri("[%d]: %p %d\n", i, o, ksize(o));
  3728. +#if 0 // verbose
  3729. + int j;
  3730. + for (j = 0; j < 8; j++) {
  3731. + dpri("%p(+%d) {%02x %02x %02x %02x %02x %02x %02x %02x "
  3732. + "%02x %02x %02x %02x %02x %02x %02x %02x}\n",
  3733. + p.p, p.p - o,
  3734. + p.p[0], p.p[1], p.p[2], p.p[3],
  3735. + p.p[4], p.p[5], p.p[6], p.p[7],
  3736. + p.p[8], p.p[9], p.p[10], p.p[11],
  3737. + p.p[12], p.p[13], p.p[14], p.p[15]);
  3738. + p.p += 16;
  3739. + }
  3740. +#endif
  3741. + }
  3742. +}
  3743. +
  3744. +static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode)
  3745. +{
  3746. + if (!inode || IS_ERR(inode)) {
  3747. + dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
  3748. + return -1;
  3749. + }
  3750. +
  3751. + /* the type of i_blocks depends upon CONFIG_LSF */
  3752. + BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
  3753. + && sizeof(inode->i_blocks) != sizeof(u64));
  3754. + dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %Lu, blk %Lu,"
  3755. + " ct %Ld, np %lu, st 0x%lx, g %x\n",
  3756. + bindex,
  3757. + inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
  3758. + atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
  3759. + i_size_read(inode), (u64)inode->i_blocks,
  3760. + timespec_to_ns(&inode->i_ctime) & 0x0ffff,
  3761. + inode->i_mapping ? inode->i_mapping->nrpages : 0,
  3762. + inode->i_state, inode->i_generation);
  3763. + return 0;
  3764. +}
  3765. +
  3766. +void au_dpri_inode(struct inode *inode)
  3767. +{
  3768. + struct aufs_iinfo *iinfo;
  3769. + aufs_bindex_t bindex;
  3770. + int err;
  3771. +
  3772. + err = do_pri_inode(-1, inode);
  3773. + if (err || !au_is_aufs(inode->i_sb))
  3774. + return;
  3775. +
  3776. + iinfo = itoii(inode);
  3777. + if (!iinfo)
  3778. + return;
  3779. + dpri("i-1: bstart %d, bend %d, gen %d\n",
  3780. + iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
  3781. + if (iinfo->ii_bstart < 0)
  3782. + return;
  3783. + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
  3784. + do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode);
  3785. +}
  3786. +
  3787. +static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
  3788. +{
  3789. + if (!dentry || IS_ERR(dentry)) {
  3790. + dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
  3791. + return -1;
  3792. + }
  3793. + dpri("d%d: %.*s/%.*s, %s, cnt %d, flags 0x%x\n",
  3794. + bindex,
  3795. + DLNPair(dentry->d_parent), DLNPair(dentry),
  3796. + dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
  3797. + atomic_read(&dentry->d_count), dentry->d_flags);
  3798. + do_pri_inode(bindex, dentry->d_inode);
  3799. + return 0;
  3800. +}
  3801. +
  3802. +void au_dpri_dentry(struct dentry *dentry)
  3803. +{
  3804. + struct aufs_dinfo *dinfo;
  3805. + aufs_bindex_t bindex;
  3806. + int err;
  3807. +
  3808. + err = do_pri_dentry(-1, dentry);
  3809. + if (err || !au_is_aufs(dentry->d_sb))
  3810. + return;
  3811. +
  3812. + dinfo = dtodi(dentry);
  3813. + if (!dinfo)
  3814. + return;
  3815. + dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
  3816. + dinfo->di_bstart, dinfo->di_bend,
  3817. + dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
  3818. + if (dinfo->di_bstart < 0)
  3819. + return;
  3820. + for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
  3821. + do_pri_dentry(bindex, dinfo->di_hdentry[0 + bindex].hd_dentry);
  3822. +}
  3823. +
  3824. +static int do_pri_file(aufs_bindex_t bindex, struct file *file)
  3825. +{
  3826. + char a[32];
  3827. +
  3828. + if (!file || IS_ERR(file)) {
  3829. + dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
  3830. + return -1;
  3831. + }
  3832. + a[0] = 0;
  3833. + if (bindex == -1 && ftofi(file))
  3834. + snprintf(a, sizeof(a), ", mmapped %d", au_is_mmapped(file));
  3835. + dpri("f%d: mode 0x%x, flags 0%o, cnt %d, pos %Lu%s\n",
  3836. + bindex, file->f_mode, file->f_flags, file_count(file),
  3837. + file->f_pos, a);
  3838. + do_pri_dentry(bindex, file->f_dentry);
  3839. + return 0;
  3840. +}
  3841. +
  3842. +void au_dpri_file(struct file *file)
  3843. +{
  3844. + struct aufs_finfo *finfo;
  3845. + aufs_bindex_t bindex;
  3846. + int err;
  3847. +
  3848. + err = do_pri_file(-1, file);
  3849. + if (err || !file->f_dentry || !au_is_aufs(file->f_dentry->d_sb))
  3850. + return;
  3851. +
  3852. + finfo = ftofi(file);
  3853. + if (!finfo)
  3854. + return;
  3855. + if (finfo->fi_bstart < 0)
  3856. + return;
  3857. + for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
  3858. + struct aufs_hfile *hf;
  3859. + //dpri("bindex %d\n", bindex);
  3860. + hf = finfo->fi_hfile + bindex;
  3861. + do_pri_file(bindex, hf ? hf->hf_file : NULL);
  3862. + }
  3863. +}
  3864. +
  3865. +static int do_pri_br(aufs_bindex_t bindex, struct aufs_branch *br)
  3866. +{
  3867. + struct vfsmount *mnt;
  3868. + struct super_block *sb;
  3869. +
  3870. + if (!br || IS_ERR(br)
  3871. + || !(mnt = br->br_mnt) || IS_ERR(mnt)
  3872. + || !(sb = mnt->mnt_sb) || IS_ERR(sb)) {
  3873. + dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
  3874. + return -1;
  3875. + }
  3876. +
  3877. + dpri("s%d: {perm 0x%x, cnt %d}, "
  3878. + "%s, flags 0x%lx, cnt(BIAS) %d, active %d, xino %p %p\n",
  3879. + bindex, br->br_perm, br_count(br),
  3880. + au_sbtype(sb), sb->s_flags, sb->s_count - S_BIAS,
  3881. + atomic_read(&sb->s_active), br->br_xino,
  3882. + br->br_xino ? br->br_xino->f_dentry : NULL);
  3883. + return 0;
  3884. +}
  3885. +
  3886. +void au_dpri_sb(struct super_block *sb)
  3887. +{
  3888. + struct aufs_sbinfo *sbinfo;
  3889. + aufs_bindex_t bindex;
  3890. + int err;
  3891. + struct vfsmount mnt = {.mnt_sb = sb};
  3892. + struct aufs_branch fake = {
  3893. + .br_perm = 0,
  3894. + .br_mnt = &mnt,
  3895. + .br_count = ATOMIC_INIT(0),
  3896. + .br_xino = NULL
  3897. + };
  3898. +
  3899. + atomic_set(&fake.br_count, 0);
  3900. + err = do_pri_br(-1, &fake);
  3901. + dpri("dev 0x%x\n", sb->s_dev);
  3902. + if (err || !au_is_aufs(sb))
  3903. + return;
  3904. +
  3905. + sbinfo = stosi(sb);
  3906. + if (!sbinfo)
  3907. + return;
  3908. + for (bindex = 0; bindex <= sbinfo->si_bend; bindex++) {
  3909. + //dpri("bindex %d\n", bindex);
  3910. + do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
  3911. + }
  3912. +}
  3913. +
  3914. +/* ---------------------------------------------------------------------- */
  3915. +
  3916. +void DbgSleep(int sec)
  3917. +{
  3918. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  3919. + Dbg("sleep %d sec\n", sec);
  3920. + wait_event_timeout(wq, 0, sec * HZ);
  3921. +}
  3922. diff --git a/fs/aufs/debug.h b/fs/aufs/debug.h
  3923. new file mode 100755
  3924. index 0000000..53f5f6a
  3925. --- /dev/null
  3926. +++ b/fs/aufs/debug.h
  3927. @@ -0,0 +1,129 @@
  3928. +/*
  3929. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  3930. + *
  3931. + * This program, aufs is free software; you can redistribute it and/or modify
  3932. + * it under the terms of the GNU General Public License as published by
  3933. + * the Free Software Foundation; either version 2 of the License, or
  3934. + * (at your option) any later version.
  3935. + *
  3936. + * This program is distributed in the hope that it will be useful,
  3937. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3938. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  3939. + * GNU General Public License for more details.
  3940. + *
  3941. + * You should have received a copy of the GNU General Public License
  3942. + * along with this program; if not, write to the Free Software
  3943. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  3944. + */
  3945. +
  3946. +/* $Id: debug.h,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
  3947. +
  3948. +#ifndef __AUFS_DEBUG_H__
  3949. +#define __AUFS_DEBUG_H__
  3950. +
  3951. +#ifdef __KERNEL__
  3952. +
  3953. +#include <linux/fs.h>
  3954. +
  3955. +#ifdef CONFIG_AUFS_DEBUG
  3956. +#define DEBUG_ON(a) BUG_ON(a)
  3957. +extern atomic_t aufs_cond;
  3958. +#define au_debug_on() atomic_inc(&aufs_cond)
  3959. +#define au_debug_off() atomic_dec(&aufs_cond)
  3960. +#define au_is_debug() atomic_read(&aufs_cond)
  3961. +#else
  3962. +#define DEBUG_ON(a) /* */
  3963. +#define au_debug_on() /* */
  3964. +#define au_debug_off() /* */
  3965. +#define au_is_debug() 0
  3966. +#endif
  3967. +
  3968. +#define MtxMustLock(mtx) DEBUG_ON(!mutex_is_locked(mtx))
  3969. +
  3970. +/* ---------------------------------------------------------------------- */
  3971. +
  3972. +/* debug print */
  3973. +#if defined(CONFIG_LKTR) || defined(CONFIG_LKTR_MODULE)
  3974. +#include <linux/lktr.h>
  3975. +#ifdef CONFIG_AUFS_DEBUG
  3976. +#undef LktrCond
  3977. +#define LktrCond unlikely((lktr_cond && lktr_cond()) || au_is_debug())
  3978. +#endif
  3979. +#else
  3980. +#define LktrCond au_is_debug()
  3981. +#define LKTRDumpVma(pre, vma, suf) /* */
  3982. +#define LKTRDumpStack() /* */
  3983. +#define LKTRTrace(fmt, args...) do { \
  3984. + if (LktrCond) \
  3985. + Dbg(fmt, ##args); \
  3986. +} while (0)
  3987. +#define LKTRLabel(label) LKTRTrace("%s\n", #label)
  3988. +#endif /* CONFIG_LKTR */
  3989. +
  3990. +#define TraceErr(e) do { \
  3991. + if (unlikely((e) < 0)) \
  3992. + LKTRTrace("err %d\n", (int)(e)); \
  3993. +} while (0)
  3994. +#define TraceErrPtr(p) do { \
  3995. + if (IS_ERR(p)) \
  3996. + LKTRTrace("err %ld\n", PTR_ERR(p)); \
  3997. +} while (0)
  3998. +#define TraceEnter() LKTRLabel(enter)
  3999. +
  4000. +/* dirty macros for debug print, use with "%.*s" and caution */
  4001. +#define LNPair(qstr) (qstr)->len,(qstr)->name
  4002. +#define DLNPair(d) LNPair(&(d)->d_name)
  4003. +
  4004. +/* ---------------------------------------------------------------------- */
  4005. +
  4006. +#define Dpri(lvl, fmt, arg...) \
  4007. + printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
  4008. + __func__, __LINE__, current->comm, current->pid, ##arg)
  4009. +#define Dbg(fmt, arg...) Dpri(KERN_DEBUG, fmt, ##arg)
  4010. +#define Warn(fmt, arg...) Dpri(KERN_WARNING, fmt, ##arg)
  4011. +#define Warn1(fmt, arg...) do { \
  4012. + static unsigned char c; \
  4013. + if (!c++) Warn(fmt, ##arg); \
  4014. + } while (0)
  4015. +#define Err(fmt, arg...) Dpri(KERN_ERR, fmt, ##arg)
  4016. +#define Err1(fmt, arg...) do { \
  4017. + static unsigned char c; \
  4018. + if (!c++) Err(fmt, ##arg); \
  4019. + } while (0)
  4020. +#define IOErr(fmt, arg...) Err("I/O Error, " fmt, ##arg)
  4021. +#define IOErr1(fmt, arg...) do { \
  4022. + static unsigned char c; \
  4023. + if (!c++) IOErr(fmt, ##arg); \
  4024. + } while (0)
  4025. +#define IOErrWhck(fmt, arg...) Err("I/O Error, try whck. " fmt, ##arg)
  4026. +
  4027. +/* ---------------------------------------------------------------------- */
  4028. +
  4029. +#ifdef CONFIG_AUFS_DEBUG
  4030. +struct aufs_nhash;
  4031. +void au_dpri_whlist(struct aufs_nhash *whlist);
  4032. +struct aufs_vdir;
  4033. +void au_dpri_vdir(struct aufs_vdir *vdir);
  4034. +void au_dpri_inode(struct inode *inode);
  4035. +void au_dpri_dentry(struct dentry *dentry);
  4036. +void au_dpri_file(struct file *filp);
  4037. +void au_dpri_sb(struct super_block *sb);
  4038. +#define DbgWhlist(w) do{LKTRTrace(#w "\n"); au_dpri_whlist(w);}while(0)
  4039. +#define DbgVdir(v) do{LKTRTrace(#v "\n"); au_dpri_vdir(v);}while(0)
  4040. +#define DbgInode(i) do{LKTRTrace(#i "\n"); au_dpri_inode(i);}while(0)
  4041. +#define DbgDentry(d) do{LKTRTrace(#d "\n"); au_dpri_dentry(d);}while(0)
  4042. +#define DbgFile(f) do{LKTRTrace(#f "\n"); au_dpri_file(f);}while(0)
  4043. +#define DbgSb(sb) do{LKTRTrace(#sb "\n"); au_dpri_sb(sb);}while(0)
  4044. +void DbgSleep(int sec);
  4045. +#else
  4046. +#define DbgWhlist(w) /* */
  4047. +#define DbgVdir(v) /* */
  4048. +#define DbgInode(i) /* */
  4049. +#define DbgDentry(d) /* */
  4050. +#define DbgFile(f) /* */
  4051. +#define DbgSb(sb) /* */
  4052. +#define DbgSleep(sec) /* */
  4053. +#endif
  4054. +
  4055. +#endif /* __KERNEL__ */
  4056. +#endif /* __AUFS_DEBUG_H__ */
  4057. diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c
  4058. new file mode 100755
  4059. index 0000000..2acb89b
  4060. --- /dev/null
  4061. +++ b/fs/aufs/dentry.c
  4062. @@ -0,0 +1,946 @@
  4063. +/*
  4064. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  4065. + *
  4066. + * This program, aufs is free software; you can redistribute it and/or modify
  4067. + * it under the terms of the GNU General Public License as published by
  4068. + * the Free Software Foundation; either version 2 of the License, or
  4069. + * (at your option) any later version.
  4070. + *
  4071. + * This program is distributed in the hope that it will be useful,
  4072. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  4073. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  4074. + * GNU General Public License for more details.
  4075. + *
  4076. + * You should have received a copy of the GNU General Public License
  4077. + * along with this program; if not, write to the Free Software
  4078. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  4079. + */
  4080. +
  4081. +/* $Id: dentry.c,v 1.41 2007/05/14 03:38:38 sfjro Exp $ */
  4082. +
  4083. +//#include <linux/fs.h>
  4084. +//#include <linux/namei.h>
  4085. +#include "aufs.h"
  4086. +
  4087. +#ifdef CONFIG_AUFS_LHASH_PATCH
  4088. +
  4089. +#ifdef CONFIG_AUFS_DLGT
  4090. +struct lookup_hash_args {
  4091. + struct dentry **errp;
  4092. + struct qstr *name;
  4093. + struct dentry *base;
  4094. + struct nameidata *nd;
  4095. +};
  4096. +
  4097. +static void call_lookup_hash(void *args)
  4098. +{
  4099. + struct lookup_hash_args *a = args;
  4100. + *a->errp = __lookup_hash(a->name, a->base, a->nd);
  4101. +}
  4102. +#endif /* CONFIG_AUFS_DLGT */
  4103. +
  4104. +static struct dentry *lkup_hash(const char *name, struct dentry *parent,
  4105. + int len, struct lkup_args *lkup)
  4106. +{
  4107. + struct dentry *dentry;
  4108. + char *p;
  4109. + unsigned long hash;
  4110. + struct qstr this;
  4111. + unsigned int c;
  4112. + struct nameidata tmp_nd;
  4113. +
  4114. + dentry = ERR_PTR(-EACCES);
  4115. + this.name = name;
  4116. + this.len = len;
  4117. + if (unlikely(!len))
  4118. + goto out;
  4119. +
  4120. + p = (void*)name;
  4121. + hash = init_name_hash();
  4122. + while (len--) {
  4123. + c = *p++;
  4124. + if (unlikely(c == '/' || c == '\0'))
  4125. + goto out;
  4126. + hash = partial_name_hash(c, hash);
  4127. + }
  4128. + this.hash = end_name_hash(hash);
  4129. +
  4130. + memset(&tmp_nd, 0, sizeof(tmp_nd));
  4131. + tmp_nd.dentry = dget(parent);
  4132. + tmp_nd.mnt = mntget(lkup->nfsmnt);
  4133. +#ifndef CONFIG_AUFS_DLGT
  4134. + dentry = __lookup_hash(&this, parent, &tmp_nd);
  4135. +#else
  4136. + if (!lkup->dlgt)
  4137. + dentry = __lookup_hash(&this, parent, &tmp_nd);
  4138. + else {
  4139. + struct lookup_hash_args args = {
  4140. + .errp = &dentry,
  4141. + .name = &this,
  4142. + .base = parent,
  4143. + .nd = &tmp_nd
  4144. + };
  4145. + au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1);
  4146. + }
  4147. +#endif
  4148. + path_release(&tmp_nd);
  4149. +
  4150. + out:
  4151. + TraceErrPtr(dentry);
  4152. + return dentry;
  4153. +}
  4154. +#elif defined(CONFIG_AUFS_DLGT)
  4155. +static struct dentry *lkup_hash(const char *name, struct dentry *parent,
  4156. + int len, struct lkup_args *lkup)
  4157. +{
  4158. + return ERR_PTR(-ENOSYS);
  4159. +}
  4160. +#endif
  4161. +
  4162. +#ifdef CONFIG_AUFS_DLGT
  4163. +struct lookup_one_len_args {
  4164. + struct dentry **errp;
  4165. + const char *name;
  4166. + struct dentry *parent;
  4167. + int len;
  4168. +};
  4169. +
  4170. +static void call_lookup_one_len(void *args)
  4171. +{
  4172. + struct lookup_one_len_args *a = args;
  4173. + *a->errp = lookup_one_len(a->name, a->parent, a->len);
  4174. +}
  4175. +#endif /* CONFIG_AUFS_DLGT */
  4176. +
  4177. +#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
  4178. +/* cf. lookup_one_len() in linux/fs/namei.c */
  4179. +struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
  4180. + struct lkup_args *lkup)
  4181. +{
  4182. + struct dentry *dentry;
  4183. +
  4184. + LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n",
  4185. + DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt);
  4186. +
  4187. + if (!lkup->nfsmnt) {
  4188. +#ifndef CONFIG_AUFS_DLGT
  4189. + dentry = lookup_one_len(name, parent, len);
  4190. +#else
  4191. + if (!lkup->dlgt)
  4192. + dentry = lookup_one_len(name, parent, len);
  4193. + else {
  4194. + struct lookup_one_len_args args = {
  4195. + .errp = &dentry,
  4196. + .name = name,
  4197. + .parent = parent,
  4198. + .len = len
  4199. + };
  4200. + au_wkq_wait(call_lookup_one_len, &args, /*dlgt*/1);
  4201. + }
  4202. +#endif
  4203. + } else
  4204. + dentry = lkup_hash(name, parent, len, lkup);
  4205. +
  4206. + TraceErrPtr(dentry);
  4207. + return dentry;
  4208. +}
  4209. +#endif
  4210. +
  4211. +struct lkup_one_args {
  4212. + struct dentry **errp;
  4213. + const char *name;
  4214. + struct dentry *parent;
  4215. + int len;
  4216. + struct lkup_args *lkup;
  4217. +};
  4218. +
  4219. +static void call_lkup_one(void *args)
  4220. +{
  4221. + struct lkup_one_args *a = args;
  4222. + *a->errp = lkup_one(a->name, a->parent, a->len, a->lkup);
  4223. +}
  4224. +
  4225. +/*
  4226. + * returns positive/negative dentry, NULL or an error.
  4227. + * NULL means whiteout-ed or not-found.
  4228. + */
  4229. +static struct dentry *do_lookup(struct dentry *hidden_parent,
  4230. + struct dentry *dentry, aufs_bindex_t bindex,
  4231. + struct qstr *wh_name, int allow_neg,
  4232. + mode_t type, int dlgt)
  4233. +{
  4234. + struct dentry *hidden_dentry;
  4235. + int wh_found, wh_able, opq;
  4236. + struct inode *hidden_dir, *hidden_inode;
  4237. + struct qstr *name;
  4238. + struct super_block *sb;
  4239. + struct lkup_args lkup = {.dlgt = dlgt};
  4240. +
  4241. + LKTRTrace("%.*s/%.*s, b%d, allow_neg %d, type 0%o, dlgt %d\n",
  4242. + DLNPair(hidden_parent), DLNPair(dentry), bindex, allow_neg,
  4243. + type, dlgt);
  4244. + DEBUG_ON(IS_ROOT(dentry));
  4245. + hidden_dir = hidden_parent->d_inode;
  4246. + IMustLock(hidden_dir);
  4247. +
  4248. + wh_found = 0;
  4249. + sb = dentry->d_sb;
  4250. + wh_able = sbr_is_whable(sb, bindex);
  4251. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  4252. + name = &dentry->d_name;
  4253. + if (unlikely(wh_able)) {
  4254. +#if 0 //def CONFIG_AUFS_ROBR
  4255. + if (strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
  4256. + wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0,
  4257. + &lkup);
  4258. + else
  4259. + wh_found = -EPERM;
  4260. +#else
  4261. + wh_found = is_wh(hidden_parent, wh_name, /*try_sio*/0, &lkup);
  4262. +#endif
  4263. + }
  4264. + //if (LktrCond) wh_found = -1;
  4265. + hidden_dentry = ERR_PTR(wh_found);
  4266. + if (!wh_found)
  4267. + goto real_lookup;
  4268. + if (unlikely(wh_found < 0))
  4269. + goto out;
  4270. +
  4271. + /* We found a whiteout */
  4272. + //set_dbend(dentry, bindex);
  4273. + set_dbwh(dentry, bindex);
  4274. + if (!allow_neg)
  4275. + return NULL; /* success */
  4276. +
  4277. + real_lookup:
  4278. + // do not superio.
  4279. + hidden_dentry = lkup_one(name->name, hidden_parent, name->len, &lkup);
  4280. + //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
  4281. + if (IS_ERR(hidden_dentry))
  4282. + goto out;
  4283. + DEBUG_ON(d_unhashed(hidden_dentry));
  4284. + hidden_inode = hidden_dentry->d_inode;
  4285. + if (!hidden_inode) {
  4286. + if (!allow_neg)
  4287. + goto out_neg;
  4288. + } else if (wh_found
  4289. + || (type && type != (hidden_inode->i_mode & S_IFMT)))
  4290. + goto out_neg;
  4291. +
  4292. + if (dbend(dentry) <= bindex)
  4293. + set_dbend(dentry, bindex);
  4294. + if (dbstart(dentry) == -1 || bindex < dbstart(dentry))
  4295. + set_dbstart(dentry, bindex);
  4296. + set_h_dptr(dentry, bindex, hidden_dentry);
  4297. +
  4298. + if (!hidden_inode || !S_ISDIR(hidden_inode->i_mode) || !wh_able)
  4299. + return hidden_dentry; /* success */
  4300. +
  4301. + hi_lock_child(hidden_inode);
  4302. + opq = is_diropq(hidden_dentry, &lkup);
  4303. + //if (LktrCond) opq = -1;
  4304. + i_unlock(hidden_inode);
  4305. + if (opq > 0)
  4306. + set_dbdiropq(dentry, bindex);
  4307. + else if (unlikely(opq < 0)) {
  4308. + set_h_dptr(dentry, bindex, NULL);
  4309. + hidden_dentry = ERR_PTR(opq);
  4310. + }
  4311. + goto out;
  4312. +
  4313. + out_neg:
  4314. + dput(hidden_dentry);
  4315. + hidden_dentry = NULL;
  4316. + out:
  4317. + TraceErrPtr(hidden_dentry);
  4318. + return hidden_dentry;
  4319. +}
  4320. +
  4321. +/*
  4322. + * returns the number of hidden positive dentries,
  4323. + * otherwise an error.
  4324. + */
  4325. +int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type)
  4326. +{
  4327. + int npositive, err, allow_neg, dlgt;
  4328. + struct dentry *parent;
  4329. + aufs_bindex_t bindex, btail;
  4330. + const struct qstr *name = &dentry->d_name;
  4331. + struct qstr whname;
  4332. + struct super_block *sb;
  4333. +
  4334. + LKTRTrace("%.*s, b%d, type 0%o\n", LNPair(name), bstart, type);
  4335. + DEBUG_ON(bstart < 0 || IS_ROOT(dentry));
  4336. + parent = dget_parent(dentry);
  4337. +
  4338. +#if 1 //ndef CONFIG_AUFS_ROBR
  4339. + err = -EPERM;
  4340. + if (unlikely(!strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
  4341. + goto out;
  4342. +#endif
  4343. +
  4344. + err = au_alloc_whname(name->name, name->len, &whname);
  4345. + //if (LktrCond) {au_free_whname(&whname); err = -1;}
  4346. + if (unlikely(err))
  4347. + goto out;
  4348. +
  4349. + sb = dentry->d_sb;
  4350. + dlgt = need_dlgt(sb);
  4351. + allow_neg = !type;
  4352. + npositive = 0;
  4353. + btail = dbtaildir(parent);
  4354. + for (bindex = bstart; bindex <= btail; bindex++) {
  4355. + struct dentry *hidden_parent, *hidden_dentry;
  4356. + struct inode *hidden_inode;
  4357. + struct inode *hidden_dir;
  4358. +
  4359. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  4360. + if (hidden_dentry) {
  4361. + if (hidden_dentry->d_inode)
  4362. + npositive++;
  4363. + if (type != S_IFDIR)
  4364. + break;
  4365. + continue;
  4366. + }
  4367. + hidden_parent = au_h_dptr_i(parent, bindex);
  4368. + if (!hidden_parent)
  4369. + continue;
  4370. + hidden_dir = hidden_parent->d_inode;
  4371. + if (!hidden_dir || !S_ISDIR(hidden_dir->i_mode))
  4372. + continue;
  4373. +
  4374. + hi_lock_parent(hidden_dir);
  4375. + hidden_dentry = do_lookup(hidden_parent, dentry, bindex,
  4376. + &whname, allow_neg, type, dlgt);
  4377. + // do not dput for testing
  4378. + //if (LktrCond) {hidden_dentry = ERR_PTR(-1);}
  4379. + i_unlock(hidden_dir);
  4380. + err = PTR_ERR(hidden_dentry);
  4381. + if (IS_ERR(hidden_dentry))
  4382. + goto out_wh;
  4383. + allow_neg = 0;
  4384. +
  4385. + if (dbwh(dentry) != -1)
  4386. + break;
  4387. + if (!hidden_dentry)
  4388. + continue;
  4389. + hidden_inode = hidden_dentry->d_inode;
  4390. + if (!hidden_inode)
  4391. + continue;
  4392. + npositive++;
  4393. + if (!type)
  4394. + type = hidden_inode->i_mode & S_IFMT;
  4395. + if (type != S_IFDIR)
  4396. + break;
  4397. + else if (dbdiropq(dentry) != -1)
  4398. + break;
  4399. + }
  4400. +
  4401. + if (npositive) {
  4402. + LKTRLabel(positive);
  4403. + au_update_dbstart(dentry);
  4404. + }
  4405. + err = npositive;
  4406. +
  4407. + out_wh:
  4408. + au_free_whname(&whname);
  4409. + out:
  4410. + dput(parent);
  4411. + TraceErr(err);
  4412. + return err;
  4413. +}
  4414. +
  4415. +struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
  4416. + struct lkup_args *lkup)
  4417. +{
  4418. + struct dentry *dentry;
  4419. +
  4420. + LKTRTrace("%.*s/%.*s\n", DLNPair(parent), len, name);
  4421. + IMustLock(parent->d_inode);
  4422. +
  4423. + if (!au_test_perm(parent->d_inode, MAY_EXEC, lkup->dlgt))
  4424. + dentry = lkup_one(name, parent, len, lkup);
  4425. + else {
  4426. + // ugly
  4427. + int dlgt = lkup->dlgt;
  4428. + struct lkup_one_args args = {
  4429. + .errp = &dentry,
  4430. + .name = name,
  4431. + .parent = parent,
  4432. + .len = len,
  4433. + .lkup = lkup
  4434. + };
  4435. +
  4436. + lkup->dlgt = 0;
  4437. + au_wkq_wait(call_lkup_one, &args, /*dlgt*/0);
  4438. + lkup->dlgt = dlgt;
  4439. + }
  4440. +
  4441. + TraceErrPtr(dentry);
  4442. + return dentry;
  4443. +}
  4444. +
  4445. +/*
  4446. + * lookup @dentry on @bindex which should be negative.
  4447. + */
  4448. +int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
  4449. +{
  4450. + int err;
  4451. + struct dentry *parent, *hidden_parent, *hidden_dentry;
  4452. + struct inode *hidden_dir;
  4453. + struct lkup_args lkup;
  4454. +
  4455. + LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
  4456. + parent = dget_parent(dentry);
  4457. + DEBUG_ON(!parent || !parent->d_inode
  4458. + || !S_ISDIR(parent->d_inode->i_mode));
  4459. + hidden_parent = au_h_dptr_i(parent, bindex);
  4460. + DEBUG_ON(!hidden_parent);
  4461. + hidden_dir = hidden_parent->d_inode;
  4462. + DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
  4463. + IMustLock(hidden_dir);
  4464. +
  4465. + lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bindex);
  4466. + lkup.dlgt = need_dlgt(dentry->d_sb);
  4467. + hidden_dentry = sio_lkup_one(dentry->d_name.name, hidden_parent,
  4468. + dentry->d_name.len, &lkup);
  4469. + //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
  4470. + err = PTR_ERR(hidden_dentry);
  4471. + if (IS_ERR(hidden_dentry))
  4472. + goto out;
  4473. + if (unlikely(hidden_dentry->d_inode)) {
  4474. + err = -EIO;
  4475. + IOErr("b%d %.*s should be negative.%s\n",
  4476. + bindex, DLNPair(hidden_dentry),
  4477. + au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY) ? "" :
  4478. + " Try udba=inotify.");
  4479. + dput(hidden_dentry);
  4480. + goto out;
  4481. + }
  4482. +
  4483. + if (bindex < dbstart(dentry))
  4484. + set_dbstart(dentry, bindex);
  4485. + if (dbend(dentry) < bindex)
  4486. + set_dbend(dentry, bindex);
  4487. + set_h_dptr(dentry, bindex, hidden_dentry);
  4488. + err = 0;
  4489. +
  4490. + out:
  4491. + dput(parent);
  4492. + TraceErr(err);
  4493. + return err;
  4494. +}
  4495. +
  4496. +/*
  4497. + * returns the number of found hidden positive dentries,
  4498. + * otherwise an error.
  4499. + */
  4500. +int au_refresh_hdentry(struct dentry *dentry, mode_t type)
  4501. +{
  4502. + int npositive, pgen, new_sz, sgen, dgen;
  4503. + struct aufs_dinfo *dinfo;
  4504. + struct super_block *sb;
  4505. + struct dentry *parent;
  4506. + aufs_bindex_t bindex, parent_bend, parent_bstart, bwh, bdiropq, bend;
  4507. + struct aufs_hdentry *p;
  4508. + //struct nameidata nd;
  4509. +
  4510. + LKTRTrace("%.*s, type 0%o\n", DLNPair(dentry), type);
  4511. + DiMustWriteLock(dentry);
  4512. + sb = dentry->d_sb;
  4513. + DEBUG_ON(IS_ROOT(dentry));
  4514. + parent = dget_parent(dentry);
  4515. + pgen = au_digen(parent);
  4516. + sgen = au_sigen(sb);
  4517. + dgen = au_digen(dentry);
  4518. + DEBUG_ON(pgen != sgen);
  4519. +
  4520. + npositive = -ENOMEM;
  4521. + new_sz = sizeof(*dinfo->di_hdentry) * (sbend(sb) + 1);
  4522. + dinfo = dtodi(dentry);
  4523. + p = au_kzrealloc(dinfo->di_hdentry, sizeof(*p) * (dinfo->di_bend + 1),
  4524. + new_sz, GFP_KERNEL);
  4525. + //p = NULL;
  4526. + if (unlikely(!p))
  4527. + goto out;
  4528. + dinfo->di_hdentry = p;
  4529. +
  4530. + bend = dinfo->di_bend;
  4531. + bwh = dinfo->di_bwh;
  4532. + bdiropq = dinfo->di_bdiropq;
  4533. + p += dinfo->di_bstart;
  4534. + for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
  4535. + struct dentry *hd, *hdp;
  4536. + struct aufs_hdentry tmp, *q;
  4537. + aufs_bindex_t new_bindex;
  4538. +
  4539. + hd = p->hd_dentry;
  4540. + if (!hd)
  4541. + continue;
  4542. + hdp = dget_parent(hd);
  4543. + if (hdp == au_h_dptr_i(parent, bindex)) {
  4544. + dput(hdp);
  4545. + continue;
  4546. + }
  4547. +
  4548. + new_bindex = au_find_dbindex(parent, hdp);
  4549. + dput(hdp);
  4550. + DEBUG_ON(new_bindex == bindex);
  4551. + if (dinfo->di_bwh == bindex)
  4552. + bwh = new_bindex;
  4553. + if (dinfo->di_bdiropq == bindex)
  4554. + bdiropq = new_bindex;
  4555. + if (new_bindex < 0) { // test here
  4556. + hdput(p);
  4557. + p->hd_dentry = NULL;
  4558. + continue;
  4559. + }
  4560. + /* swap two hidden dentries, and loop again */
  4561. + q = dinfo->di_hdentry + new_bindex;
  4562. + tmp = *q;
  4563. + *q = *p;
  4564. + *p = tmp;
  4565. + if (tmp.hd_dentry) {
  4566. + bindex--;
  4567. + p--;
  4568. + }
  4569. + }
  4570. +
  4571. + // test here
  4572. + dinfo->di_bwh = -1;
  4573. + if (unlikely(bwh != -1 && bwh <= sbend(sb) && sbr_is_whable(sb, bwh)))
  4574. + dinfo->di_bwh = bwh;
  4575. + dinfo->di_bdiropq = -1;
  4576. + if (unlikely(bdiropq != -1 && bdiropq <= sbend(sb)
  4577. + && sbr_is_whable(sb, bdiropq)))
  4578. + dinfo->di_bdiropq = bdiropq;
  4579. + parent_bend = dbend(parent);
  4580. + p = dinfo->di_hdentry;
  4581. + for (bindex = 0; bindex <= parent_bend; bindex++, p++)
  4582. + if (p->hd_dentry) {
  4583. + dinfo->di_bstart = bindex;
  4584. + break;
  4585. + }
  4586. + p = dinfo->di_hdentry + parent_bend;
  4587. + //for (bindex = parent_bend; bindex > dinfo->di_bstart; bindex--, p--)
  4588. + for (bindex = parent_bend; bindex >= 0; bindex--, p--)
  4589. + if (p->hd_dentry) {
  4590. + dinfo->di_bend = bindex;
  4591. + break;
  4592. + }
  4593. +
  4594. + npositive = 0;
  4595. + parent_bstart = dbstart(parent);
  4596. + if (type != S_IFDIR && dinfo->di_bstart == parent_bstart)
  4597. + goto out_dgen; /* success */
  4598. +
  4599. +#if 0
  4600. + nd.last_type = LAST_ROOT;
  4601. + nd.flags = LOOKUP_FOLLOW;
  4602. + nd.depth = 0;
  4603. + nd.mnt = mntget(??);
  4604. + nd.dentry = dget(parent);
  4605. +#endif
  4606. + npositive = lkup_dentry(dentry, parent_bstart, type);
  4607. + //if (LktrCond) npositive = -1;
  4608. + if (npositive < 0)
  4609. + goto out;
  4610. +
  4611. + out_dgen:
  4612. + au_update_digen(dentry);
  4613. + out:
  4614. + dput(parent);
  4615. + TraceErr(npositive);
  4616. + return npositive;
  4617. +}
  4618. +
  4619. +static int h_d_revalidate(struct dentry *dentry, struct nameidata *nd,
  4620. + int do_udba)
  4621. +{
  4622. + int err, plus, locked, unhashed, is_root, h_plus, is_nfs;
  4623. + struct nameidata fake_nd, *p;
  4624. + aufs_bindex_t bindex, btail, bstart, ibs, ibe;
  4625. + struct super_block *sb;
  4626. + struct inode *inode, *first, *h_inode, *h_cached_inode;
  4627. + umode_t mode, h_mode;
  4628. + struct dentry *h_dentry;
  4629. + int (*reval)(struct dentry *, struct nameidata *);
  4630. + struct qstr *name;
  4631. +
  4632. + LKTRTrace("%.*s\n", DLNPair(dentry));
  4633. + inode = dentry->d_inode;
  4634. + DEBUG_ON(inode && au_digen(dentry) != au_iigen(inode));
  4635. + //DbgDentry(dentry);
  4636. + //DbgInode(inode);
  4637. +
  4638. + err = 0;
  4639. + sb = dentry->d_sb;
  4640. + plus = 0;
  4641. + mode = 0;
  4642. + first = NULL;
  4643. + ibs = ibe = -1;
  4644. + unhashed = d_unhashed(dentry);
  4645. + is_root = IS_ROOT(dentry);
  4646. + name = &dentry->d_name;
  4647. +
  4648. + /*
  4649. + * Theoretically, REVAL test should be unnecessary in case of INOTIFY.
  4650. + * But inotify doesn't fire some necessary events,
  4651. + * IN_ATTRIB for atime/nlink/pageio
  4652. + * IN_DELETE for NFS dentry
  4653. + * Let's do REVAL test too.
  4654. + */
  4655. + if (do_udba && inode) {
  4656. + mode = (inode->i_mode & S_IFMT);
  4657. + plus = (inode->i_nlink > 0);
  4658. + first = au_h_iptr(inode);
  4659. + ibs = ibstart(inode);
  4660. + ibe = ibend(inode);
  4661. + }
  4662. +
  4663. + btail = bstart = dbstart(dentry);
  4664. + if (inode && S_ISDIR(inode->i_mode))
  4665. + btail = dbtaildir(dentry);
  4666. + locked = 0;
  4667. + if (nd) {
  4668. + fake_nd = *nd;
  4669. +#ifndef CONFIG_AUFS_FAKE_DM
  4670. + if (dentry != nd->dentry) {
  4671. + di_read_lock_parent(nd->dentry, 0);
  4672. + locked = 1;
  4673. + }
  4674. +#endif
  4675. + }
  4676. + for (bindex = bstart; bindex <= btail; bindex++) {
  4677. + h_dentry = au_h_dptr_i(dentry, bindex);
  4678. + if (unlikely(!h_dentry))
  4679. + continue;
  4680. + if (unlikely(do_udba
  4681. + && !is_root
  4682. + && (unhashed != d_unhashed(h_dentry)
  4683. +#if 1
  4684. + || name->len != h_dentry->d_name.len
  4685. + || memcmp(name->name, h_dentry->d_name.name,
  4686. + name->len)
  4687. +#endif
  4688. + ))) {
  4689. + LKTRTrace("unhash 0x%x 0x%x, %.*s %.*s\n",
  4690. + unhashed, d_unhashed(h_dentry),
  4691. + DLNPair(dentry), DLNPair(h_dentry));
  4692. + goto err;
  4693. + }
  4694. +
  4695. + reval = NULL;
  4696. + if (h_dentry->d_op)
  4697. + reval = h_dentry->d_op->d_revalidate;
  4698. + if (unlikely(reval)) {
  4699. + //LKTRLabel(hidden reval);
  4700. + p = fake_dm(&fake_nd, nd, sb, bindex);
  4701. + DEBUG_ON(IS_ERR(p));
  4702. + err = !reval(h_dentry, p);
  4703. + fake_dm_release(p);
  4704. + if (unlikely(err)) {
  4705. + //Dbg("here\n");
  4706. + goto err;
  4707. + }
  4708. + }
  4709. +
  4710. + if (unlikely(!do_udba))
  4711. + continue;
  4712. +
  4713. + /* UDBA tests */
  4714. + h_inode = h_dentry->d_inode;
  4715. + if (unlikely(!!inode != !!h_inode)) {
  4716. + //Dbg("here\n");
  4717. + goto err;
  4718. + }
  4719. +
  4720. + h_plus = plus;
  4721. + h_mode = mode;
  4722. + h_cached_inode = h_inode;
  4723. + is_nfs = 0;
  4724. + if (h_inode) {
  4725. + h_mode = (h_inode->i_mode & S_IFMT);
  4726. + h_plus = (h_inode->i_nlink > 0);
  4727. + }
  4728. + if (inode && ibs <= bindex && bindex <= ibe) {
  4729. + h_cached_inode = au_h_iptr_i(inode, bindex);
  4730. + //is_nfs = au_is_nfs(h_cached_inode->i_sb);
  4731. + }
  4732. +
  4733. + LKTRTrace("{%d, 0%o, %p}, h{%d, 0%o, %p}\n",
  4734. + plus, mode, h_cached_inode,
  4735. + h_plus, h_mode, h_inode);
  4736. + if (unlikely(plus != h_plus || mode != h_mode
  4737. + || (h_cached_inode != h_inode /* && !is_nfs */))) {
  4738. + //Dbg("here\n");
  4739. + goto err;
  4740. + }
  4741. + continue;
  4742. +
  4743. + err:
  4744. + err = -EINVAL;
  4745. + break;
  4746. + }
  4747. +#ifndef CONFIG_AUFS_FAKE_DM
  4748. + if (unlikely(locked))
  4749. + di_read_unlock(nd->dentry, 0);
  4750. +#endif
  4751. +
  4752. +#if 0
  4753. + // some filesystem uses CURRENT_TIME_SEC instead of CURRENT_TIME.
  4754. + // NFS may stop IN_DELETE because of DCACHE_NFSFS_RENAMED.
  4755. +#if 0
  4756. + && (!timespec_equal(&inode->i_ctime, &first->i_ctime)
  4757. + || !timespec_equal(&inode->i_atime, &first->i_atime))
  4758. +#endif
  4759. + if (unlikely(!err && udba && first))
  4760. + au_cpup_attr_all(inode);
  4761. +#endif
  4762. +
  4763. + TraceErr(err);
  4764. + return err;
  4765. +}
  4766. +
  4767. +static int simple_reval_dpath(struct dentry *dentry, int sgen)
  4768. +{
  4769. + int err;
  4770. + mode_t type;
  4771. + struct dentry *parent;
  4772. + struct inode *inode;
  4773. +
  4774. + LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
  4775. + SiMustAnyLock(dentry->d_sb);
  4776. + DiMustWriteLock(dentry);
  4777. + inode = dentry->d_inode;
  4778. + DEBUG_ON(!inode);
  4779. +
  4780. + if (au_digen(dentry) == sgen)
  4781. + return 0;
  4782. +
  4783. + parent = dget_parent(dentry);
  4784. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  4785. + DEBUG_ON(au_digen(parent) != sgen);
  4786. +#ifdef CONFIG_AUFS_DEBUG
  4787. + {
  4788. + struct dentry *d = parent;
  4789. + while (!IS_ROOT(d)) {
  4790. + DEBUG_ON(au_digen(d) != sgen);
  4791. + d = d->d_parent;
  4792. + }
  4793. + }
  4794. +#endif
  4795. + type = (inode->i_mode & S_IFMT);
  4796. + /* returns a number of positive dentries */
  4797. + err = au_refresh_hdentry(dentry, type);
  4798. + if (err >= 0)
  4799. + err = au_refresh_hinode(inode, dentry);
  4800. + di_read_unlock(parent, AUFS_I_RLOCK);
  4801. + dput(parent);
  4802. + TraceErr(err);
  4803. + return err;
  4804. +}
  4805. +
  4806. +int au_reval_dpath(struct dentry *dentry, int sgen)
  4807. +{
  4808. + int err;
  4809. + struct dentry *d, *parent;
  4810. + struct inode *inode;
  4811. +
  4812. + LKTRTrace("%.*s, sgen %d\n", DLNPair(dentry), sgen);
  4813. + DEBUG_ON(!dentry->d_inode);
  4814. + DiMustWriteLock(dentry);
  4815. +
  4816. + if (!stosi(dentry->d_sb)->si_failed_refresh_dirs)
  4817. + return simple_reval_dpath(dentry, sgen);
  4818. +
  4819. + /* slow loop, keep it simple and stupid */
  4820. + /* cf: cpup_dirs() */
  4821. + err = 0;
  4822. + while (au_digen(dentry) != sgen) {
  4823. + d = dentry;
  4824. + while (1) {
  4825. + parent = d->d_parent; // dget_parent()
  4826. + if (au_digen(parent) == sgen)
  4827. + break;
  4828. + d = parent;
  4829. + }
  4830. +
  4831. + inode = d->d_inode;
  4832. + if (d != dentry) {
  4833. + //i_lock(inode);
  4834. + di_write_lock_child(d);
  4835. + }
  4836. +
  4837. + /* someone might update our dentry while we were sleeping */
  4838. + if (au_digen(d) != sgen) {
  4839. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  4840. + /* returns a number of positive dentries */
  4841. + err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
  4842. + //err = -1;
  4843. + if (err >= 0)
  4844. + err = au_refresh_hinode(inode, d);
  4845. + //err = -1;
  4846. + di_read_unlock(parent, AUFS_I_RLOCK);
  4847. + }
  4848. +
  4849. + if (d != dentry) {
  4850. + di_write_unlock(d);
  4851. + //i_unlock(inode);
  4852. + }
  4853. + if (unlikely(err))
  4854. + break;
  4855. + }
  4856. +
  4857. + TraceErr(err);
  4858. + return err;
  4859. +}
  4860. +
  4861. +/*
  4862. + * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise.
  4863. + * nfsd passes NULL as nameidata.
  4864. + */
  4865. +static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
  4866. +{
  4867. + int valid, sgen, err, do_udba;
  4868. + struct super_block *sb;
  4869. + struct inode *inode;
  4870. +
  4871. + LKTRTrace("dentry %.*s\n", DLNPair(dentry));
  4872. + if (nd && nd->dentry)
  4873. + LKTRTrace("nd %.*s\n", DLNPair(nd->dentry));
  4874. + //dir case: DEBUG_ON(dentry->d_parent != nd->dentry);
  4875. + //remove failure case: DEBUG_ON(!IS_ROOT(dentry) && d_unhashed(dentry));
  4876. + DEBUG_ON(!dentry->d_fsdata);
  4877. + //DbgDentry(dentry);
  4878. +
  4879. + err = -EINVAL;
  4880. + inode = dentry->d_inode;
  4881. + //DbgInode(inode);
  4882. + sb = dentry->d_sb;
  4883. + si_read_lock(sb);
  4884. + sgen = au_sigen(sb);
  4885. + if (au_digen(dentry) == sgen)
  4886. + di_read_lock_child(dentry, !AUFS_I_RLOCK);
  4887. + else {
  4888. + DEBUG_ON(IS_ROOT(dentry));
  4889. +#ifdef ForceInotify
  4890. + Dbg("UDBA or digen, %.*s\n", DLNPair(dentry));
  4891. +#endif
  4892. + //i_lock(inode);
  4893. + di_write_lock_child(dentry);
  4894. + if (inode)
  4895. + err = au_reval_dpath(dentry, sgen);
  4896. + //err = -1;
  4897. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  4898. + //i_unlock(inode);
  4899. + if (unlikely(err))
  4900. + goto out;
  4901. + ii_read_unlock(inode);
  4902. + DEBUG_ON(au_iigen(inode) != sgen);
  4903. + }
  4904. +
  4905. + if (inode) {
  4906. + if (au_iigen(inode) == sgen)
  4907. + ii_read_lock_child(inode);
  4908. + else {
  4909. + DEBUG_ON(IS_ROOT(dentry));
  4910. +#ifdef ForceInotify
  4911. + Dbg("UDBA or survived, %.*s\n", DLNPair(dentry));
  4912. +#endif
  4913. + ii_write_lock_child(inode);
  4914. + err = au_refresh_hinode(inode, dentry);
  4915. + ii_downgrade_lock(inode);
  4916. + if (unlikely(err))
  4917. + goto out;
  4918. + DEBUG_ON(au_iigen(inode) != sgen);
  4919. + }
  4920. + }
  4921. +
  4922. +#if 0 // fix it
  4923. + /* parent dir i_nlink is not updated in the case of setattr */
  4924. + if (S_ISDIR(inode->i_mode)) {
  4925. + i_lock(inode);
  4926. + ii_write_lock(inode);
  4927. + au_cpup_attr_nlink(inode);
  4928. + ii_write_unlock(inode);
  4929. + i_unlock(inode);
  4930. + }
  4931. +#endif
  4932. +
  4933. + err = -EINVAL;
  4934. + do_udba = !au_flag_test(sb, AuFlag_UDBA_NONE);
  4935. + if (do_udba && inode && ibstart(inode) >= 0
  4936. + && au_test_higen(inode, au_h_iptr(inode)))
  4937. + goto out;
  4938. + err = h_d_revalidate(dentry, nd, do_udba);
  4939. + //err = -1;
  4940. +
  4941. + out:
  4942. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  4943. + TraceErr(err);
  4944. + valid = !err;
  4945. + //au_debug_on();
  4946. + if (!valid)
  4947. + LKTRTrace("%.*s invalid\n", DLNPair(dentry));
  4948. + //au_debug_off();
  4949. + return valid;
  4950. +}
  4951. +
  4952. +static void aufs_d_release(struct dentry *dentry)
  4953. +{
  4954. + struct aufs_dinfo *dinfo;
  4955. + aufs_bindex_t bend, bindex;
  4956. +
  4957. + LKTRTrace("%.*s\n", DLNPair(dentry));
  4958. + DEBUG_ON(!d_unhashed(dentry));
  4959. +
  4960. + dinfo = dentry->d_fsdata;
  4961. + if (unlikely(!dinfo))
  4962. + return;
  4963. +
  4964. + /* dentry may not be revalidated */
  4965. + bindex = dinfo->di_bstart;
  4966. + if (bindex >= 0) {
  4967. + struct aufs_hdentry *p;
  4968. + bend = dinfo->di_bend;
  4969. + DEBUG_ON(bend < bindex);
  4970. + p = dinfo->di_hdentry + bindex;
  4971. + while (bindex++ <= bend) {
  4972. + if (p->hd_dentry)
  4973. + hdput(p);
  4974. + p++;
  4975. + }
  4976. + }
  4977. + kfree(dinfo->di_hdentry);
  4978. + cache_free_dinfo(dinfo);
  4979. +}
  4980. +
  4981. +#if 0
  4982. +/* it may be called at remount time, too */
  4983. +static void aufs_d_iput(struct dentry *dentry, struct inode *inode)
  4984. +{
  4985. + struct super_block *sb;
  4986. +
  4987. + LKTRTrace("%.*s, i%lu\n", DLNPair(dentry), inode->i_ino);
  4988. +
  4989. + sb = dentry->d_sb;
  4990. +#if 0
  4991. + si_read_lock(sb);
  4992. + if (unlikely(au_flag_test(sb, AuFlag_PLINK)
  4993. + && au_is_plinked(sb, inode))) {
  4994. + ii_write_lock(inode);
  4995. + au_update_brange(inode, 1);
  4996. + ii_write_unlock(inode);
  4997. + }
  4998. + si_read_unlock(sb);
  4999. +#endif
  5000. + iput(inode);
  5001. +}
  5002. +#endif
  5003. +
  5004. +struct dentry_operations aufs_dop = {
  5005. + .d_revalidate = aufs_d_revalidate,
  5006. + .d_release = aufs_d_release
  5007. + //.d_iput = aufs_d_iput
  5008. +};
  5009. diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h
  5010. new file mode 100755
  5011. index 0000000..78049e3
  5012. --- /dev/null
  5013. +++ b/fs/aufs/dentry.h
  5014. @@ -0,0 +1,183 @@
  5015. +/*
  5016. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  5017. + *
  5018. + * This program, aufs is free software; you can redistribute it and/or modify
  5019. + * it under the terms of the GNU General Public License as published by
  5020. + * the Free Software Foundation; either version 2 of the License, or
  5021. + * (at your option) any later version.
  5022. + *
  5023. + * This program is distributed in the hope that it will be useful,
  5024. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5025. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5026. + * GNU General Public License for more details.
  5027. + *
  5028. + * You should have received a copy of the GNU General Public License
  5029. + * along with this program; if not, write to the Free Software
  5030. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  5031. + */
  5032. +
  5033. +/* $Id: dentry.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
  5034. +
  5035. +#ifndef __AUFS_DENTRY_H__
  5036. +#define __AUFS_DENTRY_H__
  5037. +
  5038. +#ifdef __KERNEL__
  5039. +
  5040. +#include <linux/fs.h>
  5041. +#include <linux/aufs_type.h>
  5042. +#include "misc.h"
  5043. +
  5044. +struct aufs_hdentry {
  5045. + struct dentry *hd_dentry;
  5046. +};
  5047. +
  5048. +struct aufs_dinfo {
  5049. + atomic_t di_generation;
  5050. +
  5051. + struct aufs_rwsem di_rwsem;
  5052. + aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
  5053. + struct aufs_hdentry *di_hdentry;
  5054. +};
  5055. +
  5056. +struct lkup_args {
  5057. + struct vfsmount *nfsmnt;
  5058. + int dlgt;
  5059. + //struct super_block *sb;
  5060. +};
  5061. +
  5062. +/* ---------------------------------------------------------------------- */
  5063. +
  5064. +/* dentry.c */
  5065. +#if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT)
  5066. +struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
  5067. + struct lkup_args *lkup);
  5068. +#else
  5069. +static inline
  5070. +struct dentry *lkup_one(const char *name, struct dentry *parent, int len,
  5071. + struct lkup_args *lkup)
  5072. +{
  5073. + return lookup_one_len(name, parent, len);
  5074. +}
  5075. +#endif
  5076. +
  5077. +extern struct dentry_operations aufs_dop;
  5078. +struct dentry *sio_lkup_one(const char *name, struct dentry *parent, int len,
  5079. + struct lkup_args *lkup);
  5080. +int lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type);
  5081. +int lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
  5082. +int au_refresh_hdentry(struct dentry *dentry, mode_t type);
  5083. +int au_reval_dpath(struct dentry *dentry, int sgen);
  5084. +
  5085. +/* dinfo.c */
  5086. +int au_alloc_dinfo(struct dentry *dentry);
  5087. +struct aufs_dinfo *dtodi(struct dentry *dentry);
  5088. +
  5089. +void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
  5090. +void di_read_unlock(struct dentry *d, int flags);
  5091. +void di_downgrade_lock(struct dentry *d, int flags);
  5092. +void di_write_lock(struct dentry *d, unsigned int lsc);
  5093. +void di_write_unlock(struct dentry *d);
  5094. +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
  5095. +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
  5096. +void di_write_unlock2(struct dentry *d1, struct dentry *d2);
  5097. +
  5098. +aufs_bindex_t dbstart(struct dentry *dentry);
  5099. +aufs_bindex_t dbend(struct dentry *dentry);
  5100. +aufs_bindex_t dbwh(struct dentry *dentry);
  5101. +aufs_bindex_t dbdiropq(struct dentry *dentry);
  5102. +struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex);
  5103. +struct dentry *au_h_dptr(struct dentry *dentry);
  5104. +
  5105. +aufs_bindex_t dbtail(struct dentry *dentry);
  5106. +aufs_bindex_t dbtaildir(struct dentry *dentry);
  5107. +aufs_bindex_t dbtail_generic(struct dentry *dentry);
  5108. +
  5109. +void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex);
  5110. +void set_dbend(struct dentry *dentry, aufs_bindex_t bindex);
  5111. +void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex);
  5112. +void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex);
  5113. +void hdput(struct aufs_hdentry *hdentry);
  5114. +void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
  5115. + struct dentry *h_dentry);
  5116. +
  5117. +void au_update_digen(struct dentry *dentry);
  5118. +void au_update_dbstart(struct dentry *dentry);
  5119. +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
  5120. +
  5121. +/* ---------------------------------------------------------------------- */
  5122. +
  5123. +static inline int au_digen(struct dentry *d)
  5124. +{
  5125. + return atomic_read(&dtodi(d)->di_generation);
  5126. +}
  5127. +
  5128. +#ifdef CONFIG_AUFS_HINOTIFY
  5129. +static inline void au_digen_dec(struct dentry *d)
  5130. +{
  5131. + atomic_dec(&dtodi(d)->di_generation);
  5132. +}
  5133. +#endif /* CONFIG_AUFS_HINOTIFY */
  5134. +
  5135. +/* ---------------------------------------------------------------------- */
  5136. +
  5137. +/* lock subclass for dinfo */
  5138. +enum {
  5139. + AuLsc_DI_CHILD, /* child first */
  5140. + AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hinotify */
  5141. + AuLsc_DI_CHILD3, /* copyup dirs */
  5142. + AuLsc_DI_PARENT,
  5143. + AuLsc_DI_PARENT2,
  5144. + AuLsc_DI_PARENT3
  5145. +};
  5146. +
  5147. +/*
  5148. + * di_read_lock_child, di_write_lock_child,
  5149. + * di_read_lock_child2, di_write_lock_child2,
  5150. + * di_read_lock_child3, di_write_lock_child3,
  5151. + * di_read_lock_parent, di_write_lock_parent,
  5152. + * di_read_lock_parent2, di_write_lock_parent2,
  5153. + * di_read_lock_parent3, di_write_lock_parent3,
  5154. + */
  5155. +#define ReadLockFunc(name, lsc) \
  5156. +static inline void di_read_lock_##name(struct dentry *d, int flags) \
  5157. +{di_read_lock(d, flags, AuLsc_DI_##lsc);}
  5158. +
  5159. +#define WriteLockFunc(name, lsc) \
  5160. +static inline void di_write_lock_##name(struct dentry *d) \
  5161. +{di_write_lock(d, AuLsc_DI_##lsc);}
  5162. +
  5163. +#define RWLockFuncs(name, lsc) \
  5164. + ReadLockFunc(name, lsc); \
  5165. + WriteLockFunc(name, lsc)
  5166. +
  5167. +RWLockFuncs(child, CHILD);
  5168. +RWLockFuncs(child2, CHILD2);
  5169. +RWLockFuncs(child3, CHILD3);
  5170. +RWLockFuncs(parent, PARENT);
  5171. +RWLockFuncs(parent2, PARENT2);
  5172. +RWLockFuncs(parent3, PARENT3);
  5173. +
  5174. +#undef ReadLockFunc
  5175. +#undef WriteLockFunc
  5176. +#undef RWLockFunc
  5177. +
  5178. +/* to debug easier, do not make them inlined functions */
  5179. +#define DiMustReadLock(d) do { \
  5180. + SiMustAnyLock((d)->d_sb); \
  5181. + RwMustReadLock(&dtodi(d)->di_rwsem); \
  5182. +} while (0)
  5183. +
  5184. +#define DiMustWriteLock(d) do { \
  5185. + SiMustAnyLock((d)->d_sb); \
  5186. + RwMustWriteLock(&dtodi(d)->di_rwsem); \
  5187. +} while (0)
  5188. +
  5189. +#define DiMustAnyLock(d) do { \
  5190. + SiMustAnyLock((d)->d_sb); \
  5191. + RwMustAnyLock(&dtodi(d)->di_rwsem); \
  5192. +} while (0)
  5193. +
  5194. +#define DiMustNoWaiters(d) RwMustNoWaiters(&dtodi(d)->di_rwsem)
  5195. +
  5196. +#endif /* __KERNEL__ */
  5197. +#endif /* __AUFS_DENTRY_H__ */
  5198. diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c
  5199. new file mode 100755
  5200. index 0000000..6082149
  5201. --- /dev/null
  5202. +++ b/fs/aufs/dinfo.c
  5203. @@ -0,0 +1,419 @@
  5204. +/*
  5205. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  5206. + *
  5207. + * This program, aufs is free software; you can redistribute it and/or modify
  5208. + * it under the terms of the GNU General Public License as published by
  5209. + * the Free Software Foundation; either version 2 of the License, or
  5210. + * (at your option) any later version.
  5211. + *
  5212. + * This program is distributed in the hope that it will be useful,
  5213. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5214. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5215. + * GNU General Public License for more details.
  5216. + *
  5217. + * You should have received a copy of the GNU General Public License
  5218. + * along with this program; if not, write to the Free Software
  5219. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  5220. + */
  5221. +
  5222. +/* $Id: dinfo.c,v 1.23 2007/05/07 03:43:36 sfjro Exp $ */
  5223. +
  5224. +#include "aufs.h"
  5225. +
  5226. +int au_alloc_dinfo(struct dentry *dentry)
  5227. +{
  5228. + struct aufs_dinfo *dinfo;
  5229. + struct super_block *sb;
  5230. + int nbr;
  5231. +
  5232. + LKTRTrace("%.*s\n", DLNPair(dentry));
  5233. + DEBUG_ON(dentry->d_fsdata);
  5234. +
  5235. + dinfo = cache_alloc_dinfo();
  5236. + //if (LktrCond) {cache_free_dinfo(dinfo); dinfo = NULL;}
  5237. + if (dinfo) {
  5238. + sb = dentry->d_sb;
  5239. + nbr = sbend(sb) + 1;
  5240. + if (unlikely(!nbr))
  5241. + nbr++;
  5242. + dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
  5243. + GFP_KERNEL);
  5244. + //if (LktrCond)
  5245. + //{kfree(dinfo->di_hdentry); dinfo->di_hdentry = NULL;}
  5246. + if (dinfo->di_hdentry) {
  5247. + rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_PARENT);
  5248. + dinfo->di_bstart = dinfo->di_bend = -1;
  5249. + dinfo->di_bwh = dinfo->di_bdiropq = -1;
  5250. + atomic_set(&dinfo->di_generation, au_sigen(sb));
  5251. +
  5252. + dentry->d_fsdata = dinfo;
  5253. + dentry->d_op = &aufs_dop;
  5254. + return 0; /* success */
  5255. + }
  5256. + cache_free_dinfo(dinfo);
  5257. + }
  5258. + TraceErr(-ENOMEM);
  5259. + return -ENOMEM;
  5260. +}
  5261. +
  5262. +struct aufs_dinfo *dtodi(struct dentry *dentry)
  5263. +{
  5264. + struct aufs_dinfo *dinfo = dentry->d_fsdata;
  5265. + DEBUG_ON(!dinfo
  5266. + || !dinfo->di_hdentry
  5267. + /* || stosi(dentry->d_sb)->si_bend < dinfo->di_bend */
  5268. + || dinfo->di_bend < dinfo->di_bstart
  5269. + /* dbwh can be outside of this range */
  5270. + || (0 <= dinfo->di_bdiropq
  5271. + && (dinfo->di_bdiropq < dinfo->di_bstart
  5272. + /* || dinfo->di_bend < dinfo->di_bdiropq */))
  5273. + );
  5274. + return dinfo;
  5275. +}
  5276. +
  5277. +/* ---------------------------------------------------------------------- */
  5278. +
  5279. +static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
  5280. +{
  5281. + switch (lsc) {
  5282. + case AuLsc_DI_CHILD:
  5283. + ii_write_lock_child(inode);
  5284. + break;
  5285. + case AuLsc_DI_CHILD2:
  5286. + ii_write_lock_child2(inode);
  5287. + break;
  5288. + case AuLsc_DI_CHILD3:
  5289. + ii_write_lock_child3(inode);
  5290. + break;
  5291. + case AuLsc_DI_PARENT:
  5292. + ii_write_lock_parent(inode);
  5293. + break;
  5294. + case AuLsc_DI_PARENT2:
  5295. + ii_write_lock_parent2(inode);
  5296. + break;
  5297. + case AuLsc_DI_PARENT3:
  5298. + ii_write_lock_parent3(inode);
  5299. + break;
  5300. + default:
  5301. + BUG();
  5302. + }
  5303. +}
  5304. +
  5305. +static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
  5306. +{
  5307. + switch (lsc) {
  5308. + case AuLsc_DI_CHILD:
  5309. + ii_read_lock_child(inode);
  5310. + break;
  5311. + case AuLsc_DI_CHILD2:
  5312. + ii_read_lock_child2(inode);
  5313. + break;
  5314. + case AuLsc_DI_CHILD3:
  5315. + ii_read_lock_child3(inode);
  5316. + break;
  5317. + case AuLsc_DI_PARENT:
  5318. + ii_read_lock_parent(inode);
  5319. + break;
  5320. + case AuLsc_DI_PARENT2:
  5321. + ii_read_lock_parent2(inode);
  5322. + break;
  5323. + case AuLsc_DI_PARENT3:
  5324. + ii_read_lock_parent3(inode);
  5325. + break;
  5326. + default:
  5327. + BUG();
  5328. + }
  5329. +}
  5330. +
  5331. +void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
  5332. +{
  5333. + SiMustAnyLock(d->d_sb);
  5334. + // todo: always nested?
  5335. + rw_read_lock_nested(&dtodi(d)->di_rwsem, lsc);
  5336. + if (d->d_inode) {
  5337. + if (flags & AUFS_I_WLOCK)
  5338. + do_ii_write_lock(d->d_inode, lsc);
  5339. + else if (flags & AUFS_I_RLOCK)
  5340. + do_ii_read_lock(d->d_inode, lsc);
  5341. + }
  5342. +}
  5343. +
  5344. +void di_read_unlock(struct dentry *d, int flags)
  5345. +{
  5346. + SiMustAnyLock(d->d_sb);
  5347. + if (d->d_inode) {
  5348. + if (flags & AUFS_I_WLOCK)
  5349. + ii_write_unlock(d->d_inode);
  5350. + else if (flags & AUFS_I_RLOCK)
  5351. + ii_read_unlock(d->d_inode);
  5352. + }
  5353. + rw_read_unlock(&dtodi(d)->di_rwsem);
  5354. +}
  5355. +
  5356. +void di_downgrade_lock(struct dentry *d, int flags)
  5357. +{
  5358. + SiMustAnyLock(d->d_sb);
  5359. + rw_dgrade_lock(&dtodi(d)->di_rwsem);
  5360. + if (d->d_inode && (flags & AUFS_I_RLOCK))
  5361. + ii_downgrade_lock(d->d_inode);
  5362. +}
  5363. +
  5364. +void di_write_lock(struct dentry *d, unsigned int lsc)
  5365. +{
  5366. + SiMustAnyLock(d->d_sb);
  5367. + // todo: always nested?
  5368. + rw_write_lock_nested(&dtodi(d)->di_rwsem, lsc);
  5369. + if (d->d_inode)
  5370. + do_ii_write_lock(d->d_inode, lsc);
  5371. +}
  5372. +
  5373. +void di_write_unlock(struct dentry *d)
  5374. +{
  5375. + SiMustAnyLock(d->d_sb);
  5376. + if (d->d_inode)
  5377. + ii_write_unlock(d->d_inode);
  5378. + rw_write_unlock(&dtodi(d)->di_rwsem);
  5379. +}
  5380. +
  5381. +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
  5382. +{
  5383. + struct dentry *d;
  5384. +
  5385. + TraceEnter();
  5386. + DEBUG_ON(d1 == d2
  5387. + || d1->d_inode == d2->d_inode
  5388. + || d1->d_sb != d2->d_sb);
  5389. +
  5390. + if (isdir)
  5391. + for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
  5392. + if (d->d_parent == d2) {
  5393. + di_write_lock_child(d1);
  5394. + di_write_lock_child2(d2);
  5395. + return;
  5396. + }
  5397. +
  5398. + di_write_lock_child(d2);
  5399. + di_write_lock_child2(d1);
  5400. +}
  5401. +
  5402. +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
  5403. +{
  5404. + struct dentry *d;
  5405. +
  5406. + TraceEnter();
  5407. + DEBUG_ON(d1 == d2
  5408. + || d1->d_inode == d2->d_inode
  5409. + || d1->d_sb != d2->d_sb);
  5410. +
  5411. + if (isdir)
  5412. + for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
  5413. + if (d->d_parent == d2) {
  5414. + di_write_lock_parent(d1);
  5415. + di_write_lock_parent2(d2);
  5416. + return;
  5417. + }
  5418. +
  5419. + di_write_lock_parent(d2);
  5420. + di_write_lock_parent2(d1);
  5421. +}
  5422. +
  5423. +void di_write_unlock2(struct dentry *d1, struct dentry *d2)
  5424. +{
  5425. + di_write_unlock(d1);
  5426. + if (d1->d_inode == d2->d_inode)
  5427. + rw_write_unlock(&dtodi(d2)->di_rwsem);
  5428. + else
  5429. + di_write_unlock(d2);
  5430. +}
  5431. +
  5432. +/* ---------------------------------------------------------------------- */
  5433. +
  5434. +aufs_bindex_t dbstart(struct dentry *dentry)
  5435. +{
  5436. + DiMustAnyLock(dentry);
  5437. + return dtodi(dentry)->di_bstart;
  5438. +}
  5439. +
  5440. +aufs_bindex_t dbend(struct dentry *dentry)
  5441. +{
  5442. + DiMustAnyLock(dentry);
  5443. + return dtodi(dentry)->di_bend;
  5444. +}
  5445. +
  5446. +aufs_bindex_t dbwh(struct dentry *dentry)
  5447. +{
  5448. + DiMustAnyLock(dentry);
  5449. + return dtodi(dentry)->di_bwh;
  5450. +}
  5451. +
  5452. +aufs_bindex_t dbdiropq(struct dentry *dentry)
  5453. +{
  5454. + DiMustAnyLock(dentry);
  5455. + DEBUG_ON(dentry->d_inode
  5456. + && dentry->d_inode->i_mode
  5457. + && !S_ISDIR(dentry->d_inode->i_mode));
  5458. + return dtodi(dentry)->di_bdiropq;
  5459. +}
  5460. +
  5461. +struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex)
  5462. +{
  5463. + struct dentry *d;
  5464. +
  5465. + DiMustAnyLock(dentry);
  5466. + if (dbstart(dentry) < 0 || bindex < dbstart(dentry))
  5467. + return NULL;
  5468. + DEBUG_ON(bindex < 0
  5469. + /* || bindex > sbend(dentry->d_sb) */);
  5470. + d = dtodi(dentry)->di_hdentry[0 + bindex].hd_dentry;
  5471. + DEBUG_ON(d && (atomic_read(&d->d_count) <= 0));
  5472. + return d;
  5473. +}
  5474. +
  5475. +struct dentry *au_h_dptr(struct dentry *dentry)
  5476. +{
  5477. + return au_h_dptr_i(dentry, dbstart(dentry));
  5478. +}
  5479. +
  5480. +aufs_bindex_t dbtail(struct dentry *dentry)
  5481. +{
  5482. + aufs_bindex_t bend, bwh;
  5483. +
  5484. + bend = dbend(dentry);
  5485. + if (0 <= bend) {
  5486. + bwh = dbwh(dentry);
  5487. + //DEBUG_ON(bend < bwh);
  5488. + if (!bwh)
  5489. + return bwh;
  5490. + if (0 < bwh && bwh < bend)
  5491. + return bwh - 1;
  5492. + }
  5493. + return bend;
  5494. +}
  5495. +
  5496. +aufs_bindex_t dbtaildir(struct dentry *dentry)
  5497. +{
  5498. + aufs_bindex_t bend, bopq;
  5499. +
  5500. + DEBUG_ON(dentry->d_inode
  5501. + && dentry->d_inode->i_mode
  5502. + && !S_ISDIR(dentry->d_inode->i_mode));
  5503. +
  5504. + bend = dbtail(dentry);
  5505. + if (0 <= bend) {
  5506. + bopq = dbdiropq(dentry);
  5507. + DEBUG_ON(bend < bopq);
  5508. + if (0 <= bopq && bopq < bend)
  5509. + bend = bopq;
  5510. + }
  5511. + return bend;
  5512. +}
  5513. +
  5514. +aufs_bindex_t dbtail_generic(struct dentry *dentry)
  5515. +{
  5516. + struct inode *inode;
  5517. +
  5518. + inode = dentry->d_inode;
  5519. + if (inode && S_ISDIR(inode->i_mode))
  5520. + return dbtaildir(dentry);
  5521. + else
  5522. + return dbtail(dentry);
  5523. +}
  5524. +
  5525. +/* ---------------------------------------------------------------------- */
  5526. +
  5527. +// hard/soft set
  5528. +void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
  5529. +{
  5530. + DiMustWriteLock(dentry);
  5531. + DEBUG_ON(sbend(dentry->d_sb) < bindex);
  5532. + /* */
  5533. + dtodi(dentry)->di_bstart = bindex;
  5534. +}
  5535. +
  5536. +void set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
  5537. +{
  5538. + DiMustWriteLock(dentry);
  5539. + DEBUG_ON(sbend(dentry->d_sb) < bindex
  5540. + || bindex < dbstart(dentry));
  5541. + dtodi(dentry)->di_bend = bindex;
  5542. +}
  5543. +
  5544. +void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
  5545. +{
  5546. + DiMustWriteLock(dentry);
  5547. + DEBUG_ON(sbend(dentry->d_sb) < bindex);
  5548. + /* dbwh can be outside of bstart - bend range */
  5549. + dtodi(dentry)->di_bwh = bindex;
  5550. +}
  5551. +
  5552. +void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
  5553. +{
  5554. + DiMustWriteLock(dentry);
  5555. + DEBUG_ON(sbend(dentry->d_sb) < bindex);
  5556. + DEBUG_ON((bindex != -1
  5557. + && (bindex < dbstart(dentry) || dbend(dentry) < bindex))
  5558. + || (dentry->d_inode
  5559. + && dentry->d_inode->i_mode
  5560. + && !S_ISDIR(dentry->d_inode->i_mode)));
  5561. + dtodi(dentry)->di_bdiropq = bindex;
  5562. +}
  5563. +
  5564. +void hdput(struct aufs_hdentry *hd)
  5565. +{
  5566. + dput(hd->hd_dentry);
  5567. +}
  5568. +
  5569. +void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
  5570. + struct dentry *h_dentry)
  5571. +{
  5572. + struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
  5573. + DiMustWriteLock(dentry);
  5574. + DEBUG_ON(bindex < dtodi(dentry)->di_bstart
  5575. + || bindex > dtodi(dentry)->di_bend
  5576. + || (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
  5577. + || (h_dentry && hd->hd_dentry)
  5578. + );
  5579. + if (hd->hd_dentry)
  5580. + hdput(hd);
  5581. + hd->hd_dentry = h_dentry;
  5582. +}
  5583. +
  5584. +/* ---------------------------------------------------------------------- */
  5585. +
  5586. +void au_update_digen(struct dentry *dentry)
  5587. +{
  5588. + //DiMustWriteLock(dentry);
  5589. + DEBUG_ON(!dentry->d_sb);
  5590. + atomic_set(&dtodi(dentry)->di_generation, au_sigen(dentry->d_sb));
  5591. +}
  5592. +
  5593. +void au_update_dbstart(struct dentry *dentry)
  5594. +{
  5595. + aufs_bindex_t bindex, bstart = dbstart(dentry), bend = dbend(dentry);
  5596. + struct dentry *hidden_dentry;
  5597. +
  5598. + DiMustWriteLock(dentry);
  5599. + for (bindex = bstart; bindex <= bend; bindex++) {
  5600. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  5601. + if (!hidden_dentry)
  5602. + continue;
  5603. + if (hidden_dentry->d_inode) {
  5604. + set_dbstart(dentry, bindex);
  5605. + return;
  5606. + }
  5607. + set_h_dptr(dentry, bindex, NULL);
  5608. + }
  5609. + //set_dbstart(dentry, -1);
  5610. + //set_dbend(dentry, -1);
  5611. +}
  5612. +
  5613. +int au_find_dbindex(struct dentry *dentry, struct dentry *hidden_dentry)
  5614. +{
  5615. + aufs_bindex_t bindex, bend;
  5616. +
  5617. + bend = dbend(dentry);
  5618. + for (bindex = dbstart(dentry); bindex <= bend; bindex++)
  5619. + if (au_h_dptr_i(dentry, bindex) == hidden_dentry)
  5620. + return bindex;
  5621. + return -1;
  5622. +}
  5623. diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c
  5624. new file mode 100755
  5625. index 0000000..9afb1a9
  5626. --- /dev/null
  5627. +++ b/fs/aufs/dir.c
  5628. @@ -0,0 +1,564 @@
  5629. +/*
  5630. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  5631. + *
  5632. + * This program, aufs is free software; you can redistribute it and/or modify
  5633. + * it under the terms of the GNU General Public License as published by
  5634. + * the Free Software Foundation; either version 2 of the License, or
  5635. + * (at your option) any later version.
  5636. + *
  5637. + * This program is distributed in the hope that it will be useful,
  5638. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5639. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5640. + * GNU General Public License for more details.
  5641. + *
  5642. + * You should have received a copy of the GNU General Public License
  5643. + * along with this program; if not, write to the Free Software
  5644. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  5645. + */
  5646. +
  5647. +/* $Id: dir.c,v 1.36 2007/05/14 03:38:52 sfjro Exp $ */
  5648. +
  5649. +#include "aufs.h"
  5650. +
  5651. +static int reopen_dir(struct file *file)
  5652. +{
  5653. + int err;
  5654. + struct dentry *dentry, *hidden_dentry;
  5655. + aufs_bindex_t bindex, btail, bstart;
  5656. + struct file *hidden_file;
  5657. +
  5658. + dentry = file->f_dentry;
  5659. + LKTRTrace("%.*s\n", DLNPair(dentry));
  5660. + DEBUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
  5661. +
  5662. + /* open all hidden dirs */
  5663. + bstart = dbstart(dentry);
  5664. +#if 1
  5665. + for (bindex = fbstart(file); bindex < bstart; bindex++)
  5666. + set_h_fptr(file, bindex, NULL);
  5667. +#endif
  5668. + set_fbstart(file, bstart);
  5669. + btail = dbtaildir(dentry);
  5670. +#if 1
  5671. + for (bindex = fbend(file); btail < bindex; bindex--)
  5672. + set_h_fptr(file, bindex, NULL);
  5673. +#endif
  5674. + set_fbend(file, btail);
  5675. + for (bindex = bstart; bindex <= btail; bindex++) {
  5676. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  5677. + if (!hidden_dentry)
  5678. + continue;
  5679. + hidden_file = au_h_fptr_i(file, bindex);
  5680. + if (hidden_file) {
  5681. + DEBUG_ON(hidden_file->f_dentry != hidden_dentry);
  5682. + continue;
  5683. + }
  5684. +
  5685. + hidden_file = hidden_open(dentry, bindex, file->f_flags);
  5686. + // unavailable
  5687. + //if (LktrCond) {fput(hidden_file);
  5688. + //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
  5689. + err = PTR_ERR(hidden_file);
  5690. + if (IS_ERR(hidden_file))
  5691. + goto out; // close all?
  5692. + //cpup_file_flags(hidden_file, file);
  5693. + set_h_fptr(file, bindex, hidden_file);
  5694. + }
  5695. + err = 0;
  5696. +
  5697. + out:
  5698. + TraceErr(err);
  5699. + return err;
  5700. +}
  5701. +
  5702. +static int do_open_dir(struct file *file, int flags)
  5703. +{
  5704. + int err;
  5705. + aufs_bindex_t bindex, btail;
  5706. + struct dentry *dentry, *hidden_dentry;
  5707. + struct file *hidden_file;
  5708. +
  5709. + dentry = file->f_dentry;
  5710. + LKTRTrace("%.*s, 0x%x\n", DLNPair(dentry), flags);
  5711. + DEBUG_ON(!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode));
  5712. +
  5713. + err = 0;
  5714. + set_fvdir_cache(file, NULL);
  5715. + file->f_version = dentry->d_inode->i_version;
  5716. + bindex = dbstart(dentry);
  5717. + set_fbstart(file, bindex);
  5718. + btail = dbtaildir(dentry);
  5719. + set_fbend(file, btail);
  5720. + for (; !err && bindex <= btail; bindex++) {
  5721. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  5722. + if (!hidden_dentry)
  5723. + continue;
  5724. +
  5725. + hidden_file = hidden_open(dentry, bindex, flags);
  5726. + //if (LktrCond) {fput(hidden_file);
  5727. + //br_put(stobr(dentry->d_sb, bindex));hidden_file=ERR_PTR(-1);}
  5728. + if (!IS_ERR(hidden_file)) {
  5729. + set_h_fptr(file, bindex, hidden_file);
  5730. + continue;
  5731. + }
  5732. + err = PTR_ERR(hidden_file);
  5733. + }
  5734. + if (!err)
  5735. + return 0; /* success */
  5736. +
  5737. + /* close all */
  5738. + for (bindex = fbstart(file); !err && bindex <= btail; bindex++)
  5739. + set_h_fptr(file, bindex, NULL);
  5740. + set_fbstart(file, -1);
  5741. + set_fbend(file, -1);
  5742. + return err;
  5743. +}
  5744. +
  5745. +static int aufs_open_dir(struct inode *inode, struct file *file)
  5746. +{
  5747. + return au_do_open(inode, file, do_open_dir);
  5748. +}
  5749. +
  5750. +static int aufs_release_dir(struct inode *inode, struct file *file)
  5751. +{
  5752. + struct aufs_vdir *vdir_cache;
  5753. + struct super_block *sb;
  5754. +
  5755. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
  5756. +
  5757. + sb = file->f_dentry->d_sb;
  5758. + si_read_lock(sb);
  5759. + fi_write_lock(file);
  5760. + vdir_cache = fvdir_cache(file);
  5761. + if (vdir_cache)
  5762. + free_vdir(vdir_cache);
  5763. + fi_write_unlock(file);
  5764. + au_fin_finfo(file);
  5765. + si_read_unlock(sb);
  5766. + return 0;
  5767. +}
  5768. +
  5769. +static int fsync_dir(struct dentry *dentry, int datasync)
  5770. +{
  5771. + int err;
  5772. + struct inode *inode;
  5773. + struct super_block *sb;
  5774. + aufs_bindex_t bend, bindex;
  5775. +
  5776. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
  5777. + DiMustAnyLock(dentry);
  5778. + sb = dentry->d_sb;
  5779. + SiMustAnyLock(sb);
  5780. + inode = dentry->d_inode;
  5781. + IMustLock(inode);
  5782. + IiMustAnyLock(inode);
  5783. +
  5784. + err = 0;
  5785. + bend = dbend(dentry);
  5786. + for (bindex = dbstart(dentry); !err && bindex <= bend; bindex++) {
  5787. + struct dentry *h_dentry;
  5788. + struct inode *h_inode;
  5789. + struct file_operations *fop;
  5790. +
  5791. + if (test_ro(sb, bindex, inode))
  5792. + continue;
  5793. + h_dentry = au_h_dptr_i(dentry, bindex);
  5794. + if (!h_dentry)
  5795. + continue;
  5796. + h_inode = h_dentry->d_inode;
  5797. + if (!h_inode)
  5798. + continue;
  5799. +
  5800. + /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
  5801. + //hdir_lock(h_inode, inode, bindex);
  5802. + i_lock(h_inode);
  5803. + fop = (void*)h_inode->i_fop;
  5804. + err = filemap_fdatawrite(h_inode->i_mapping);
  5805. + if (!err && fop && fop->fsync)
  5806. + err = fop->fsync(NULL, h_dentry, datasync);
  5807. + if (!err)
  5808. + err = filemap_fdatawrite(h_inode->i_mapping);
  5809. + //hdir_unlock(h_inode, inode, bindex);
  5810. + i_unlock(h_inode);
  5811. + }
  5812. +
  5813. + TraceErr(err);
  5814. + return err;
  5815. +}
  5816. +
  5817. +/*
  5818. + * @file may be NULL
  5819. + */
  5820. +static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
  5821. + int datasync)
  5822. +{
  5823. + int err;
  5824. + struct inode *inode;
  5825. + struct file *hidden_file;
  5826. + struct super_block *sb;
  5827. + aufs_bindex_t bend, bindex;
  5828. +
  5829. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
  5830. + inode = dentry->d_inode;
  5831. + IMustLock(inode);
  5832. +
  5833. + err = 0;
  5834. + sb = dentry->d_sb;
  5835. + si_read_lock(sb);
  5836. + if (file) {
  5837. + err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
  5838. + /*locked*/1);
  5839. + //err = -1;
  5840. + if (unlikely(err))
  5841. + goto out;
  5842. + } else
  5843. + di_read_lock_child(dentry, !AUFS_I_WLOCK);
  5844. +
  5845. + ii_write_lock_child(inode);
  5846. + if (file) {
  5847. + bend = fbend(file);
  5848. + for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
  5849. + hidden_file = au_h_fptr_i(file, bindex);
  5850. + if (!hidden_file || test_ro(sb, bindex, inode))
  5851. + continue;
  5852. +
  5853. + err = -EINVAL;
  5854. + if (hidden_file->f_op && hidden_file->f_op->fsync) {
  5855. + // todo: try do_fsync() in fs/sync.c
  5856. +#if 0
  5857. + DEBUG_ON(hidden_file->f_dentry->d_inode
  5858. + != au_h_iptr_i(inode, bindex));
  5859. + hdir_lock(hidden_file->f_dentry->d_inode, inode,
  5860. + bindex);
  5861. +#else
  5862. + i_lock(hidden_file->f_dentry->d_inode);
  5863. +#endif
  5864. + err = hidden_file->f_op->fsync
  5865. + (hidden_file, hidden_file->f_dentry,
  5866. + datasync);
  5867. + //err = -1;
  5868. +#if 0
  5869. + hdir_unlock(hidden_file->f_dentry->d_inode,
  5870. + inode, bindex);
  5871. +#else
  5872. + i_unlock(hidden_file->f_dentry->d_inode);
  5873. +#endif
  5874. + }
  5875. + }
  5876. + } else
  5877. + err = fsync_dir(dentry, datasync);
  5878. + au_cpup_attr_timesizes(inode);
  5879. + ii_write_unlock(inode);
  5880. + if (file)
  5881. + fi_write_unlock(file);
  5882. + else
  5883. + di_read_unlock(dentry, !AUFS_I_WLOCK);
  5884. +
  5885. + out:
  5886. + si_read_unlock(sb);
  5887. + TraceErr(err);
  5888. + return err;
  5889. +}
  5890. +
  5891. +/* ---------------------------------------------------------------------- */
  5892. +
  5893. +static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
  5894. +{
  5895. + int err;
  5896. + struct dentry *dentry;
  5897. + struct inode *inode;
  5898. + struct super_block *sb;
  5899. +
  5900. + dentry = file->f_dentry;
  5901. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  5902. + inode = dentry->d_inode;
  5903. + IMustLock(inode);
  5904. +
  5905. + au_nfsd_lockdep_off();
  5906. + sb = dentry->d_sb;
  5907. + si_read_lock(sb);
  5908. + err = au_reval_and_lock_finfo(file, reopen_dir, /*wlock*/1,
  5909. + /*locked*/1);
  5910. + if (unlikely(err))
  5911. + goto out;
  5912. +
  5913. + ii_write_lock_child(inode);
  5914. + err = au_init_vdir(file);
  5915. + if (unlikely(err)) {
  5916. + ii_write_unlock(inode);
  5917. + goto out_unlock;
  5918. + }
  5919. + //DbgVdir(fvdir_cache(file));// goto out_unlock;
  5920. +
  5921. + /* nfsd filldir calls lookup_one_len(). */
  5922. + ii_downgrade_lock(inode);
  5923. + err = au_fill_de(file, dirent, filldir);
  5924. + //DbgVdir(fvdir_cache(file));// goto out_unlock;
  5925. +
  5926. + inode->i_atime = au_h_iptr(inode)->i_atime;
  5927. + ii_read_unlock(inode);
  5928. +
  5929. + out_unlock:
  5930. + fi_write_unlock(file);
  5931. + out:
  5932. + si_read_unlock(sb);
  5933. + au_nfsd_lockdep_on();
  5934. +#if 0 // debug
  5935. + if (LktrCond)
  5936. + igrab(inode);
  5937. +#endif
  5938. + TraceErr(err);
  5939. + return err;
  5940. +}
  5941. +
  5942. +/* ---------------------------------------------------------------------- */
  5943. +
  5944. +struct test_empty_arg {
  5945. + struct aufs_nhash *whlist;
  5946. + int whonly;
  5947. + aufs_bindex_t bindex;
  5948. + int err, called;
  5949. +};
  5950. +
  5951. +static int test_empty_cb(void *__arg, const char *__name, int namelen,
  5952. + loff_t offset, filldir_ino_t ino, unsigned int d_type)
  5953. +{
  5954. + struct test_empty_arg *arg = __arg;
  5955. + char *name = (void*)__name;
  5956. +
  5957. + LKTRTrace("%.*s\n", namelen, name);
  5958. +
  5959. + arg->err = 0;
  5960. + arg->called++;
  5961. + //smp_mb();
  5962. + if (name[0] == '.'
  5963. + && (namelen == 1 || (name[1] == '.' && namelen == 2)))
  5964. + return 0; /* success */
  5965. +
  5966. + if (namelen <= AUFS_WH_PFX_LEN
  5967. + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
  5968. + if (arg->whonly && !test_known_wh(arg->whlist, name, namelen))
  5969. + arg->err = -ENOTEMPTY;
  5970. + goto out;
  5971. + }
  5972. +
  5973. + name += AUFS_WH_PFX_LEN;
  5974. + namelen -= AUFS_WH_PFX_LEN;
  5975. + if (!test_known_wh(arg->whlist, name, namelen))
  5976. + arg->err = append_wh(arg->whlist, name, namelen, arg->bindex);
  5977. +
  5978. + out:
  5979. + //smp_mb();
  5980. + TraceErr(arg->err);
  5981. + return arg->err;
  5982. +}
  5983. +
  5984. +static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
  5985. +{
  5986. + int err, dlgt;
  5987. + struct file *hidden_file;
  5988. +
  5989. + LKTRTrace("%.*s, {%p, %d, %d}\n",
  5990. + DLNPair(dentry), arg->whlist, arg->whonly, arg->bindex);
  5991. +
  5992. + hidden_file = hidden_open(dentry, arg->bindex,
  5993. + O_RDONLY | O_NONBLOCK | O_DIRECTORY
  5994. + | O_LARGEFILE);
  5995. + err = PTR_ERR(hidden_file);
  5996. + if (IS_ERR(hidden_file))
  5997. + goto out;
  5998. +
  5999. + dlgt = need_dlgt(dentry->d_sb);
  6000. + //hidden_file->f_pos = 0;
  6001. + do {
  6002. + arg->err = 0;
  6003. + arg->called = 0;
  6004. + //smp_mb();
  6005. + err = vfsub_readdir(hidden_file, test_empty_cb, arg, dlgt);
  6006. + if (err >= 0)
  6007. + err = arg->err;
  6008. + } while (!err && arg->called);
  6009. + fput(hidden_file);
  6010. + sbr_put(dentry->d_sb, arg->bindex);
  6011. +
  6012. + out:
  6013. + TraceErr(err);
  6014. + return err;
  6015. +}
  6016. +
  6017. +struct do_test_empty_args {
  6018. + int *errp;
  6019. + struct dentry *dentry;
  6020. + struct test_empty_arg *arg;
  6021. +};
  6022. +
  6023. +static void call_do_test_empty(void *args)
  6024. +{
  6025. + struct do_test_empty_args *a = args;
  6026. + *a->errp = do_test_empty(a->dentry, a->arg);
  6027. +}
  6028. +
  6029. +static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
  6030. +{
  6031. + int err;
  6032. + struct dentry *hidden_dentry;
  6033. + struct inode *hidden_inode;
  6034. +
  6035. + LKTRTrace("%.*s\n", DLNPair(dentry));
  6036. + hidden_dentry = au_h_dptr_i(dentry, arg->bindex);
  6037. + DEBUG_ON(!hidden_dentry);
  6038. + hidden_inode = hidden_dentry->d_inode;
  6039. + DEBUG_ON(!hidden_inode || !S_ISDIR(hidden_inode->i_mode));
  6040. +
  6041. + hi_lock_child(hidden_inode);
  6042. + err = au_test_perm(hidden_inode, MAY_EXEC | MAY_READ,
  6043. + need_dlgt(dentry->d_sb));
  6044. + i_unlock(hidden_inode);
  6045. + if (!err)
  6046. + err = do_test_empty(dentry, arg);
  6047. + else {
  6048. + struct do_test_empty_args args = {
  6049. + .errp = &err,
  6050. + .dentry = dentry,
  6051. + .arg = arg
  6052. + };
  6053. + au_wkq_wait(call_do_test_empty, &args, /*dlgt*/0);
  6054. + }
  6055. +
  6056. + TraceErr(err);
  6057. + return err;
  6058. +}
  6059. +
  6060. +int au_test_empty_lower(struct dentry *dentry)
  6061. +{
  6062. + int err;
  6063. + struct inode *inode;
  6064. + struct test_empty_arg arg;
  6065. + struct aufs_nhash *whlist;
  6066. + aufs_bindex_t bindex, bstart, btail;
  6067. +
  6068. + LKTRTrace("%.*s\n", DLNPair(dentry));
  6069. + inode = dentry->d_inode;
  6070. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  6071. +
  6072. + whlist = nhash_new(GFP_KERNEL);
  6073. + err = PTR_ERR(whlist);
  6074. + if (IS_ERR(whlist))
  6075. + goto out;
  6076. +
  6077. + bstart = dbstart(dentry);
  6078. + arg.whlist = whlist;
  6079. + arg.whonly = 0;
  6080. + arg.bindex = bstart;
  6081. + err = do_test_empty(dentry, &arg);
  6082. + if (unlikely(err))
  6083. + goto out_whlist;
  6084. +
  6085. + arg.whonly = 1;
  6086. + btail = dbtaildir(dentry);
  6087. + for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
  6088. + struct dentry *hidden_dentry;
  6089. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  6090. + if (hidden_dentry && hidden_dentry->d_inode) {
  6091. + DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
  6092. + arg.bindex = bindex;
  6093. + err = do_test_empty(dentry, &arg);
  6094. + }
  6095. + }
  6096. +
  6097. + out_whlist:
  6098. + nhash_del(whlist);
  6099. + out:
  6100. + TraceErr(err);
  6101. + return err;
  6102. +}
  6103. +
  6104. +int test_empty(struct dentry *dentry, struct aufs_nhash *whlist)
  6105. +{
  6106. + int err;
  6107. + struct inode *inode;
  6108. + struct test_empty_arg arg;
  6109. + aufs_bindex_t bindex, btail;
  6110. +
  6111. + LKTRTrace("%.*s\n", DLNPair(dentry));
  6112. + inode = dentry->d_inode;
  6113. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  6114. +
  6115. + err = 0;
  6116. + arg.whlist = whlist;
  6117. + arg.whonly = 1;
  6118. + btail = dbtaildir(dentry);
  6119. + for (bindex = dbstart(dentry); !err && bindex <= btail; bindex++) {
  6120. + struct dentry *hidden_dentry;
  6121. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  6122. + if (hidden_dentry && hidden_dentry->d_inode) {
  6123. + DEBUG_ON(!S_ISDIR(hidden_dentry->d_inode->i_mode));
  6124. + arg.bindex = bindex;
  6125. + err = sio_test_empty(dentry, &arg);
  6126. + }
  6127. + }
  6128. +
  6129. + TraceErr(err);
  6130. + return err;
  6131. +}
  6132. +
  6133. +/* ---------------------------------------------------------------------- */
  6134. +
  6135. +void au_add_nlink(struct inode *dir, struct inode *h_dir)
  6136. +{
  6137. + DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
  6138. + dir->i_nlink += h_dir->i_nlink - 2;
  6139. + if (unlikely(h_dir->i_nlink < 2))
  6140. + dir->i_nlink += 2;
  6141. +}
  6142. +
  6143. +void au_sub_nlink(struct inode *dir, struct inode *h_dir)
  6144. +{
  6145. + DEBUG_ON(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
  6146. + dir->i_nlink -= h_dir->i_nlink - 2;
  6147. + if (unlikely(h_dir->i_nlink < 2))
  6148. + dir->i_nlink -= 2;
  6149. +}
  6150. +
  6151. +/* ---------------------------------------------------------------------- */
  6152. +
  6153. +#if 0 // comment
  6154. +struct file_operations {
  6155. + struct module *owner;
  6156. + loff_t (*llseek) (struct file *, loff_t, int);
  6157. + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
  6158. + ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
  6159. + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
  6160. + ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
  6161. + int (*readdir) (struct file *, void *, filldir_t);
  6162. + unsigned int (*poll) (struct file *, struct poll_table_struct *);
  6163. + int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
  6164. + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
  6165. + long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
  6166. + int (*mmap) (struct file *, struct vm_area_struct *);
  6167. + int (*open) (struct inode *, struct file *);
  6168. + int (*flush) (struct file *);
  6169. + int (*release) (struct inode *, struct file *);
  6170. + int (*fsync) (struct file *, struct dentry *, int datasync);
  6171. + int (*aio_fsync) (struct kiocb *, int datasync);
  6172. + int (*fasync) (int, struct file *, int);
  6173. + int (*lock) (struct file *, int, struct file_lock *);
  6174. + ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
  6175. + ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
  6176. + ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
  6177. + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
  6178. + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
  6179. + int (*check_flags)(int);
  6180. + int (*dir_notify)(struct file *file, unsigned long arg);
  6181. + int (*flock) (struct file *, int, struct file_lock *);
  6182. +};
  6183. +#endif
  6184. +
  6185. +struct file_operations aufs_dir_fop = {
  6186. + .read = generic_read_dir,
  6187. + .readdir = aufs_readdir,
  6188. + .open = aufs_open_dir,
  6189. + .release = aufs_release_dir,
  6190. + .flush = aufs_flush,
  6191. + .fsync = aufs_fsync_dir,
  6192. +};
  6193. diff --git a/fs/aufs/dir.h b/fs/aufs/dir.h
  6194. new file mode 100755
  6195. index 0000000..3ddf309
  6196. --- /dev/null
  6197. +++ b/fs/aufs/dir.h
  6198. @@ -0,0 +1,125 @@
  6199. +/*
  6200. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  6201. + *
  6202. + * This program, aufs is free software; you can redistribute it and/or modify
  6203. + * it under the terms of the GNU General Public License as published by
  6204. + * the Free Software Foundation; either version 2 of the License, or
  6205. + * (at your option) any later version.
  6206. + *
  6207. + * This program is distributed in the hope that it will be useful,
  6208. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  6209. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  6210. + * GNU General Public License for more details.
  6211. + *
  6212. + * You should have received a copy of the GNU General Public License
  6213. + * along with this program; if not, write to the Free Software
  6214. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  6215. + */
  6216. +
  6217. +/* $Id: dir.h,v 1.18 2007/05/14 03:41:52 sfjro Exp $ */
  6218. +
  6219. +#ifndef __AUFS_DIR_H__
  6220. +#define __AUFS_DIR_H__
  6221. +
  6222. +#ifdef __KERNEL__
  6223. +
  6224. +#include <linux/fs.h>
  6225. +#include <linux/version.h>
  6226. +#include <linux/aufs_type.h>
  6227. +
  6228. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
  6229. +#define filldir_ino_t u64
  6230. +#else
  6231. +#define filldir_ino_t ino_t
  6232. +#endif
  6233. +
  6234. +/* ---------------------------------------------------------------------- */
  6235. +
  6236. +/* need to be faster and smaller */
  6237. +
  6238. +#define AUFS_DEBLK_SIZE 512 // todo: changable
  6239. +#define AUFS_NHASH_SIZE 32 // todo: changable
  6240. +#if AUFS_DEBLK_SIZE < NAME_MAX || PAGE_SIZE < AUFS_DEBLK_SIZE
  6241. +#error invalid size AUFS_DEBLK_SIZE
  6242. +#endif
  6243. +
  6244. +typedef char aufs_deblk_t[AUFS_DEBLK_SIZE];
  6245. +
  6246. +struct aufs_nhash {
  6247. + struct hlist_head heads[AUFS_NHASH_SIZE];
  6248. +};
  6249. +
  6250. +struct aufs_destr {
  6251. + unsigned char len;
  6252. + char name[0];
  6253. +} __attribute__ ((packed));
  6254. +
  6255. +struct aufs_dehstr {
  6256. + struct hlist_node hash;
  6257. + struct aufs_destr *str;
  6258. +};
  6259. +
  6260. +struct aufs_de {
  6261. + ino_t de_ino;
  6262. + unsigned char de_type;
  6263. + //caution: packed
  6264. + struct aufs_destr de_str;
  6265. +} __attribute__ ((packed));
  6266. +
  6267. +struct aufs_wh {
  6268. + struct hlist_node wh_hash;
  6269. + aufs_bindex_t wh_bindex;
  6270. + struct aufs_destr wh_str;
  6271. +} __attribute__ ((packed));
  6272. +
  6273. +union aufs_deblk_p {
  6274. + unsigned char *p;
  6275. + aufs_deblk_t *deblk;
  6276. + struct aufs_de *de;
  6277. +};
  6278. +
  6279. +struct aufs_vdir {
  6280. + aufs_deblk_t **vd_deblk;
  6281. + int vd_nblk;
  6282. + struct {
  6283. + int i;
  6284. + union aufs_deblk_p p;
  6285. + } vd_last;
  6286. +
  6287. + unsigned long vd_version;
  6288. + unsigned long vd_jiffy;
  6289. +};
  6290. +
  6291. +/* ---------------------------------------------------------------------- */
  6292. +
  6293. +/* dir.c */
  6294. +extern struct file_operations aufs_dir_fop;
  6295. +int au_test_empty_lower(struct dentry *dentry);
  6296. +int test_empty(struct dentry *dentry, struct aufs_nhash *whlist);
  6297. +void au_add_nlink(struct inode *dir, struct inode *h_dir);
  6298. +void au_sub_nlink(struct inode *dir, struct inode *h_dir);
  6299. +
  6300. +/* vdir.c */
  6301. +struct aufs_nhash *nhash_new(gfp_t gfp);
  6302. +void nhash_del(struct aufs_nhash *nhash);
  6303. +void nhash_init(struct aufs_nhash *nhash);
  6304. +void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src);
  6305. +void nhash_fin(struct aufs_nhash *nhash);
  6306. +int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit);
  6307. +int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen);
  6308. +int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
  6309. + aufs_bindex_t bindex);
  6310. +void free_vdir(struct aufs_vdir *vdir);
  6311. +int au_init_vdir(struct file *file);
  6312. +int au_fill_de(struct file *file, void *dirent, filldir_t filldir);
  6313. +
  6314. +/* ---------------------------------------------------------------------- */
  6315. +
  6316. +static inline
  6317. +unsigned int au_name_hash(const unsigned char *name, unsigned int len)
  6318. +{
  6319. + return (full_name_hash(name, len) % AUFS_NHASH_SIZE);
  6320. +}
  6321. +
  6322. +#endif /* __KERNEL__ */
  6323. +#endif /* __AUFS_DIR_H__ */
  6324. diff --git a/fs/aufs/export.c b/fs/aufs/export.c
  6325. new file mode 100755
  6326. index 0000000..7b1c6ac
  6327. --- /dev/null
  6328. +++ b/fs/aufs/export.c
  6329. @@ -0,0 +1,585 @@
  6330. +/*
  6331. + * Copyright (C) 2007 Junjiro Okajima
  6332. + *
  6333. + * This program, aufs is free software; you can redistribute it and/or modify
  6334. + * it under the terms of the GNU General Public License as published by
  6335. + * the Free Software Foundation; either version 2 of the License, or
  6336. + * (at your option) any later version.
  6337. + *
  6338. + * This program is distributed in the hope that it will be useful,
  6339. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  6340. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  6341. + * GNU General Public License for more details.
  6342. + *
  6343. + * You should have received a copy of the GNU General Public License
  6344. + * along with this program; if not, write to the Free Software
  6345. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  6346. + */
  6347. +
  6348. +/* $Id: export.c,v 1.7 2007/05/14 03:38:24 sfjro Exp $ */
  6349. +
  6350. +#include "aufs.h"
  6351. +
  6352. +extern struct export_operations export_op_default;
  6353. +#define CALL(ops, func) (((ops)->func) ? ((ops)->func) : export_op_default.func)
  6354. +#define is_anon(d) ((d)->d_flags & DCACHE_DISCONNECTED)
  6355. +
  6356. +union conv {
  6357. +#if BITS_PER_LONG == 32
  6358. + __u32 a[1];
  6359. +#else
  6360. + __u32 a[2];
  6361. +#endif
  6362. + ino_t ino;
  6363. +};
  6364. +
  6365. +static ino_t decode_ino(__u32 *a)
  6366. +{
  6367. + union conv u;
  6368. + u.a[0] = a[0];
  6369. +#if BITS_PER_LONG == 64
  6370. + u.a[1] = a[1];
  6371. +#endif
  6372. + return u.ino;
  6373. +}
  6374. +
  6375. +static void encode_ino(__u32 *a, ino_t ino)
  6376. +{
  6377. + union conv u;
  6378. + u.ino = ino;
  6379. + a[0] = u.a[0];
  6380. +#if BITS_PER_LONG == 64
  6381. + a[1] = u.a[1];
  6382. +#endif
  6383. +}
  6384. +
  6385. +static void decode_br_id_sigen(__u32 a, aufs_bindex_t *br_id,
  6386. + aufs_bindex_t *sigen)
  6387. +{
  6388. + BUILD_BUG_ON((sizeof(*br_id) + sizeof(*sigen)) > sizeof(a));
  6389. + *br_id = a >> 16;
  6390. + DEBUG_ON(*br_id < 0);
  6391. + *sigen = a;
  6392. + DEBUG_ON(*sigen < 0);
  6393. +}
  6394. +
  6395. +static __u32 encode_br_id_sigen(aufs_bindex_t br_id, aufs_bindex_t sigen)
  6396. +{
  6397. + DEBUG_ON(br_id < 0 || sigen < 0);
  6398. + return (br_id << 16) | sigen;
  6399. +}
  6400. +
  6401. +/* NFS file handle */
  6402. +enum {
  6403. + /* support 64bit inode number */
  6404. + /* but untested */
  6405. + Fh_br_id_sigen,
  6406. + Fh_ino1,
  6407. +#if BITS_PER_LONG == 64
  6408. + Fh_ino2,
  6409. +#endif
  6410. + Fh_dir_ino1,
  6411. +#if BITS_PER_LONG == 64
  6412. + Fh_dir_ino2,
  6413. +#endif
  6414. + Fh_h_ino1,
  6415. +#if BITS_PER_LONG == 64
  6416. + Fh_h_ino2,
  6417. +#endif
  6418. + Fh_h_igen,
  6419. + Fh_h_type,
  6420. + Fh_tail,
  6421. +
  6422. + Fh_ino = Fh_ino1,
  6423. + Fh_dir_ino = Fh_dir_ino1,
  6424. + Fh_h_ino = Fh_h_ino1,
  6425. +};
  6426. +
  6427. +/* ---------------------------------------------------------------------- */
  6428. +
  6429. +static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
  6430. + ino_t dir_ino)
  6431. +{
  6432. + struct dentry *dentry;
  6433. + struct inode *inode;
  6434. +
  6435. + LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
  6436. +
  6437. + dentry = NULL;
  6438. + inode = ilookup(sb, ino);
  6439. + if (unlikely(!inode))
  6440. + goto out;
  6441. +
  6442. + dentry = ERR_PTR(-ESTALE);
  6443. + if (unlikely(is_bad_inode(inode)))
  6444. + goto out_iput;
  6445. +
  6446. + dentry = NULL;
  6447. + if (!S_ISDIR(inode->i_mode)) {
  6448. + struct dentry *d;
  6449. + spin_lock(&dcache_lock);
  6450. + list_for_each_entry(d, &inode->i_dentry, d_alias)
  6451. + if (!is_anon(d)
  6452. + && d->d_parent->d_inode->i_ino == dir_ino) {
  6453. + dentry = dget_locked(d);
  6454. + break;
  6455. + }
  6456. + spin_unlock(&dcache_lock);
  6457. + } else {
  6458. + dentry = d_find_alias(inode);
  6459. + if (dentry
  6460. + && !is_anon(dentry)
  6461. + && dentry->d_parent->d_inode->i_ino == dir_ino)
  6462. + goto out_iput; /* success */
  6463. +
  6464. + dput(dentry);
  6465. + dentry = NULL;
  6466. + }
  6467. +
  6468. + out_iput:
  6469. + iput(inode);
  6470. + out:
  6471. + TraceErrPtr(dentry);
  6472. + return dentry;
  6473. +}
  6474. +
  6475. +/* ---------------------------------------------------------------------- */
  6476. +
  6477. +struct find_name_by_ino {
  6478. + int called, found;
  6479. + ino_t ino;
  6480. + char *name;
  6481. + int namelen;
  6482. +};
  6483. +
  6484. +static int
  6485. +find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
  6486. + filldir_ino_t ino, unsigned int d_type)
  6487. +{
  6488. + struct find_name_by_ino *a = arg;
  6489. +
  6490. + a->called++;
  6491. + if (a->ino != ino)
  6492. + return 0;
  6493. +
  6494. + memcpy(a->name, name, namelen);
  6495. + a->namelen = namelen;
  6496. + a->found = 1;
  6497. + return 1;
  6498. +}
  6499. +
  6500. +static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
  6501. + ino_t dir_ino)
  6502. +{
  6503. + struct dentry *dentry, *parent;
  6504. + struct inode *dir;
  6505. + struct find_name_by_ino arg;
  6506. + struct file *file;
  6507. + int err;
  6508. +
  6509. + LKTRTrace("i%lu, diri%lu\n", ino, dir_ino);
  6510. +
  6511. + dentry = NULL;
  6512. + dir = ilookup(sb, dir_ino);
  6513. + if (unlikely(!dir))
  6514. + goto out;
  6515. +
  6516. + dentry = ERR_PTR(-ESTALE);
  6517. + if (unlikely(is_bad_inode(dir)))
  6518. + goto out_iput;
  6519. +
  6520. + dentry = NULL;
  6521. + parent = d_find_alias(dir);
  6522. + if (parent) {
  6523. + if (unlikely(is_anon(parent))) {
  6524. + dput(parent);
  6525. + goto out_iput;
  6526. + }
  6527. + } else
  6528. + goto out_iput;
  6529. +
  6530. + file = dentry_open(parent, NULL, au_dir_roflags);
  6531. + dentry = (void*)file;
  6532. + if (IS_ERR(file))
  6533. + goto out_iput;
  6534. +
  6535. + dentry = ERR_PTR(-ENOMEM);
  6536. + arg.name = __getname();
  6537. + if (unlikely(!arg.name))
  6538. + goto out_fput;
  6539. + arg.ino = ino;
  6540. + arg.found = 0;
  6541. +
  6542. + do {
  6543. + arg.called = 0;
  6544. + //smp_mb();
  6545. + err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
  6546. + } while (!err && !arg.found && arg.called);
  6547. + dentry = ERR_PTR(err);
  6548. + if (arg.found) {
  6549. + /* do not call lkup_one(), nor dlgt */
  6550. + i_lock(dir);
  6551. + dentry = lookup_one_len(arg.name, parent, arg.namelen);
  6552. + i_unlock(dir);
  6553. + TraceErrPtr(dentry);
  6554. + }
  6555. +
  6556. + //out_putname:
  6557. + __putname(arg.name);
  6558. + out_fput:
  6559. + fput(file);
  6560. + out_iput:
  6561. + iput(dir);
  6562. + out:
  6563. + TraceErrPtr(dentry);
  6564. + return dentry;
  6565. +}
  6566. +
  6567. +/* ---------------------------------------------------------------------- */
  6568. +
  6569. +struct append_name {
  6570. + int found, called, len;
  6571. + char *h_path;
  6572. + ino_t h_ino;
  6573. +};
  6574. +
  6575. +static int append_name(void *arg, const char *name, int len, loff_t pos,
  6576. + filldir_ino_t ino, unsigned int d_type)
  6577. +{
  6578. + struct append_name *a = arg;
  6579. + char *p;
  6580. +
  6581. + a->called++;
  6582. + if (ino != a->h_ino)
  6583. + return 0;
  6584. +
  6585. + DEBUG_ON(len == 1 && *name == '.');
  6586. + DEBUG_ON(len == 2 && name[0] == '.' && name[1] == '.');
  6587. + a->len = strlen(a->h_path);
  6588. + memmove(a->h_path - a->len - 1, a->h_path, a->len);
  6589. + a->h_path -= a->len + 1;
  6590. + p = a->h_path + a->len;
  6591. + *p++ = '/';
  6592. + memcpy(p, name, a->len);
  6593. + a->len += 1 + len;
  6594. + a->found++;
  6595. + return 1;
  6596. +}
  6597. +
  6598. +static int h_acceptable(void *expv, struct dentry *dentry)
  6599. +{
  6600. + return 1;
  6601. +}
  6602. +
  6603. +static struct dentry*
  6604. +decode_by_path(struct super_block *sb, aufs_bindex_t bindex, __u32 *fh,
  6605. + int fh_len, void *context)
  6606. +{
  6607. + struct dentry *dentry, *h_parent, *root, *h_root;
  6608. + struct super_block *h_sb;
  6609. + char *path, *p;
  6610. + struct vfsmount *h_mnt;
  6611. + struct append_name arg;
  6612. + int len, err;
  6613. + struct file *h_file;
  6614. + struct nameidata nd;
  6615. + struct aufs_branch *br;
  6616. +
  6617. + LKTRTrace("b%d\n", bindex);
  6618. + SiMustAnyLock(sb);
  6619. +
  6620. + br = stobr(sb, bindex);
  6621. + //br_get(br);
  6622. + h_mnt = br->br_mnt;
  6623. + h_sb = h_mnt->mnt_sb;
  6624. + LKTRTrace("%s, h_decode_fh\n", au_sbtype(h_sb));
  6625. + h_parent = CALL(h_sb->s_export_op, decode_fh)
  6626. + (h_sb, fh + Fh_tail, fh_len - Fh_tail, fh[Fh_h_type],
  6627. + h_acceptable, /*context*/NULL);
  6628. + dentry = h_parent;
  6629. + if (unlikely(!h_parent || IS_ERR(h_parent))) {
  6630. + Warn1("%s decode_fh failed\n", au_sbtype(h_sb));
  6631. + goto out;
  6632. + }
  6633. + dentry = NULL;
  6634. + if (unlikely(is_anon(h_parent))) {
  6635. + Warn1("%s decode_fh returned a disconnected dentry\n",
  6636. + au_sbtype(h_sb));
  6637. + dput(h_parent);
  6638. + goto out;
  6639. + }
  6640. +
  6641. + dentry = ERR_PTR(-ENOMEM);
  6642. + path = __getname();
  6643. + if (unlikely(!path)) {
  6644. + dput(h_parent);
  6645. + goto out;
  6646. + }
  6647. +
  6648. + root = sb->s_root;
  6649. + di_read_lock_parent(root, !AUFS_I_RLOCK);
  6650. + h_root = au_h_dptr_i(root, bindex);
  6651. + di_read_unlock(root, !AUFS_I_RLOCK);
  6652. + arg.h_path = d_path(h_root, h_mnt, path, PATH_MAX);
  6653. + dentry = (void*)arg.h_path;
  6654. + if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
  6655. + goto out_putname;
  6656. + len = strlen(arg.h_path);
  6657. + arg.h_path = d_path(h_parent, h_mnt, path, PATH_MAX);
  6658. + dentry = (void*)arg.h_path;
  6659. + if (unlikely(!arg.h_path || IS_ERR(arg.h_path)))
  6660. + goto out_putname;
  6661. + LKTRTrace("%s\n", arg.h_path);
  6662. + if (len != 1)
  6663. + arg.h_path += len;
  6664. + LKTRTrace("%s\n", arg.h_path);
  6665. +
  6666. + /* cf. fs/exportfs/expfs.c */
  6667. + h_file = dentry_open(h_parent, NULL, au_dir_roflags);
  6668. + dentry = (void*)h_file;
  6669. + if (IS_ERR(h_file))
  6670. + goto out_putname;
  6671. +
  6672. + arg.found = 0;
  6673. + arg.h_ino = decode_ino(fh + Fh_h_ino);
  6674. + do {
  6675. + arg.called = 0;
  6676. + err = vfsub_readdir(h_file, append_name, &arg, /*dlgt*/0);
  6677. + } while (!err && !arg.found && arg.called);
  6678. + LKTRTrace("%s, %d\n", arg.h_path, arg.len);
  6679. +
  6680. + p = d_path(root, stosi(sb)->si_mnt, path, PATH_MAX - arg.len - 2);
  6681. + dentry = (void*)p;
  6682. + if (unlikely(!p || IS_ERR(p)))
  6683. + goto out_fput;
  6684. + p[strlen(p)] = '/';
  6685. + LKTRTrace("%s\n", p);
  6686. +
  6687. + err = path_lookup(p, LOOKUP_FOLLOW, &nd);
  6688. + dentry = ERR_PTR(err);
  6689. + if (!err) {
  6690. + dentry = dget(nd.dentry);
  6691. + if (unlikely(is_anon(dentry))) {
  6692. + dput(dentry);
  6693. + dentry = ERR_PTR(-ESTALE);
  6694. + }
  6695. + path_release(&nd);
  6696. + }
  6697. +
  6698. + out_fput:
  6699. + fput(h_file);
  6700. + out_putname:
  6701. + __putname(path);
  6702. + out:
  6703. + //br_put(br);
  6704. + TraceErrPtr(dentry);
  6705. + return dentry;
  6706. +}
  6707. +
  6708. +/* ---------------------------------------------------------------------- */
  6709. +
  6710. +static struct dentry*
  6711. +aufs_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
  6712. + int (*acceptable)(void *context, struct dentry *de),
  6713. + void *context)
  6714. +{
  6715. + struct dentry *dentry;
  6716. + ino_t ino, dir_ino;
  6717. + aufs_bindex_t bindex, br_id, sigen_v;
  6718. + struct inode *inode, *h_inode;
  6719. +
  6720. + //au_debug_on();
  6721. + LKTRTrace("%d, fh{i%u, br_id_sigen 0x%x, hi%u}\n",
  6722. + fh_type, fh[Fh_ino], fh[Fh_br_id_sigen], fh[Fh_h_ino]);
  6723. + DEBUG_ON(fh_len < Fh_tail);
  6724. +
  6725. + si_read_lock(sb);
  6726. + lockdep_off();
  6727. +
  6728. + /* branch id may be wrapped around */
  6729. + dentry = ERR_PTR(-ESTALE);
  6730. + decode_br_id_sigen(fh[Fh_br_id_sigen], &br_id, &sigen_v);
  6731. + bindex = find_brindex(sb, br_id);
  6732. + if (unlikely(bindex < 0 || au_sigen(sb) < sigen_v))
  6733. + goto out;
  6734. +
  6735. + /* is this inode still cached? */
  6736. + ino = decode_ino(fh + Fh_ino);
  6737. + dir_ino = decode_ino(fh + Fh_dir_ino);
  6738. + dentry = decode_by_ino(sb, ino, dir_ino);
  6739. + if (IS_ERR(dentry))
  6740. + goto out;
  6741. + if (dentry)
  6742. + goto accept;
  6743. +
  6744. + /* is the parent dir cached? */
  6745. + dentry = decode_by_dir_ino(sb, ino, dir_ino);
  6746. + if (IS_ERR(dentry))
  6747. + goto out;
  6748. + if (dentry)
  6749. + goto accept;
  6750. +
  6751. + /* lookup path */
  6752. + dentry = decode_by_path(sb, bindex, fh, fh_len, context);
  6753. + if (IS_ERR(dentry))
  6754. + goto out;
  6755. + if (unlikely(!dentry))
  6756. + goto out_stale;
  6757. + if (unlikely(dentry->d_inode->i_ino != ino))
  6758. + goto out_dput;
  6759. +
  6760. + accept:
  6761. + inode = dentry->d_inode;
  6762. + h_inode = NULL;
  6763. + ii_read_lock_child(inode);
  6764. + if (ibstart(inode) <= bindex && bindex <= ibend(inode))
  6765. + h_inode = au_h_iptr_i(inode, bindex);
  6766. + ii_read_unlock(inode);
  6767. + if (h_inode
  6768. + && h_inode->i_generation == fh[Fh_h_igen]
  6769. + && acceptable(context, dentry))
  6770. + goto out; /* success */
  6771. + out_dput:
  6772. + dput(dentry);
  6773. + out_stale:
  6774. + dentry = ERR_PTR(-ESTALE);
  6775. + out:
  6776. + lockdep_on();
  6777. + si_read_unlock(sb);
  6778. + TraceErrPtr(dentry);
  6779. + //au_debug_off();
  6780. + return dentry;
  6781. +}
  6782. +
  6783. +/* ---------------------------------------------------------------------- */
  6784. +
  6785. +static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
  6786. + int connectable)
  6787. +{
  6788. + int err;
  6789. + struct super_block *sb, *h_sb;
  6790. + struct inode *inode, *h_inode, *dir;
  6791. + aufs_bindex_t bindex;
  6792. + union conv u;
  6793. + struct dentry *parent, *h_parent;
  6794. +
  6795. + //au_debug_on();
  6796. + BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
  6797. + LKTRTrace("%.*s, max %d, conn %d\n",
  6798. + DLNPair(dentry), *max_len, connectable);
  6799. + DEBUG_ON(is_anon(dentry));
  6800. + inode = dentry->d_inode;
  6801. + DEBUG_ON(!inode);
  6802. + parent = dentry->d_parent;
  6803. + DEBUG_ON(is_anon(parent));
  6804. +
  6805. + err = -ENOSPC;
  6806. + if (unlikely(*max_len <= Fh_tail)) {
  6807. + Warn1("NFSv2 client (max_len %d)?\n", *max_len);
  6808. + goto out;
  6809. + }
  6810. +
  6811. + sb = dentry->d_sb;
  6812. + si_read_lock(sb);
  6813. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  6814. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  6815. +#ifdef CONFIG_AUFS_DEBUG
  6816. + if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
  6817. + Warn1("NFS-exporting requires xino\n");
  6818. +#if 0
  6819. + if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
  6820. + Warn1("udba=inotify is not recommended when exporting\n");
  6821. +#endif
  6822. +#endif
  6823. +
  6824. + err = -EPERM;
  6825. + bindex = ibstart(inode);
  6826. + h_sb = sbr_sb(sb, bindex);
  6827. + if (unlikely(!h_sb->s_export_op)) {
  6828. + Err1("%s branch is not exportable\n", au_sbtype(h_sb));
  6829. + goto out_unlock;
  6830. + }
  6831. +
  6832. +#if 0 //def CONFIG_AUFS_ROBR
  6833. + if (unlikely(SB_AUFS(h_sb))) {
  6834. + Err1("aufs branch is not supported\n");
  6835. + goto out_unlock;
  6836. + }
  6837. +#endif
  6838. +
  6839. + /* doesn't support pseudo-link */
  6840. + if (unlikely(bindex < dbstart(dentry)
  6841. + || dbend(dentry) < bindex
  6842. + || !au_h_dptr_i(dentry, bindex))) {
  6843. + Err("%.*s/%.*s, b%d, pseudo-link?\n",
  6844. + DLNPair(dentry->d_parent), DLNPair(dentry), bindex);
  6845. + goto out_unlock;
  6846. + }
  6847. +
  6848. + fh[Fh_br_id_sigen] = encode_br_id_sigen(sbr_id(sb, bindex),
  6849. + au_sigen(sb));
  6850. + encode_ino(fh + Fh_ino, inode->i_ino);
  6851. + dir = parent->d_inode;
  6852. + encode_ino(fh + Fh_dir_ino, dir->i_ino);
  6853. + h_inode = au_h_iptr(inode);
  6854. + encode_ino(fh + Fh_h_ino, h_inode->i_ino);
  6855. + fh[Fh_h_igen] = h_inode->i_generation;
  6856. +
  6857. + /* it should be set at exporting time */
  6858. + if (unlikely(!h_sb->s_export_op->find_exported_dentry)) {
  6859. + Warn("set default find_exported_dentry for %s\n",
  6860. + au_sbtype(h_sb));
  6861. + h_sb->s_export_op->find_exported_dentry = find_exported_dentry;
  6862. + }
  6863. +
  6864. + *max_len -= Fh_tail;
  6865. + //LKTRTrace("Fh_tail %d, max_len %d\n", Fh_tail, *max_len);
  6866. + h_parent = au_h_dptr_i(parent, bindex);
  6867. + DEBUG_ON(is_anon(h_parent));
  6868. + err = fh[Fh_h_type] = CALL(h_sb->s_export_op, encode_fh)
  6869. + (h_parent, fh + Fh_tail, max_len, connectable);
  6870. + *max_len += Fh_tail;
  6871. + if (err != 255)
  6872. + err = 2; //??
  6873. + else
  6874. + Warn1("%s encode_fh failed\n", au_sbtype(h_sb));
  6875. +
  6876. + out_unlock:
  6877. + di_read_unlock(parent, AUFS_I_RLOCK);
  6878. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  6879. + out:
  6880. + TraceErr(err);
  6881. + //au_debug_off();
  6882. + if (unlikely(err < 0))
  6883. + err = 255;
  6884. + return err;
  6885. +}
  6886. +
  6887. +/* ---------------------------------------------------------------------- */
  6888. +
  6889. +#if 0
  6890. +struct export_operations {
  6891. + struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type,
  6892. + int (*acceptable)(void *context, struct dentry *de),
  6893. + void *context);
  6894. + int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len,
  6895. + int connectable);
  6896. +
  6897. + /* the following are only called from the filesystem itself */
  6898. + int (*get_name)(struct dentry *parent, char *name,
  6899. + struct dentry *child);
  6900. + struct dentry * (*get_parent)(struct dentry *child);
  6901. + struct dentry * (*get_dentry)(struct super_block *sb, void *inump);
  6902. +
  6903. + /* This is set by the exporting module to a standard helper */
  6904. + struct dentry * (*find_exported_dentry)(
  6905. + struct super_block *sb, void *obj, void *parent,
  6906. + int (*acceptable)(void *context, struct dentry *de),
  6907. + void *context);
  6908. +};
  6909. +#endif
  6910. +
  6911. +struct export_operations aufs_export_op = {
  6912. + .decode_fh = aufs_decode_fh,
  6913. + .encode_fh = aufs_encode_fh
  6914. +};
  6915. diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
  6916. new file mode 100755
  6917. index 0000000..3cd1081
  6918. --- /dev/null
  6919. +++ b/fs/aufs/f_op.c
  6920. @@ -0,0 +1,684 @@
  6921. +/*
  6922. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  6923. + *
  6924. + * This program, aufs is free software; you can redistribute it and/or modify
  6925. + * it under the terms of the GNU General Public License as published by
  6926. + * the Free Software Foundation; either version 2 of the License, or
  6927. + * (at your option) any later version.
  6928. + *
  6929. + * This program is distributed in the hope that it will be useful,
  6930. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  6931. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  6932. + * GNU General Public License for more details.
  6933. + *
  6934. + * You should have received a copy of the GNU General Public License
  6935. + * along with this program; if not, write to the Free Software
  6936. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  6937. + */
  6938. +
  6939. +/* $Id: f_op.c,v 1.27 2007/05/14 03:38:24 sfjro Exp $ */
  6940. +
  6941. +#include <linux/fsnotify.h>
  6942. +#include <linux/pagemap.h>
  6943. +#include <linux/poll.h>
  6944. +#include <linux/security.h>
  6945. +#include <linux/version.h>
  6946. +#include "aufs.h"
  6947. +
  6948. +/* common function to regular file and dir */
  6949. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  6950. +#define FlushArgs hidden_file, id
  6951. +int aufs_flush(struct file *file, fl_owner_t id)
  6952. +#else
  6953. +#define FlushArgs hidden_file
  6954. +int aufs_flush(struct file *file)
  6955. +#endif
  6956. +{
  6957. + int err;
  6958. + struct dentry *dentry;
  6959. + aufs_bindex_t bindex, bend;
  6960. +
  6961. + dentry = file->f_dentry;
  6962. + LKTRTrace("%.*s\n", DLNPair(dentry));
  6963. +
  6964. + // aufs_read_lock_file()
  6965. + si_read_lock(dentry->d_sb);
  6966. + fi_read_lock(file);
  6967. + di_read_lock_child(dentry, !AUFS_I_RLOCK);
  6968. +
  6969. + err = 0;
  6970. + bend = fbend(file);
  6971. + for (bindex = fbstart(file); !err && bindex <= bend; bindex++) {
  6972. + struct file *hidden_file;
  6973. + hidden_file = au_h_fptr_i(file, bindex);
  6974. + if (hidden_file && hidden_file->f_op
  6975. + && hidden_file->f_op->flush)
  6976. + err = hidden_file->f_op->flush(FlushArgs);
  6977. + }
  6978. +
  6979. + di_read_unlock(dentry, !AUFS_I_RLOCK);
  6980. + fi_read_unlock(file);
  6981. + si_read_unlock(dentry->d_sb);
  6982. + TraceErr(err);
  6983. + return err;
  6984. +}
  6985. +#undef FlushArgs
  6986. +
  6987. +/* ---------------------------------------------------------------------- */
  6988. +
  6989. +static int do_open_nondir(struct file *file, int flags)
  6990. +{
  6991. + int err;
  6992. + aufs_bindex_t bindex;
  6993. + struct super_block *sb;
  6994. + struct file *hidden_file;
  6995. + struct dentry *dentry;
  6996. + struct inode *inode;
  6997. + struct aufs_finfo *finfo;
  6998. +
  6999. + dentry = file->f_dentry;
  7000. + LKTRTrace("%.*s, flags 0%o\n", DLNPair(dentry), flags);
  7001. + FiMustWriteLock(file);
  7002. + inode = dentry->d_inode;
  7003. + DEBUG_ON(!inode || S_ISDIR(inode->i_mode));
  7004. +
  7005. + err = 0;
  7006. + finfo = ftofi(file);
  7007. + finfo->fi_h_vm_ops = NULL;
  7008. + sb = dentry->d_sb;
  7009. + bindex = dbstart(dentry);
  7010. + DEBUG_ON(!au_h_dptr(dentry)->d_inode);
  7011. + /* O_TRUNC is processed already */
  7012. + BUG_ON(test_ro(sb, bindex, inode) && (flags & O_TRUNC));
  7013. +
  7014. + hidden_file = hidden_open(dentry, bindex, flags);
  7015. + //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bindex));
  7016. + //hidden_file = ERR_PTR(-1);}
  7017. + if (!IS_ERR(hidden_file)) {
  7018. + set_fbstart(file, bindex);
  7019. + set_fbend(file, bindex);
  7020. + set_h_fptr(file, bindex, hidden_file);
  7021. + return 0; /* success */
  7022. + }
  7023. + err = PTR_ERR(hidden_file);
  7024. + TraceErr(err);
  7025. + return err;
  7026. +}
  7027. +
  7028. +static int aufs_open_nondir(struct inode *inode, struct file *file)
  7029. +{
  7030. + return au_do_open(inode, file, do_open_nondir);
  7031. +}
  7032. +
  7033. +static int aufs_release_nondir(struct inode *inode, struct file *file)
  7034. +{
  7035. + struct super_block *sb = file->f_dentry->d_sb;
  7036. +
  7037. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(file->f_dentry));
  7038. +
  7039. + si_read_lock(sb);
  7040. + au_fin_finfo(file);
  7041. + si_read_unlock(sb);
  7042. + return 0;
  7043. +}
  7044. +
  7045. +/* ---------------------------------------------------------------------- */
  7046. +
  7047. +static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
  7048. + loff_t *ppos)
  7049. +{
  7050. + ssize_t err;
  7051. + struct dentry *dentry;
  7052. + struct file *hidden_file;
  7053. + struct super_block *sb;
  7054. + struct inode *h_inode;
  7055. + int dlgt;
  7056. +
  7057. + dentry = file->f_dentry;
  7058. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  7059. + DLNPair(dentry), (unsigned long)count, *ppos);
  7060. +
  7061. + sb = dentry->d_sb;
  7062. + si_read_lock(sb);
  7063. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7064. + /*locked*/0);
  7065. + //if (LktrCond) {fi_read_unlock(file); err = -1;}
  7066. + if (unlikely(err))
  7067. + goto out;
  7068. +
  7069. + /* support LSM and notify */
  7070. + dlgt = need_dlgt(sb);
  7071. + hidden_file = au_h_fptr(file);
  7072. + h_inode = hidden_file->f_dentry->d_inode;
  7073. + if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
  7074. + err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
  7075. + else {
  7076. + struct inode *dir = dentry->d_parent->d_inode,
  7077. + *h_dir = hidden_file->f_dentry->d_parent->d_inode;
  7078. + aufs_bindex_t bstart = fbstart(file);
  7079. + hdir_lock(h_dir, dir, bstart);
  7080. + err = vfsub_read_u(hidden_file, buf, count, ppos, dlgt);
  7081. + hdir_unlock(h_dir, dir, bstart);
  7082. + }
  7083. + memcpy(&file->f_ra, &hidden_file->f_ra, sizeof(file->f_ra)); //??
  7084. + dentry->d_inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
  7085. +
  7086. + fi_read_unlock(file);
  7087. + out:
  7088. + si_read_unlock(sb);
  7089. + TraceErr(err);
  7090. + return err;
  7091. +}
  7092. +
  7093. +static ssize_t aufs_write(struct file *file, const char __user *__buf,
  7094. + size_t count, loff_t *ppos)
  7095. +{
  7096. + ssize_t err;
  7097. + struct dentry *dentry;
  7098. + struct inode *inode;
  7099. + struct super_block *sb;
  7100. + struct file *hidden_file;
  7101. + char __user *buf = (char __user*)__buf;
  7102. + struct inode *h_inode;
  7103. + int dlgt;
  7104. +
  7105. + dentry = file->f_dentry;
  7106. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  7107. + DLNPair(dentry), (unsigned long)count, *ppos);
  7108. +
  7109. + inode = dentry->d_inode;
  7110. + i_lock(inode);
  7111. + sb = dentry->d_sb;
  7112. + si_read_lock(sb);
  7113. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
  7114. + /*locked*/1);
  7115. + //if (LktrCond) {fi_write_unlock(file); err = -1;}
  7116. + if (unlikely(err))
  7117. + goto out;
  7118. + err = au_ready_to_write(file, -1);
  7119. + //if (LktrCond) err = -1;
  7120. + if (unlikely(err))
  7121. + goto out_unlock;
  7122. +
  7123. + /* support LSM and notify */
  7124. + dlgt = need_dlgt(sb);
  7125. + hidden_file = au_h_fptr(file);
  7126. + h_inode = hidden_file->f_dentry->d_inode;
  7127. + if (!au_flag_test(sb, AuFlag_UDBA_INOTIFY))
  7128. + err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
  7129. + else {
  7130. + struct inode *dir = dentry->d_parent->d_inode,
  7131. + *h_dir = hidden_file->f_dentry->d_parent->d_inode;
  7132. + aufs_bindex_t bstart = fbstart(file);
  7133. + hdir_lock(h_dir, dir, bstart);
  7134. + err = vfsub_write_u(hidden_file, buf, count, ppos, dlgt);
  7135. + hdir_unlock(h_dir, dir, bstart);
  7136. + }
  7137. + ii_write_lock_child(inode);
  7138. + au_cpup_attr_timesizes(inode);
  7139. + ii_write_unlock(inode);
  7140. +
  7141. + out_unlock:
  7142. + fi_write_unlock(file);
  7143. + out:
  7144. + si_read_unlock(sb);
  7145. + i_unlock(inode);
  7146. + TraceErr(err);
  7147. + return err;
  7148. +}
  7149. +
  7150. +/* ---------------------------------------------------------------------- */
  7151. +
  7152. +#if 0 //def CONFIG_AUFS_ROBR
  7153. +struct lvma {
  7154. + struct list_head list;
  7155. + struct vm_area_struct *vma;
  7156. +};
  7157. +
  7158. +static struct file *safe_file(struct vm_area_struct *vma)
  7159. +{
  7160. + struct file *file = vma->vm_file;
  7161. + struct super_block *sb = file->f_dentry->d_sb;
  7162. + struct lvma *lvma, *entry;
  7163. + struct aufs_sbinfo *sbinfo;
  7164. + int found, warn;
  7165. +
  7166. + TraceEnter();
  7167. + DEBUG_ON(!SB_AUFS(sb));
  7168. +
  7169. + warn = 0;
  7170. + found = 0;
  7171. + sbinfo = stosi(sb);
  7172. + spin_lock(&sbinfo->si_lvma_lock);
  7173. + list_for_each_entry(entry, &sbinfo->si_lvma, list) {
  7174. + found = (entry->vma == vma);
  7175. + if (unlikely(found))
  7176. + break;
  7177. + }
  7178. + if (!found) {
  7179. + lvma = kmalloc(sizeof(*lvma), GFP_ATOMIC);
  7180. + if (lvma) {
  7181. + lvma->vma = vma;
  7182. + list_add(&lvma->list, &sbinfo->si_lvma);
  7183. + } else {
  7184. + warn = 1;
  7185. + file = NULL;
  7186. + }
  7187. + } else
  7188. + file = NULL;
  7189. + spin_unlock(&sbinfo->si_lvma_lock);
  7190. +
  7191. + if (unlikely(warn))
  7192. + Warn1("no memory for lvma\n");
  7193. + return file;
  7194. +}
  7195. +
  7196. +static void reset_file(struct vm_area_struct *vma, struct file *file)
  7197. +{
  7198. + struct super_block *sb = file->f_dentry->d_sb;
  7199. + struct lvma *entry, *found;
  7200. + struct aufs_sbinfo *sbinfo;
  7201. +
  7202. + TraceEnter();
  7203. + DEBUG_ON(!SB_AUFS(sb));
  7204. +
  7205. + vma->vm_file = file;
  7206. +
  7207. + found = NULL;
  7208. + sbinfo = stosi(sb);
  7209. + spin_lock(&sbinfo->si_lvma_lock);
  7210. + list_for_each_entry(entry, &sbinfo->si_lvma, list)
  7211. + if (entry->vma == vma){
  7212. + found = entry;
  7213. + break;
  7214. + }
  7215. + DEBUG_ON(!found);
  7216. + list_del(&found->list);
  7217. + spin_unlock(&sbinfo->si_lvma_lock);
  7218. + kfree(found);
  7219. +}
  7220. +
  7221. +#else
  7222. +
  7223. +static struct file *safe_file(struct vm_area_struct *vma)
  7224. +{
  7225. + struct file *file;
  7226. +
  7227. + file = vma->vm_file;
  7228. + if (file->private_data && au_is_aufs(file->f_dentry->d_sb))
  7229. + return file;
  7230. + return NULL;
  7231. +}
  7232. +
  7233. +static void reset_file(struct vm_area_struct *vma, struct file *file)
  7234. +{
  7235. + vma->vm_file = file;
  7236. + smp_mb();
  7237. +}
  7238. +#endif /* CONFIG_AUFS_ROBR */
  7239. +
  7240. +static struct page *aufs_nopage(struct vm_area_struct *vma, unsigned long addr,
  7241. + int *type)
  7242. +{
  7243. + struct page *page;
  7244. + struct dentry *dentry;
  7245. + struct file *file, *hidden_file;
  7246. + struct inode *inode;
  7247. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  7248. + struct aufs_finfo *finfo;
  7249. +
  7250. + TraceEnter();
  7251. + DEBUG_ON(!vma || !vma->vm_file);
  7252. + wait_event(wq, (file = safe_file(vma)));
  7253. + DEBUG_ON(!au_is_aufs(file->f_dentry->d_sb));
  7254. + dentry = file->f_dentry;
  7255. + LKTRTrace("%.*s, addr %lx\n", DLNPair(dentry), addr);
  7256. + inode = dentry->d_inode;
  7257. + DEBUG_ON(!S_ISREG(inode->i_mode));
  7258. +
  7259. + // do not revalidate, nor lock
  7260. + finfo = ftofi(file);
  7261. + hidden_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
  7262. + DEBUG_ON(!hidden_file || !au_is_mmapped(file));
  7263. + vma->vm_file = hidden_file;
  7264. + //smp_mb();
  7265. + page = finfo->fi_h_vm_ops->nopage(vma, addr, type);
  7266. + reset_file(vma, file);
  7267. +#if 0 //def CONFIG_SMP
  7268. + //wake_up_nr(&wq, online_cpu - 1);
  7269. + wake_up_all(&wq);
  7270. +#else
  7271. + wake_up(&wq);
  7272. +#endif
  7273. + if (!IS_ERR(page)) {
  7274. + //page->mapping = file->f_mapping;
  7275. + //get_page(page);
  7276. + //file->f_mapping = hidden_file->f_mapping;
  7277. + //touch_atime(NULL, dentry);
  7278. + //inode->i_atime = hidden_file->f_dentry->d_inode->i_atime;
  7279. + }
  7280. + TraceErrPtr(page);
  7281. + return page;
  7282. +}
  7283. +
  7284. +static int aufs_populate(struct vm_area_struct *vma, unsigned long addr,
  7285. + unsigned long len, pgprot_t prot, unsigned long pgoff,
  7286. + int nonblock)
  7287. +{
  7288. + Err("please report me this application\n");
  7289. + BUG();
  7290. + return ftofi(vma->vm_file)->fi_h_vm_ops->populate
  7291. + (vma, addr, len, prot, pgoff, nonblock);
  7292. +}
  7293. +
  7294. +static struct vm_operations_struct aufs_vm_ops = {
  7295. + //.open = aufs_vmaopen,
  7296. + //.close = aufs_vmaclose,
  7297. + .nopage = aufs_nopage,
  7298. + .populate = aufs_populate,
  7299. + //page_mkwrite(struct vm_area_struct *vma, struct page *page)
  7300. +};
  7301. +
  7302. +/* ---------------------------------------------------------------------- */
  7303. +
  7304. +static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
  7305. +{
  7306. + int err, wlock, mmapped;
  7307. + struct dentry *dentry;
  7308. + struct super_block *sb;
  7309. + struct file *h_file;
  7310. + struct vm_operations_struct *vm_ops;
  7311. + unsigned long flags;
  7312. +
  7313. + dentry = file->f_dentry;
  7314. + LKTRTrace("%.*s, %lx, len %lu\n",
  7315. + DLNPair(dentry), vma->vm_start, vma->vm_end - vma->vm_start);
  7316. + DEBUG_ON(!S_ISREG(dentry->d_inode->i_mode));
  7317. + DEBUG_ON(down_write_trylock(&vma->vm_mm->mmap_sem));
  7318. +
  7319. + mmapped = au_is_mmapped(file);
  7320. + wlock = 0;
  7321. + if (file->f_mode & FMODE_WRITE) {
  7322. + flags = VM_SHARED | VM_WRITE;
  7323. + wlock = ((flags & vma->vm_flags) == flags);
  7324. + }
  7325. +
  7326. + sb = dentry->d_sb;
  7327. + si_read_lock(sb);
  7328. + err = au_reval_and_lock_finfo(file, au_reopen_nondir,
  7329. + wlock | !mmapped, /*locked*/0);
  7330. + //err = -1;
  7331. + if (unlikely(err))
  7332. + goto out;
  7333. +
  7334. + if (wlock) {
  7335. + err = au_ready_to_write(file, -1);
  7336. + //err = -1;
  7337. + if (unlikely(err))
  7338. + goto out_unlock;
  7339. + }
  7340. +
  7341. + h_file = au_h_fptr(file);
  7342. + vm_ops = ftofi(file)->fi_h_vm_ops;
  7343. + if (unlikely(!mmapped)) {
  7344. + // nfs uses some locks
  7345. + lockdep_off();
  7346. + err = h_file->f_op->mmap(h_file, vma);
  7347. + lockdep_on();
  7348. + if (unlikely(err))
  7349. + goto out_unlock;
  7350. + vm_ops = vma->vm_ops;
  7351. + DEBUG_ON(!vm_ops);
  7352. + err = do_munmap(current->mm, vma->vm_start,
  7353. + vma->vm_end - vma->vm_start);
  7354. + if (unlikely(err)) {
  7355. + IOErr("failed internal unmapping %.*s, %d\n",
  7356. + DLNPair(h_file->f_dentry), err);
  7357. + err = -EIO;
  7358. + goto out_unlock;
  7359. + }
  7360. + }
  7361. + DEBUG_ON(!vm_ops);
  7362. +
  7363. + err = generic_file_mmap(file, vma);
  7364. + if (!err) {
  7365. + file_accessed(h_file);
  7366. + dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
  7367. + vma->vm_ops = &aufs_vm_ops;
  7368. + if (unlikely(!mmapped))
  7369. + ftofi(file)->fi_h_vm_ops = vm_ops;
  7370. + }
  7371. +
  7372. + out_unlock:
  7373. + if (!wlock && mmapped)
  7374. + fi_read_unlock(file);
  7375. + else
  7376. + fi_write_unlock(file);
  7377. + out:
  7378. + si_read_unlock(sb);
  7379. + TraceErr(err);
  7380. + return err;
  7381. +}
  7382. +
  7383. +// todo: try do_sendfile() in fs/read_write.c
  7384. +static ssize_t aufs_sendfile(struct file *file, loff_t *ppos,
  7385. + size_t count, read_actor_t actor, void *target)
  7386. +{
  7387. + ssize_t err;
  7388. + struct file *h_file;
  7389. + const char c = current->comm[4];
  7390. + /* true if a kernel thread named 'loop[0-9].*' accesses a file */
  7391. + const int loopback = (current->mm == NULL
  7392. + && '0' <= c && c <= '9'
  7393. + && strncmp(current->comm, "loop", 4) == 0);
  7394. + struct dentry *dentry;
  7395. + struct super_block *sb;
  7396. +
  7397. + dentry = file->f_dentry;
  7398. + LKTRTrace("%.*s, pos %Ld, cnt %lu, loopback %d\n",
  7399. + DLNPair(dentry), *ppos, (unsigned long)count, loopback);
  7400. +
  7401. + sb = dentry->d_sb;
  7402. + si_read_lock(sb);
  7403. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7404. + /*locked*/0);
  7405. + if (unlikely(err))
  7406. + goto out;
  7407. +
  7408. + err = -EINVAL;
  7409. + h_file = au_h_fptr(file);
  7410. + if (h_file->f_op && h_file->f_op->sendfile) {
  7411. + if (/* unlikely */(loopback)) {
  7412. + file->f_mapping = h_file->f_mapping;
  7413. + smp_mb(); //??
  7414. + }
  7415. + // nfs uses some locks
  7416. + lockdep_off();
  7417. + err = h_file->f_op->sendfile
  7418. + (h_file, ppos, count, actor, target);
  7419. + lockdep_on();
  7420. + dentry->d_inode->i_atime = h_file->f_dentry->d_inode->i_atime;
  7421. + }
  7422. + fi_read_unlock(file);
  7423. +
  7424. + out:
  7425. + si_read_unlock(sb);
  7426. + TraceErr(err);
  7427. + return err;
  7428. +}
  7429. +
  7430. +/* ---------------------------------------------------------------------- */
  7431. +
  7432. +/* copied from linux/fs/select.h, must match */
  7433. +#define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
  7434. +
  7435. +static unsigned int aufs_poll(struct file *file, poll_table *wait)
  7436. +{
  7437. + unsigned int mask;
  7438. + struct file *hidden_file;
  7439. + int err;
  7440. + struct dentry *dentry;
  7441. + struct super_block *sb;
  7442. +
  7443. + dentry = file->f_dentry;
  7444. + LKTRTrace("%.*s, wait %p\n", DLNPair(dentry), wait);
  7445. + DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode));
  7446. +
  7447. + /* We should pretend an error happend. */
  7448. + mask = POLLERR /* | POLLIN | POLLOUT */;
  7449. + sb = dentry->d_sb;
  7450. + si_read_lock(sb);
  7451. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7452. + /*locked*/0);
  7453. + //err = -1;
  7454. + if (unlikely(err))
  7455. + goto out;
  7456. +
  7457. + /* it is not an error of hidden_file has no operation */
  7458. + mask = DEFAULT_POLLMASK;
  7459. + hidden_file = au_h_fptr(file);
  7460. + if (hidden_file->f_op && hidden_file->f_op->poll)
  7461. + mask = hidden_file->f_op->poll(hidden_file, wait);
  7462. + fi_read_unlock(file);
  7463. +
  7464. + out:
  7465. + si_read_unlock(sb);
  7466. + TraceErr((int)mask);
  7467. + return mask;
  7468. +}
  7469. +
  7470. +static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
  7471. + int datasync)
  7472. +{
  7473. + int err, my_lock;
  7474. + struct inode *inode;
  7475. + struct file *hidden_file;
  7476. + struct super_block *sb;
  7477. +
  7478. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), datasync);
  7479. + inode = dentry->d_inode;
  7480. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
  7481. + IMustLock(inode);
  7482. + my_lock = 0;
  7483. +#else
  7484. + /* before 2.6.17,
  7485. + * msync(2) calls me without locking i_sem/i_mutex, but fsync(2).
  7486. + */
  7487. + my_lock = !i_trylock(inode);
  7488. +#endif
  7489. +
  7490. + sb = dentry->d_sb;
  7491. + si_read_lock(sb);
  7492. + err = 0; //-EBADF; // posix?
  7493. + if (unlikely(!(file->f_mode & FMODE_WRITE)))
  7494. + goto out;
  7495. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/1,
  7496. + /*locked*/1);
  7497. + //err = -1;
  7498. + if (unlikely(err))
  7499. + goto out;
  7500. + err = au_ready_to_write(file, -1);
  7501. + //err = -1;
  7502. + if (unlikely(err))
  7503. + goto out_unlock;
  7504. +
  7505. + err = -EINVAL;
  7506. + hidden_file = au_h_fptr(file);
  7507. + if (hidden_file->f_op && hidden_file->f_op->fsync) {
  7508. + // todo: apparmor thread?
  7509. + //file->f_mapping->host->i_mutex
  7510. + ii_write_lock_child(inode);
  7511. + hi_lock_child(hidden_file->f_dentry->d_inode);
  7512. + err = hidden_file->f_op->fsync
  7513. + (hidden_file, hidden_file->f_dentry, datasync);
  7514. + //err = -1;
  7515. + au_cpup_attr_timesizes(inode);
  7516. + i_unlock(hidden_file->f_dentry->d_inode);
  7517. + ii_write_unlock(inode);
  7518. + }
  7519. +
  7520. + out_unlock:
  7521. + fi_write_unlock(file);
  7522. + out:
  7523. + if (unlikely(my_lock))
  7524. + i_unlock(inode);
  7525. + si_read_unlock(sb);
  7526. + TraceErr(err);
  7527. + return err;
  7528. +}
  7529. +
  7530. +static int aufs_fasync(int fd, struct file *file, int flag)
  7531. +{
  7532. + int err;
  7533. + struct file *hidden_file;
  7534. + struct dentry *dentry;
  7535. + struct super_block *sb;
  7536. +
  7537. + dentry = file->f_dentry;
  7538. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), flag);
  7539. +
  7540. + sb = dentry->d_sb;
  7541. + si_read_lock(sb);
  7542. + err = au_reval_and_lock_finfo(file, au_reopen_nondir, /*wlock*/0,
  7543. + /*locked*/0);
  7544. + //err = -1;
  7545. + if (unlikely(err))
  7546. + goto out;
  7547. +
  7548. + hidden_file = au_h_fptr(file);
  7549. + if (hidden_file->f_op && hidden_file->f_op->fasync)
  7550. + err = hidden_file->f_op->fasync(fd, hidden_file, flag);
  7551. + fi_read_unlock(file);
  7552. +
  7553. + out:
  7554. + si_read_unlock(sb);
  7555. + TraceErr(err);
  7556. + return err;
  7557. +}
  7558. +
  7559. +/* ---------------------------------------------------------------------- */
  7560. +
  7561. +#if 0 // comment
  7562. +struct file_operations {
  7563. + struct module *owner;
  7564. + loff_t (*llseek) (struct file *, loff_t, int);
  7565. + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
  7566. + ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
  7567. + ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
  7568. + ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
  7569. + int (*readdir) (struct file *, void *, filldir_t);
  7570. + unsigned int (*poll) (struct file *, struct poll_table_struct *);
  7571. + int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
  7572. + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
  7573. + long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
  7574. + int (*mmap) (struct file *, struct vm_area_struct *);
  7575. + int (*open) (struct inode *, struct file *);
  7576. + int (*flush) (struct file *);
  7577. + int (*release) (struct inode *, struct file *);
  7578. + int (*fsync) (struct file *, struct dentry *, int datasync);
  7579. + int (*aio_fsync) (struct kiocb *, int datasync);
  7580. + int (*fasync) (int, struct file *, int);
  7581. + int (*lock) (struct file *, int, struct file_lock *);
  7582. + ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
  7583. + ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
  7584. + ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
  7585. + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
  7586. + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
  7587. + int (*check_flags)(int);
  7588. + int (*dir_notify)(struct file *file, unsigned long arg);
  7589. + int (*flock) (struct file *, int, struct file_lock *);
  7590. +};
  7591. +#endif
  7592. +
  7593. +struct file_operations aufs_file_fop = {
  7594. + .read = aufs_read,
  7595. + .write = aufs_write,
  7596. + .poll = aufs_poll,
  7597. + .mmap = aufs_mmap,
  7598. + .open = aufs_open_nondir,
  7599. + .flush = aufs_flush,
  7600. + .release = aufs_release_nondir,
  7601. + .fsync = aufs_fsync_nondir,
  7602. + .fasync = aufs_fasync,
  7603. + .sendfile = aufs_sendfile,
  7604. +};
  7605. diff --git a/fs/aufs/file.c b/fs/aufs/file.c
  7606. new file mode 100755
  7607. index 0000000..857a4e8
  7608. --- /dev/null
  7609. +++ b/fs/aufs/file.c
  7610. @@ -0,0 +1,832 @@
  7611. +/*
  7612. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  7613. + *
  7614. + * This program, aufs is free software; you can redistribute it and/or modify
  7615. + * it under the terms of the GNU General Public License as published by
  7616. + * the Free Software Foundation; either version 2 of the License, or
  7617. + * (at your option) any later version.
  7618. + *
  7619. + * This program is distributed in the hope that it will be useful,
  7620. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7621. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  7622. + * GNU General Public License for more details.
  7623. + *
  7624. + * You should have received a copy of the GNU General Public License
  7625. + * along with this program; if not, write to the Free Software
  7626. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  7627. + */
  7628. +
  7629. +/* $Id: file.c,v 1.42 2007/05/14 03:39:09 sfjro Exp $ */
  7630. +
  7631. +//#include <linux/fsnotify.h>
  7632. +#include <linux/pagemap.h>
  7633. +//#include <linux/poll.h>
  7634. +//#include <linux/security.h>
  7635. +#include "aufs.h"
  7636. +
  7637. +/* drop flags for writing */
  7638. +unsigned int au_file_roflags(unsigned int flags)
  7639. +{
  7640. + flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
  7641. + flags |= O_RDONLY | O_NOATIME;
  7642. + return flags;
  7643. +}
  7644. +
  7645. +/* common functions to regular file and dir */
  7646. +struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags)
  7647. +{
  7648. + struct dentry *hidden_dentry;
  7649. + struct inode *hidden_inode;
  7650. + struct super_block *sb;
  7651. + struct vfsmount *hidden_mnt;
  7652. + struct file *hidden_file;
  7653. + struct aufs_branch *br;
  7654. + loff_t old_size;
  7655. + int udba;
  7656. +
  7657. + LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags);
  7658. + DEBUG_ON(!dentry);
  7659. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  7660. + DEBUG_ON(!hidden_dentry);
  7661. + hidden_inode = hidden_dentry->d_inode;
  7662. + DEBUG_ON(!hidden_inode);
  7663. +
  7664. + sb = dentry->d_sb;
  7665. + udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
  7666. + if (unlikely(udba)) {
  7667. + // test here?
  7668. + }
  7669. +
  7670. + br = stobr(sb, bindex);
  7671. + br_get(br);
  7672. + /* drop flags for writing */
  7673. + if (test_ro(sb, bindex, dentry->d_inode))
  7674. + flags = au_file_roflags(flags);
  7675. + flags &= ~O_CREAT;
  7676. + spin_lock(&hidden_inode->i_lock);
  7677. + old_size = i_size_read(hidden_inode);
  7678. + spin_unlock(&hidden_inode->i_lock);
  7679. +
  7680. + //DbgSleep(3);
  7681. +
  7682. + dget(hidden_dentry);
  7683. + hidden_mnt = mntget(br->br_mnt);
  7684. + hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags);
  7685. + //if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);}
  7686. +
  7687. + if (!IS_ERR(hidden_file)) {
  7688. +#if 0 // remove this
  7689. + if (/* old_size && */ (flags & O_TRUNC)) {
  7690. + au_direval_dec(dentry);
  7691. + if (!IS_ROOT(dentry))
  7692. + au_direval_dec(dentry->d_parent);
  7693. + }
  7694. +#endif
  7695. + return hidden_file;
  7696. + }
  7697. +
  7698. + br_put(br);
  7699. + TraceErrPtr(hidden_file);
  7700. + return hidden_file;
  7701. +}
  7702. +
  7703. +static int do_coo(struct dentry *dentry, aufs_bindex_t bstart)
  7704. +{
  7705. + int err;
  7706. + struct dentry *parent, *h_parent, *h_dentry;
  7707. + aufs_bindex_t bcpup;
  7708. + struct inode *h_dir, *h_inode, *dir;
  7709. +
  7710. + LKTRTrace("%.*s\n", DLNPair(dentry));
  7711. + DEBUG_ON(IS_ROOT(dentry));
  7712. + DiMustWriteLock(dentry);
  7713. +
  7714. + parent = dentry->d_parent; // dget_parent()
  7715. + di_write_lock_parent(parent);
  7716. + bcpup = err = find_rw_parent_br(dentry, bstart);
  7717. + //bcpup = err = find_rw_br(sb, bstart);
  7718. + if (unlikely(err < 0)) {
  7719. + err = 0; // stop copyup, it is not an error
  7720. + goto out;
  7721. + }
  7722. + err = 0;
  7723. +
  7724. + h_parent = au_h_dptr_i(parent, bcpup);
  7725. + if (!h_parent) {
  7726. + err = cpup_dirs(dentry, bcpup, NULL);
  7727. + if (unlikely(err))
  7728. + goto out;
  7729. + h_parent = au_h_dptr_i(parent, bcpup);
  7730. + }
  7731. +
  7732. + h_dir = h_parent->d_inode;
  7733. + h_dentry = au_h_dptr_i(dentry, bstart);
  7734. + h_inode = h_dentry->d_inode;
  7735. + dir = parent->d_inode;
  7736. + hdir_lock(h_dir, dir, bcpup);
  7737. + hi_lock_child(h_inode);
  7738. + DEBUG_ON(au_h_dptr_i(dentry, bcpup));
  7739. + err = sio_cpup_simple(dentry, bcpup, -1,
  7740. + au_flags_cpup(CPUP_DTIME, parent));
  7741. + TraceErr(err);
  7742. + i_unlock(h_inode);
  7743. + hdir_unlock(h_dir, dir, bcpup);
  7744. +
  7745. + out:
  7746. + di_write_unlock(parent);
  7747. + TraceErr(err);
  7748. + return err;
  7749. +}
  7750. +
  7751. +int au_do_open(struct inode *inode, struct file *file,
  7752. + int (*open)(struct file *file, int flags))
  7753. +{
  7754. + int err, coo;
  7755. + struct dentry *dentry;
  7756. + struct super_block *sb;
  7757. + aufs_bindex_t bstart;
  7758. + struct inode *h_dir, *dir;
  7759. +
  7760. + dentry = file->f_dentry;
  7761. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
  7762. +
  7763. + sb = dentry->d_sb;
  7764. + si_read_lock(sb);
  7765. + coo = 0;
  7766. +#if 0
  7767. + switch (au_flag_test_coo(sb)) {
  7768. + case AuFlag_COO_LEAF:
  7769. + coo = !S_ISDIR(inode->i_mode);
  7770. + break;
  7771. + case AuFlag_COO_ALL:
  7772. + coo = 1;
  7773. + break;
  7774. + }
  7775. +#endif
  7776. + err = au_init_finfo(file);
  7777. + //if (LktrCond) {fi_write_unlock(file); fin_finfo(file); err = -1;}
  7778. + if (unlikely(err))
  7779. + goto out;
  7780. +
  7781. + if (!coo) {
  7782. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  7783. + bstart = dbstart(dentry);
  7784. + } else {
  7785. + di_write_lock_child(dentry);
  7786. + bstart = dbstart(dentry);
  7787. + if (test_ro(sb, bstart, dentry->d_inode)) {
  7788. + err = do_coo(dentry, bstart);
  7789. + if (err) {
  7790. + di_write_unlock(dentry);
  7791. + goto out_finfo;
  7792. + }
  7793. + bstart = dbstart(dentry);
  7794. + }
  7795. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  7796. + }
  7797. +
  7798. + // todo: remove this extra locks
  7799. + dir = dentry->d_parent->d_inode;
  7800. + if (!IS_ROOT(dentry))
  7801. + ii_read_lock_parent(dir);
  7802. + h_dir = au_h_iptr_i(dir, bstart);
  7803. + hdir_lock(h_dir, dir, bstart);
  7804. + err = open(file, file->f_flags);
  7805. + //if (LktrCond) err = -1;
  7806. + hdir_unlock(h_dir, dir, bstart);
  7807. + if (!IS_ROOT(dentry))
  7808. + ii_read_unlock(dir);
  7809. + di_read_unlock(dentry, AUFS_I_RLOCK);
  7810. +
  7811. + out_finfo:
  7812. + fi_write_unlock(file);
  7813. + if (unlikely(err))
  7814. + au_fin_finfo(file);
  7815. + //DbgFile(file);
  7816. + out:
  7817. + si_read_unlock(sb);
  7818. + TraceErr(err);
  7819. + return err;
  7820. +}
  7821. +
  7822. +int au_reopen_nondir(struct file *file)
  7823. +{
  7824. + int err;
  7825. + struct dentry *dentry;
  7826. + aufs_bindex_t bstart, bindex, bend;
  7827. + struct file *hidden_file, *h_file_tmp;
  7828. +
  7829. + dentry = file->f_dentry;
  7830. + LKTRTrace("%.*s\n", DLNPair(dentry));
  7831. + DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
  7832. + || !au_h_dptr(dentry)->d_inode);
  7833. + bstart = dbstart(dentry);
  7834. +
  7835. + h_file_tmp = NULL;
  7836. + if (fbstart(file) == bstart) {
  7837. + hidden_file = au_h_fptr(file);
  7838. + if (file->f_mode == hidden_file->f_mode)
  7839. + return 0; /* success */
  7840. + h_file_tmp = hidden_file;
  7841. + get_file(h_file_tmp);
  7842. + set_h_fptr(file, bstart, NULL);
  7843. + }
  7844. + DEBUG_ON(fbstart(file) < bstart
  7845. + || ftofi(file)->fi_hfile[0 + bstart].hf_file);
  7846. +
  7847. + hidden_file = hidden_open(dentry, bstart, file->f_flags & ~O_TRUNC);
  7848. + //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bstart));
  7849. + //hidden_file = ERR_PTR(-1);}
  7850. + err = PTR_ERR(hidden_file);
  7851. + if (IS_ERR(hidden_file))
  7852. + goto out; // close all?
  7853. + err = 0;
  7854. + //cpup_file_flags(hidden_file, file);
  7855. + set_fbstart(file, bstart);
  7856. + set_h_fptr(file, bstart, hidden_file);
  7857. + memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(file->f_ra)); //??
  7858. +
  7859. + /* close lower files */
  7860. + bend = fbend(file);
  7861. + for (bindex = bstart + 1; bindex <= bend; bindex++)
  7862. + set_h_fptr(file, bindex, NULL);
  7863. + set_fbend(file, bstart);
  7864. +
  7865. + out:
  7866. + if (h_file_tmp)
  7867. + fput(h_file_tmp);
  7868. + TraceErr(err);
  7869. + return err;
  7870. +}
  7871. +
  7872. +/*
  7873. + * copyup the deleted file for writing.
  7874. + */
  7875. +static int cpup_wh_file(struct file *file, aufs_bindex_t bdst, loff_t len)
  7876. +{
  7877. + int err;
  7878. + struct dentry *dentry, *parent, *hidden_parent, *tmp_dentry;
  7879. + struct dentry *hidden_dentry_bstart, *hidden_dentry_bdst;
  7880. + struct inode *hidden_dir;
  7881. + aufs_bindex_t bstart;
  7882. + struct aufs_dinfo *dinfo;
  7883. + struct dtime dt;
  7884. + struct lkup_args lkup;
  7885. + struct super_block *sb;
  7886. +
  7887. + dentry = file->f_dentry;
  7888. + LKTRTrace("%.*s, bdst %d, len %Lu\n", DLNPair(dentry), bdst, len);
  7889. + DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode)
  7890. + || !(file->f_mode & FMODE_WRITE));
  7891. + DiMustWriteLock(dentry);
  7892. + parent = dentry->d_parent;
  7893. + IiMustAnyLock(parent->d_inode);
  7894. + hidden_parent = au_h_dptr_i(parent, bdst);
  7895. + DEBUG_ON(!hidden_parent);
  7896. + hidden_dir = hidden_parent->d_inode;
  7897. + DEBUG_ON(!hidden_dir);
  7898. + IMustLock(hidden_dir);
  7899. +
  7900. + sb = parent->d_sb;
  7901. + lkup.nfsmnt = au_nfsmnt(sb, bdst);
  7902. + lkup.dlgt = need_dlgt(sb);
  7903. + tmp_dentry = lkup_whtmp(hidden_parent, &dentry->d_name, &lkup);
  7904. + //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
  7905. + err = PTR_ERR(tmp_dentry);
  7906. + if (IS_ERR(tmp_dentry))
  7907. + goto out;
  7908. +
  7909. + dtime_store(&dt, parent, hidden_parent);
  7910. + dinfo = dtodi(dentry);
  7911. + bstart = dinfo->di_bstart;
  7912. + hidden_dentry_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry;
  7913. + hidden_dentry_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry;
  7914. + dinfo->di_bstart = bdst;
  7915. + dinfo->di_hdentry[0 + bdst].hd_dentry = tmp_dentry;
  7916. + dinfo->di_hdentry[0 + bstart].hd_dentry = au_h_fptr(file)->f_dentry;
  7917. + err = cpup_single(dentry, bdst, bstart, len,
  7918. + au_flags_cpup(!CPUP_DTIME, parent));
  7919. + //if (LktrCond) err = -1;
  7920. + if (!err)
  7921. + err = au_reopen_nondir(file);
  7922. + //err = -1;
  7923. + dinfo->di_hdentry[0 + bstart].hd_dentry = hidden_dentry_bstart;
  7924. + dinfo->di_hdentry[0 + bdst].hd_dentry = hidden_dentry_bdst;
  7925. + dinfo->di_bstart = bstart;
  7926. + if (unlikely(err))
  7927. + goto out_tmp;
  7928. +
  7929. + DEBUG_ON(!d_unhashed(dentry));
  7930. + err = vfsub_unlink(hidden_dir, tmp_dentry, lkup.dlgt);
  7931. + //if (LktrCond) err = -1;
  7932. + if (unlikely(err)) {
  7933. + IOErr("failed remove copied-up tmp file %.*s(%d)\n",
  7934. + DLNPair(tmp_dentry), err);
  7935. + err = -EIO;
  7936. + }
  7937. + dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
  7938. +
  7939. + out_tmp:
  7940. + dput(tmp_dentry);
  7941. + out:
  7942. + TraceErr(err);
  7943. + return err;
  7944. +}
  7945. +
  7946. +struct cpup_wh_file_args {
  7947. + int *errp;
  7948. + struct file *file;
  7949. + aufs_bindex_t bdst;
  7950. + loff_t len;
  7951. +};
  7952. +
  7953. +static void call_cpup_wh_file(void *args)
  7954. +{
  7955. + struct cpup_wh_file_args *a = args;
  7956. + *a->errp = cpup_wh_file(a->file, a->bdst, a->len);
  7957. +}
  7958. +
  7959. +/*
  7960. + * prepare the @file for writing.
  7961. + */
  7962. +int au_ready_to_write(struct file *file, loff_t len)
  7963. +{
  7964. + int err;
  7965. + struct dentry *dentry, *parent, *hidden_dentry, *hidden_parent;
  7966. + struct inode *hidden_inode, *hidden_dir, *inode, *dir;
  7967. + struct super_block *sb;
  7968. + aufs_bindex_t bstart, bcpup;
  7969. +
  7970. + dentry = file->f_dentry;
  7971. + LKTRTrace("%.*s, len %Ld\n", DLNPair(dentry), len);
  7972. + FiMustWriteLock(file);
  7973. +
  7974. + sb = dentry->d_sb;
  7975. + bstart = fbstart(file);
  7976. + DEBUG_ON(ftobr(file, bstart) != stobr(sb, bstart));
  7977. +
  7978. + inode = dentry->d_inode;
  7979. + ii_read_lock_child(inode);
  7980. + LKTRTrace("rdonly %d, bstart %d\n", test_ro(sb, bstart, inode), bstart);
  7981. + err = test_ro(sb, bstart, inode);
  7982. + ii_read_unlock(inode);
  7983. + if (!err && (au_h_fptr(file)->f_mode & FMODE_WRITE))
  7984. + return 0;
  7985. +
  7986. + /* need to cpup */
  7987. + parent = dentry->d_parent; // dget_parent()
  7988. + di_write_lock_child(dentry);
  7989. + di_write_lock_parent(parent);
  7990. + bcpup = err = find_rw_parent_br(dentry, bstart);
  7991. + //bcpup = err = find_rw_br(sb, bstart);
  7992. + if (unlikely(err < 0))
  7993. + goto out_unlock;
  7994. + err = 0;
  7995. +
  7996. + hidden_parent = au_h_dptr_i(parent, bcpup);
  7997. + if (!hidden_parent) {
  7998. + err = cpup_dirs(dentry, bcpup, NULL);
  7999. + //if (LktrCond) err = -1;
  8000. + if (unlikely(err))
  8001. + goto out_unlock;
  8002. + hidden_parent = au_h_dptr_i(parent, bcpup);
  8003. + }
  8004. +
  8005. + hidden_dir = hidden_parent->d_inode;
  8006. + hidden_dentry = au_h_fptr(file)->f_dentry;
  8007. + hidden_inode = hidden_dentry->d_inode;
  8008. + dir = parent->d_inode;
  8009. + hdir_lock(hidden_dir, dir, bcpup);
  8010. + hi_lock_child(hidden_inode);
  8011. + if (d_unhashed(dentry) || d_unhashed(hidden_dentry)
  8012. + /* || !hidden_inode->i_nlink */) {
  8013. + if (!au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE,
  8014. + need_dlgt(sb)))
  8015. + err = cpup_wh_file(file, bcpup, len);
  8016. + else {
  8017. + struct cpup_wh_file_args args = {
  8018. + .errp = &err,
  8019. + .file = file,
  8020. + .bdst = bcpup,
  8021. + .len = len
  8022. + };
  8023. + au_wkq_wait(call_cpup_wh_file, &args, /*dlgt*/0);
  8024. + }
  8025. + //if (LktrCond) err = -1;
  8026. + TraceErr(err);
  8027. + } else {
  8028. + if (!au_h_dptr_i(dentry, bcpup))
  8029. + err = sio_cpup_simple(dentry, bcpup, len,
  8030. + au_flags_cpup(CPUP_DTIME,
  8031. + parent));
  8032. + //if (LktrCond) err = -1;
  8033. + TraceErr(err);
  8034. + if (!err)
  8035. + err = au_reopen_nondir(file);
  8036. + //if (LktrCond) err = -1;
  8037. + TraceErr(err);
  8038. + }
  8039. + i_unlock(hidden_inode);
  8040. + hdir_unlock(hidden_dir, dir, bcpup);
  8041. +
  8042. + out_unlock:
  8043. + di_write_unlock(parent);
  8044. + di_write_unlock(dentry);
  8045. +// out:
  8046. + TraceErr(err);
  8047. + return err;
  8048. +
  8049. +}
  8050. +
  8051. +/* ---------------------------------------------------------------------- */
  8052. +
  8053. +/*
  8054. + * after branch manipulating, refresh the file.
  8055. + */
  8056. +static int refresh_file(struct file *file, int (*reopen)(struct file *file))
  8057. +{
  8058. + int err, new_sz;
  8059. + struct dentry *dentry;
  8060. + aufs_bindex_t bend, bindex, bstart, brid;
  8061. + struct aufs_hfile *p;
  8062. + struct aufs_finfo *finfo;
  8063. + struct super_block *sb;
  8064. + struct inode *inode;
  8065. + struct file *hidden_file;
  8066. +
  8067. + dentry = file->f_dentry;
  8068. + LKTRTrace("%.*s\n", DLNPair(dentry));
  8069. + FiMustWriteLock(file);
  8070. + DiMustReadLock(dentry);
  8071. + inode = dentry->d_inode;
  8072. + IiMustReadLock(inode);
  8073. + //au_debug_on();
  8074. + //DbgDentry(dentry);
  8075. + //DbgFile(file);
  8076. + //au_debug_off();
  8077. +
  8078. + err = -ENOMEM;
  8079. + sb = dentry->d_sb;
  8080. + finfo = ftofi(file);
  8081. + bstart = finfo->fi_bstart;
  8082. + bend = finfo->fi_bstart;
  8083. + new_sz = sizeof(*finfo->fi_hfile) * (sbend(sb) + 1);
  8084. + p = au_kzrealloc(finfo->fi_hfile, sizeof(*p) * (finfo->fi_bend + 1),
  8085. + new_sz, GFP_KERNEL);
  8086. + //p = NULL;
  8087. + if (unlikely(!p))
  8088. + goto out;
  8089. + finfo->fi_hfile = p;
  8090. + hidden_file = p[0 + bstart].hf_file;
  8091. +
  8092. + p = finfo->fi_hfile + finfo->fi_bstart;
  8093. + brid = p->hf_br->br_id;
  8094. + bend = finfo->fi_bend;
  8095. + for (bindex = finfo->fi_bstart; bindex <= bend; bindex++, p++) {
  8096. + struct aufs_hfile tmp, *q;
  8097. + aufs_bindex_t new_bindex;
  8098. +
  8099. + if (!p->hf_file)
  8100. + continue;
  8101. + new_bindex = find_bindex(sb, p->hf_br);
  8102. + if (new_bindex == bindex)
  8103. + continue;
  8104. + if (new_bindex < 0) { // test here
  8105. + set_h_fptr(file, bindex, NULL);
  8106. + continue;
  8107. + }
  8108. +
  8109. + /* swap two hidden inode, and loop again */
  8110. + q = finfo->fi_hfile + new_bindex;
  8111. + tmp = *q;
  8112. + *q = *p;
  8113. + *p = tmp;
  8114. + if (tmp.hf_file) {
  8115. + bindex--;
  8116. + p--;
  8117. + }
  8118. + }
  8119. + {
  8120. + aufs_bindex_t s = finfo->fi_bstart, e = finfo->fi_bend;
  8121. + finfo->fi_bstart = 0;
  8122. + finfo->fi_bend = sbend(sb);
  8123. + //au_debug_on();
  8124. + //DbgFile(file);
  8125. + //au_debug_off();
  8126. + finfo->fi_bstart = s;
  8127. + finfo->fi_bend = e;
  8128. + }
  8129. +
  8130. + p = finfo->fi_hfile;
  8131. + if (!au_is_mmapped(file) && !d_unhashed(dentry)) {
  8132. + bend = sbend(sb);
  8133. + for (finfo->fi_bstart = 0; finfo->fi_bstart <= bend;
  8134. + finfo->fi_bstart++, p++)
  8135. + if (p->hf_file) {
  8136. + if (p->hf_file->f_dentry
  8137. + && p->hf_file->f_dentry->d_inode)
  8138. + break;
  8139. + else
  8140. + au_hfput(p);
  8141. + }
  8142. + } else {
  8143. + bend = find_brindex(sb, brid);
  8144. + //LKTRTrace("%d\n", bend);
  8145. + for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
  8146. + finfo->fi_bstart++, p++)
  8147. + if (p->hf_file)
  8148. + au_hfput(p);
  8149. + //LKTRTrace("%d\n", finfo->fi_bstart);
  8150. + bend = sbend(sb);
  8151. + }
  8152. +
  8153. + p = finfo->fi_hfile + bend;
  8154. + for (finfo->fi_bend = bend; finfo->fi_bend >= finfo->fi_bstart;
  8155. + finfo->fi_bend--, p--)
  8156. + if (p->hf_file) {
  8157. + if (p->hf_file->f_dentry
  8158. + && p->hf_file->f_dentry->d_inode)
  8159. + break;
  8160. + else
  8161. + au_hfput(p);
  8162. + }
  8163. + //Dbg("%d, %d\n", finfo->fi_bstart, finfo->fi_bend);
  8164. + DEBUG_ON(finfo->fi_bend < finfo->fi_bstart);
  8165. + //DbgFile(file);
  8166. + //DbgDentry(file->f_dentry);
  8167. +
  8168. + err = 0;
  8169. +#if 0 // todo:
  8170. + if (!au_h_dptr(dentry)->d_inode) {
  8171. + au_update_figen(file);
  8172. + goto out; /* success */
  8173. + }
  8174. +#endif
  8175. +
  8176. + if (unlikely(au_is_mmapped(file) || d_unhashed(dentry)))
  8177. + goto out_update; /* success */
  8178. +
  8179. + again:
  8180. + bstart = ibstart(inode);
  8181. + if (bstart < finfo->fi_bstart
  8182. + && au_flag_test(sb, AuFlag_PLINK)
  8183. + && au_is_plinked(sb, inode)) {
  8184. + struct dentry *parent = dentry->d_parent; // dget_parent()
  8185. + struct inode *dir = parent->d_inode, *h_dir;
  8186. +
  8187. + if (test_ro(sb, bstart, inode)) {
  8188. + di_read_lock_parent(parent, !AUFS_I_RLOCK);
  8189. + bstart = err = find_rw_parent_br(dentry, bstart);
  8190. + //bstart = err = find_rw_br(sb, bstart);
  8191. + di_read_unlock(parent, !AUFS_I_RLOCK);
  8192. + //todo: err = -1;
  8193. + if (unlikely(err < 0))
  8194. + goto out;
  8195. + }
  8196. + di_read_unlock(dentry, AUFS_I_RLOCK);
  8197. + di_write_lock_child(dentry);
  8198. + if (bstart != ibstart(inode)) { // todo
  8199. + /* someone changed our inode while we were sleeping */
  8200. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  8201. + goto again;
  8202. + }
  8203. +
  8204. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  8205. + err = test_and_cpup_dirs(dentry, bstart, NULL);
  8206. +
  8207. + // always superio.
  8208. +#if 1
  8209. + h_dir = au_h_dptr_i(parent, bstart)->d_inode;
  8210. + hdir_lock(h_dir, dir, bstart);
  8211. + err = sio_cpup_simple(dentry, bstart, -1,
  8212. + au_flags_cpup(CPUP_DTIME, parent));
  8213. + hdir_unlock(h_dir, dir, bstart);
  8214. + di_read_unlock(parent, AUFS_I_RLOCK);
  8215. +#else
  8216. + if (!is_au_wkq(current)) {
  8217. + struct cpup_pseudo_link_args args = {
  8218. + .errp = &err,
  8219. + .dentry = dentry,
  8220. + .bdst = bstart,
  8221. + .do_lock = 1
  8222. + };
  8223. + au_wkq_wait(call_cpup_pseudo_link, &args);
  8224. + } else
  8225. + err = cpup_pseudo_link(dentry, bstart, /*do_lock*/1);
  8226. +#endif
  8227. + di_downgrade_lock(dentry, AUFS_I_RLOCK);
  8228. + if (unlikely(err))
  8229. + goto out;
  8230. + }
  8231. +
  8232. + err = reopen(file);
  8233. + //err = -1;
  8234. + out_update:
  8235. + if (!err) {
  8236. + au_update_figen(file);
  8237. + //DbgFile(file);
  8238. + return 0; /* success */
  8239. + }
  8240. +
  8241. + /* error, close all hidden files */
  8242. + bend = fbend(file);
  8243. + for (bindex = fbstart(file); bindex <= bend; bindex++)
  8244. + set_h_fptr(file, bindex, NULL);
  8245. +
  8246. + out:
  8247. + TraceErr(err);
  8248. + return err;
  8249. +}
  8250. +
  8251. +/* common function to regular file and dir */
  8252. +int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
  8253. + int wlock, int locked)
  8254. +{
  8255. + int err, sgen, fgen, pseudo_link;
  8256. + struct dentry *dentry;
  8257. + struct super_block *sb;
  8258. + aufs_bindex_t bstart;
  8259. +
  8260. + dentry = file->f_dentry;
  8261. + LKTRTrace("%.*s, w %d, l %d\n", DLNPair(dentry), wlock, locked);
  8262. + sb = dentry->d_sb;
  8263. + SiMustAnyLock(sb);
  8264. +
  8265. + err = 0;
  8266. + sgen = au_sigen(sb);
  8267. + fi_write_lock(file);
  8268. + fgen = au_figen(file);
  8269. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  8270. + bstart = dbstart(dentry);
  8271. + pseudo_link = (bstart != ibstart(dentry->d_inode));
  8272. + di_read_unlock(dentry, AUFS_I_RLOCK);
  8273. + if (sgen == fgen && !pseudo_link && fbstart(file) == bstart) {
  8274. + if (!wlock)
  8275. + fi_downgrade_lock(file);
  8276. + return 0; /* success */
  8277. + }
  8278. +
  8279. + LKTRTrace("sgen %d, fgen %d\n", sgen, fgen);
  8280. + if (sgen != au_digen(dentry)) {
  8281. + /*
  8282. + * d_path() and path_lookup() is a simple and good approach
  8283. + * to revalidate. but si_rwsem in DEBUG_RWSEM will cause a
  8284. + * deadlock. removed the code.
  8285. + */
  8286. + di_write_lock_child(dentry);
  8287. + err = au_reval_dpath(dentry, sgen);
  8288. + //if (LktrCond) err = -1;
  8289. + di_write_unlock(dentry);
  8290. + if (unlikely(err < 0))
  8291. + goto out;
  8292. + DEBUG_ON(au_digen(dentry) != sgen);
  8293. + }
  8294. +
  8295. + di_read_lock_child(dentry, AUFS_I_RLOCK);
  8296. + err = refresh_file(file, reopen);
  8297. + //if (LktrCond) err = -1;
  8298. + di_read_unlock(dentry, AUFS_I_RLOCK);
  8299. + if (!err) {
  8300. + if (!wlock)
  8301. + fi_downgrade_lock(file);
  8302. + } else
  8303. + fi_write_unlock(file);
  8304. +
  8305. + out:
  8306. + TraceErr(err);
  8307. + return err;
  8308. +}
  8309. +
  8310. +/* ---------------------------------------------------------------------- */
  8311. +
  8312. +// cf. aufs_nopage()
  8313. +// for madvise(2)
  8314. +static int aufs_readpage(struct file *file, struct page *page)
  8315. +{
  8316. + TraceEnter();
  8317. + unlock_page(page);
  8318. + return 0;
  8319. +}
  8320. +
  8321. +// they will never be called.
  8322. +#ifdef CONFIG_AUFS_DEBUG
  8323. +static int aufs_prepare_write(struct file *file, struct page *page,
  8324. + unsigned from, unsigned to)
  8325. +{BUG();return 0;}
  8326. +static int aufs_commit_write(struct file *file, struct page *page,
  8327. + unsigned from, unsigned to)
  8328. +{BUG();return 0;}
  8329. +static int aufs_writepage(struct page *page, struct writeback_control *wbc)
  8330. +{BUG();return 0;}
  8331. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
  8332. +static void aufs_sync_page(struct page *page)
  8333. +{BUG();}
  8334. +#else
  8335. +static int aufs_sync_page(struct page *page)
  8336. +{BUG(); return 0;}
  8337. +#endif
  8338. +
  8339. +#if 0 // comment
  8340. +static int aufs_writepages(struct address_space *mapping,
  8341. + struct writeback_control *wbc)
  8342. +{BUG();return 0;}
  8343. +static int aufs_readpages(struct file *filp, struct address_space *mapping,
  8344. + struct list_head *pages, unsigned nr_pages)
  8345. +{BUG();return 0;}
  8346. +static sector_t aufs_bmap(struct address_space *mapping, sector_t block)
  8347. +{BUG();return 0;}
  8348. +#endif
  8349. +
  8350. +static int aufs_set_page_dirty(struct page *page)
  8351. +{BUG();return 0;}
  8352. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
  8353. +static void aufs_invalidatepage (struct page *page, unsigned long offset)
  8354. +{BUG();}
  8355. +#else
  8356. +static int aufs_invalidatepage (struct page *page, unsigned long offset)
  8357. +{BUG(); return 0;}
  8358. +#endif
  8359. +static int aufs_releasepage (struct page *page, gfp_t gfp)
  8360. +{BUG();return 0;}
  8361. +static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
  8362. + const struct iovec *iov, loff_t offset,
  8363. + unsigned long nr_segs)
  8364. +{BUG();return 0;}
  8365. +static struct page* aufs_get_xip_page(struct address_space *mapping,
  8366. + sector_t offset, int create)
  8367. +{BUG();return NULL;}
  8368. +//static int aufs_migratepage (struct page *newpage, struct page *page)
  8369. +//{BUG();return 0;}
  8370. +#endif
  8371. +
  8372. +#if 0 // comment
  8373. +struct address_space {
  8374. + struct inode *host; /* owner: inode, block_device */
  8375. + struct radix_tree_root page_tree; /* radix tree of all pages */
  8376. + rwlock_t tree_lock; /* and rwlock protecting it */
  8377. + unsigned int i_mmap_writable;/* count VM_SHARED mappings */
  8378. + struct prio_tree_root i_mmap; /* tree of private and shared mappings */
  8379. + struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
  8380. + spinlock_t i_mmap_lock; /* protect tree, count, list */
  8381. + unsigned int truncate_count; /* Cover race condition with truncate */
  8382. + unsigned long nrpages; /* number of total pages */
  8383. + pgoff_t writeback_index;/* writeback starts here */
  8384. + struct address_space_operations *a_ops; /* methods */
  8385. + unsigned long flags; /* error bits/gfp mask */
  8386. + struct backing_dev_info *backing_dev_info; /* device readahead, etc */
  8387. + spinlock_t private_lock; /* for use by the address_space */
  8388. + struct list_head private_list; /* ditto */
  8389. + struct address_space *assoc_mapping; /* ditto */
  8390. +} __attribute__((aligned(sizeof(long))));
  8391. +
  8392. +struct address_space_operations {
  8393. + int (*writepage)(struct page *page, struct writeback_control *wbc);
  8394. + int (*readpage)(struct file *, struct page *);
  8395. + void (*sync_page)(struct page *);
  8396. +
  8397. + /* Write back some dirty pages from this mapping. */
  8398. + int (*writepages)(struct address_space *, struct writeback_control *);
  8399. +
  8400. + /* Set a page dirty. Return true if this dirtied it */
  8401. + int (*set_page_dirty)(struct page *page);
  8402. +
  8403. + int (*readpages)(struct file *filp, struct address_space *mapping,
  8404. + struct list_head *pages, unsigned nr_pages);
  8405. +
  8406. + /*
  8407. + * ext3 requires that a successful prepare_write() call be followed
  8408. + * by a commit_write() call - they must be balanced
  8409. + */
  8410. + int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
  8411. + int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
  8412. + /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
  8413. + sector_t (*bmap)(struct address_space *, sector_t);
  8414. + void (*invalidatepage) (struct page *, unsigned long);
  8415. + int (*releasepage) (struct page *, gfp_t);
  8416. + ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
  8417. + loff_t offset, unsigned long nr_segs);
  8418. + struct page* (*get_xip_page)(struct address_space *, sector_t,
  8419. + int);
  8420. + /* migrate the contents of a page to the specified target */
  8421. + int (*migratepage) (struct page *, struct page *);
  8422. +};
  8423. +#endif
  8424. +
  8425. +struct address_space_operations aufs_aop = {
  8426. + .readpage = aufs_readpage,
  8427. +#ifdef CONFIG_AUFS_DEBUG
  8428. + .writepage = aufs_writepage,
  8429. + .sync_page = aufs_sync_page,
  8430. + //.writepages = aufs_writepages,
  8431. + .set_page_dirty = aufs_set_page_dirty,
  8432. + //.readpages = aufs_readpages,
  8433. + .prepare_write = aufs_prepare_write,
  8434. + .commit_write = aufs_commit_write,
  8435. + //.bmap = aufs_bmap,
  8436. + .invalidatepage = aufs_invalidatepage,
  8437. + .releasepage = aufs_releasepage,
  8438. + .direct_IO = aufs_direct_IO,
  8439. + .get_xip_page = aufs_get_xip_page,
  8440. + //.migratepage = aufs_migratepage
  8441. +#endif
  8442. +};
  8443. diff --git a/fs/aufs/file.h b/fs/aufs/file.h
  8444. new file mode 100755
  8445. index 0000000..f0fa448
  8446. --- /dev/null
  8447. +++ b/fs/aufs/file.h
  8448. @@ -0,0 +1,140 @@
  8449. +/*
  8450. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  8451. + *
  8452. + * This program, aufs is free software; you can redistribute it and/or modify
  8453. + * it under the terms of the GNU General Public License as published by
  8454. + * the Free Software Foundation; either version 2 of the License, or
  8455. + * (at your option) any later version.
  8456. + *
  8457. + * This program is distributed in the hope that it will be useful,
  8458. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8459. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8460. + * GNU General Public License for more details.
  8461. + *
  8462. + * You should have received a copy of the GNU General Public License
  8463. + * along with this program; if not, write to the Free Software
  8464. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8465. + */
  8466. +
  8467. +/* $Id: file.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
  8468. +
  8469. +#ifndef __AUFS_FILE_H__
  8470. +#define __AUFS_FILE_H__
  8471. +
  8472. +#ifdef __KERNEL__
  8473. +
  8474. +#include <linux/file.h>
  8475. +#include <linux/fs.h>
  8476. +#include <linux/version.h>
  8477. +#include <linux/aufs_type.h>
  8478. +#include "misc.h"
  8479. +
  8480. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  8481. +// SEEK_xxx are defined in linux/fs.h
  8482. +#else
  8483. +enum {SEEK_SET, SEEK_CUR, SEEK_END};
  8484. +#endif
  8485. +
  8486. +/* ---------------------------------------------------------------------- */
  8487. +
  8488. +struct aufs_branch;
  8489. +struct aufs_hfile {
  8490. + struct file *hf_file;
  8491. + struct aufs_branch *hf_br;
  8492. +};
  8493. +
  8494. +struct aufs_vdir;
  8495. +struct aufs_finfo {
  8496. + atomic_t fi_generation;
  8497. +
  8498. + struct aufs_rwsem fi_rwsem;
  8499. + struct aufs_hfile *fi_hfile;
  8500. + aufs_bindex_t fi_bstart, fi_bend;
  8501. +
  8502. + union {
  8503. + struct vm_operations_struct *fi_h_vm_ops;
  8504. + struct aufs_vdir *fi_vdir_cache;
  8505. + };
  8506. +};
  8507. +
  8508. +/* ---------------------------------------------------------------------- */
  8509. +
  8510. +/* file.c */
  8511. +extern struct address_space_operations aufs_aop;
  8512. +unsigned int au_file_roflags(unsigned int flags);
  8513. +struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex,
  8514. + int flags);
  8515. +int au_do_open(struct inode *inode, struct file *file,
  8516. + int (*open)(struct file *file, int flags));
  8517. +int au_reopen_nondir(struct file *file);
  8518. +int au_ready_to_write(struct file *file, loff_t len);
  8519. +int au_reval_and_lock_finfo(struct file *file, int (*reopen)(struct file *file),
  8520. + int wlock, int locked);
  8521. +
  8522. +/* f_op.c */
  8523. +extern struct file_operations aufs_file_fop;
  8524. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  8525. +int aufs_flush(struct file *file, fl_owner_t id);
  8526. +#else
  8527. +int aufs_flush(struct file *file);
  8528. +#endif
  8529. +
  8530. +/* finfo.c */
  8531. +struct aufs_finfo *ftofi(struct file *file);
  8532. +aufs_bindex_t fbstart(struct file *file);
  8533. +aufs_bindex_t fbend(struct file *file);
  8534. +struct aufs_vdir *fvdir_cache(struct file *file);
  8535. +struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex);
  8536. +struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex);
  8537. +struct file *au_h_fptr(struct file *file);
  8538. +
  8539. +void set_fbstart(struct file *file, aufs_bindex_t bindex);
  8540. +void set_fbend(struct file *file, aufs_bindex_t bindex);
  8541. +void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache);
  8542. +void au_hfput(struct aufs_hfile *hf);
  8543. +void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *h_file);
  8544. +void au_update_figen(struct file *file);
  8545. +
  8546. +void au_fin_finfo(struct file *file);
  8547. +int au_init_finfo(struct file *file);
  8548. +
  8549. +/* ---------------------------------------------------------------------- */
  8550. +
  8551. +static inline int au_figen(struct file *f)
  8552. +{
  8553. + return atomic_read(&ftofi(f)->fi_generation);
  8554. +}
  8555. +
  8556. +static inline int au_is_mmapped(struct file *f)
  8557. +{
  8558. + return !!(ftofi(f)->fi_h_vm_ops);
  8559. +}
  8560. +
  8561. +/* ---------------------------------------------------------------------- */
  8562. +
  8563. +/*
  8564. + * fi_read_lock, fi_write_lock,
  8565. + * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
  8566. + */
  8567. +SimpleRwsemFuncs(fi, struct file *f, ftofi(f)->fi_rwsem);
  8568. +
  8569. +/* to debug easier, do not make them inlined functions */
  8570. +#define FiMustReadLock(f) do {\
  8571. + SiMustAnyLock((f)->f_dentry->d_sb); \
  8572. + RwMustReadLock(&ftofi(f)->fi_rwsem); \
  8573. +} while (0)
  8574. +
  8575. +#define FiMustWriteLock(f) do { \
  8576. + SiMustAnyLock((f)->f_dentry->d_sb); \
  8577. + RwMustWriteLock(&ftofi(f)->fi_rwsem); \
  8578. +} while (0)
  8579. +
  8580. +#define FiMustAnyLock(f) do { \
  8581. + SiMustAnyLock((f)->f_dentry->d_sb); \
  8582. + RwMustAnyLock(&ftofi(f)->fi_rwsem); \
  8583. +} while (0)
  8584. +
  8585. +#define FiMustNoWaiters(f) RwMustNoWaiters(&ftofi(f)->fi_rwsem)
  8586. +
  8587. +#endif /* __KERNEL__ */
  8588. +#endif /* __AUFS_FILE_H__ */
  8589. diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c
  8590. new file mode 100755
  8591. index 0000000..1e09da8
  8592. --- /dev/null
  8593. +++ b/fs/aufs/finfo.c
  8594. @@ -0,0 +1,211 @@
  8595. +/*
  8596. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  8597. + *
  8598. + * This program, aufs is free software; you can redistribute it and/or modify
  8599. + * it under the terms of the GNU General Public License as published by
  8600. + * the Free Software Foundation; either version 2 of the License, or
  8601. + * (at your option) any later version.
  8602. + *
  8603. + * This program is distributed in the hope that it will be useful,
  8604. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8605. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8606. + * GNU General Public License for more details.
  8607. + *
  8608. + * You should have received a copy of the GNU General Public License
  8609. + * along with this program; if not, write to the Free Software
  8610. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8611. + */
  8612. +
  8613. +/* $Id: finfo.c,v 1.23 2007/04/30 05:45:21 sfjro Exp $ */
  8614. +
  8615. +#include "aufs.h"
  8616. +
  8617. +struct aufs_finfo *ftofi(struct file *file)
  8618. +{
  8619. + struct aufs_finfo *finfo = file->private_data;
  8620. + DEBUG_ON(!finfo
  8621. + || !finfo->fi_hfile
  8622. + || (0 < finfo->fi_bend
  8623. + && (/* stosi(file->f_dentry->d_sb)->si_bend
  8624. + < finfo->fi_bend
  8625. + || */ finfo->fi_bend < finfo->fi_bstart)));
  8626. + return finfo;
  8627. +}
  8628. +
  8629. +// hard/soft set
  8630. +aufs_bindex_t fbstart(struct file *file)
  8631. +{
  8632. + FiMustAnyLock(file);
  8633. + return ftofi(file)->fi_bstart;
  8634. +}
  8635. +
  8636. +aufs_bindex_t fbend(struct file *file)
  8637. +{
  8638. + FiMustAnyLock(file);
  8639. + return ftofi(file)->fi_bend;
  8640. +}
  8641. +
  8642. +struct aufs_vdir *fvdir_cache(struct file *file)
  8643. +{
  8644. + FiMustAnyLock(file);
  8645. + return ftofi(file)->fi_vdir_cache;
  8646. +}
  8647. +
  8648. +struct aufs_branch *ftobr(struct file *file, aufs_bindex_t bindex)
  8649. +{
  8650. + struct aufs_finfo *finfo = ftofi(file);
  8651. + struct aufs_hfile *hf;
  8652. +
  8653. + FiMustAnyLock(file);
  8654. + DEBUG_ON(!finfo
  8655. + || finfo->fi_bstart < 0
  8656. + || bindex < finfo->fi_bstart
  8657. + || finfo->fi_bend < bindex);
  8658. + hf = finfo->fi_hfile + bindex;
  8659. + DEBUG_ON(hf->hf_br && br_count(hf->hf_br) <= 0);
  8660. + return hf->hf_br;
  8661. +}
  8662. +
  8663. +struct file *au_h_fptr_i(struct file *file, aufs_bindex_t bindex)
  8664. +{
  8665. + struct aufs_finfo *finfo = ftofi(file);
  8666. + struct aufs_hfile *hf;
  8667. +
  8668. + FiMustAnyLock(file);
  8669. + DEBUG_ON(!finfo
  8670. + || finfo->fi_bstart < 0
  8671. + || bindex < finfo->fi_bstart
  8672. + || finfo->fi_bend < bindex);
  8673. + hf = finfo->fi_hfile + bindex;
  8674. + DEBUG_ON(hf->hf_file
  8675. + && file_count(hf->hf_file) <= 0
  8676. + && br_count(hf->hf_br) <= 0);
  8677. + return hf->hf_file;
  8678. +}
  8679. +
  8680. +struct file *au_h_fptr(struct file *file)
  8681. +{
  8682. + return au_h_fptr_i(file, fbstart(file));
  8683. +}
  8684. +
  8685. +void set_fbstart(struct file *file, aufs_bindex_t bindex)
  8686. +{
  8687. + FiMustWriteLock(file);
  8688. + DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex);
  8689. + ftofi(file)->fi_bstart = bindex;
  8690. +}
  8691. +
  8692. +void set_fbend(struct file *file, aufs_bindex_t bindex)
  8693. +{
  8694. + FiMustWriteLock(file);
  8695. + DEBUG_ON(sbend(file->f_dentry->d_sb) < bindex
  8696. + || bindex < fbstart(file));
  8697. + ftofi(file)->fi_bend = bindex;
  8698. +}
  8699. +
  8700. +void set_fvdir_cache(struct file *file, struct aufs_vdir *vdir_cache)
  8701. +{
  8702. + FiMustWriteLock(file);
  8703. + DEBUG_ON(!S_ISDIR(file->f_dentry->d_inode->i_mode)
  8704. + || (ftofi(file)->fi_vdir_cache && vdir_cache));
  8705. + ftofi(file)->fi_vdir_cache = vdir_cache;
  8706. +}
  8707. +
  8708. +void au_hfput(struct aufs_hfile *hf)
  8709. +{
  8710. + fput(hf->hf_file);
  8711. + hf->hf_file = NULL;
  8712. + DEBUG_ON(!hf->hf_br);
  8713. + br_put(hf->hf_br);
  8714. + hf->hf_br = NULL;
  8715. +}
  8716. +
  8717. +void set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
  8718. +{
  8719. + struct aufs_finfo *finfo = ftofi(file);
  8720. + struct aufs_hfile *hf;
  8721. +
  8722. + FiMustWriteLock(file);
  8723. + DEBUG_ON(!finfo
  8724. + || finfo->fi_bstart < 0
  8725. + || bindex < finfo->fi_bstart
  8726. + || finfo->fi_bend < bindex);
  8727. + DEBUG_ON(val && file_count(val) <= 0);
  8728. + hf = finfo->fi_hfile + bindex;
  8729. + DEBUG_ON(val && hf->hf_file);
  8730. + if (hf->hf_file)
  8731. + au_hfput(hf);
  8732. + if (val) {
  8733. + hf->hf_file = val;
  8734. + hf->hf_br = stobr(file->f_dentry->d_sb, bindex);
  8735. + }
  8736. +}
  8737. +
  8738. +void au_update_figen(struct file *file)
  8739. +{
  8740. + atomic_set(&ftofi(file)->fi_generation, au_digen(file->f_dentry));
  8741. +}
  8742. +
  8743. +void au_fin_finfo(struct file *file)
  8744. +{
  8745. + struct aufs_finfo *finfo;
  8746. + struct dentry *dentry;
  8747. + aufs_bindex_t bindex, bend;
  8748. +
  8749. + dentry = file->f_dentry;
  8750. + LKTRTrace("%.*s\n", DLNPair(dentry));
  8751. + SiMustAnyLock(dentry->d_sb);
  8752. +
  8753. + fi_write_lock(file);
  8754. + bend = fbend(file);
  8755. + bindex = fbstart(file);
  8756. + if (bindex >= 0)
  8757. + for (; bindex <= bend; bindex++)
  8758. + set_h_fptr(file, bindex, NULL);
  8759. +
  8760. + finfo = ftofi(file);
  8761. +#ifdef CONFIG_AUFS_DEBUG
  8762. + if (finfo->fi_bstart >= 0) {
  8763. + bend = fbend(file);
  8764. + for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
  8765. + struct aufs_hfile *hf;
  8766. + hf = finfo->fi_hfile + bindex;
  8767. + DEBUG_ON(hf->hf_file || hf->hf_br);
  8768. + }
  8769. + }
  8770. +#endif
  8771. +
  8772. + kfree(finfo->fi_hfile);
  8773. + fi_write_unlock(file);
  8774. + cache_free_finfo(finfo);
  8775. + //file->private_data = NULL;
  8776. +}
  8777. +
  8778. +int au_init_finfo(struct file *file)
  8779. +{
  8780. + struct aufs_finfo *finfo;
  8781. + struct dentry *dentry;
  8782. +
  8783. + dentry = file->f_dentry;
  8784. + LKTRTrace("%.*s\n", DLNPair(dentry));
  8785. + DEBUG_ON(!dentry->d_inode);
  8786. +
  8787. + finfo = cache_alloc_finfo();
  8788. + if (finfo) {
  8789. + finfo->fi_hfile = kcalloc(sbend(dentry->d_sb) + 1,
  8790. + sizeof(*finfo->fi_hfile), GFP_KERNEL);
  8791. + if (finfo->fi_hfile) {
  8792. + rw_init_wlock(&finfo->fi_rwsem);
  8793. + finfo->fi_bstart = -1;
  8794. + finfo->fi_bend = -1;
  8795. + atomic_set(&finfo->fi_generation, au_digen(dentry));
  8796. +
  8797. + file->private_data = finfo;
  8798. + return 0; /* success */
  8799. + }
  8800. + cache_free_finfo(finfo);
  8801. + }
  8802. +
  8803. + TraceErr(-ENOMEM);
  8804. + return -ENOMEM;
  8805. +}
  8806. diff --git a/fs/aufs/hinotify.c b/fs/aufs/hinotify.c
  8807. new file mode 100755
  8808. index 0000000..3bad3f7
  8809. --- /dev/null
  8810. +++ b/fs/aufs/hinotify.c
  8811. @@ -0,0 +1,536 @@
  8812. +/*
  8813. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  8814. + *
  8815. + * This program, aufs is free software; you can redistribute it and/or modify
  8816. + * it under the terms of the GNU General Public License as published by
  8817. + * the Free Software Foundation; either version 2 of the License, or
  8818. + * (at your option) any later version.
  8819. + *
  8820. + * This program is distributed in the hope that it will be useful,
  8821. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8822. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8823. + * GNU General Public License for more details.
  8824. + *
  8825. + * You should have received a copy of the GNU General Public License
  8826. + * along with this program; if not, write to the Free Software
  8827. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8828. + */
  8829. +
  8830. +/* $Id: hinotify.c,v 1.19 2007/05/14 03:39:21 sfjro Exp $ */
  8831. +
  8832. +#include "aufs.h"
  8833. +
  8834. +static struct inotify_handle *in_handle;
  8835. +static const __u32 in_mask = (IN_MOVE | IN_DELETE | IN_CREATE /* | IN_ACCESS */
  8836. + | IN_MODIFY | IN_ATTRIB
  8837. + | IN_DELETE_SELF | IN_MOVE_SELF);
  8838. +
  8839. +int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
  8840. + struct inode *hidden_inode)
  8841. +{
  8842. + int err;
  8843. + struct aufs_hinotify *hin;
  8844. + s32 wd;
  8845. +
  8846. + LKTRTrace("i%lu, hi%lu\n", inode->i_ino, hidden_inode->i_ino);
  8847. +
  8848. + err = -ENOMEM;
  8849. + hin = cache_alloc_hinotify();
  8850. + if (hin) {
  8851. + DEBUG_ON(hinode->hi_notify);
  8852. + hinode->hi_notify = hin;
  8853. + hin->hin_aufs_inode = inode;
  8854. + inotify_init_watch(&hin->hin_watch);
  8855. + wd = inotify_add_watch(in_handle, &hin->hin_watch, hidden_inode,
  8856. + in_mask);
  8857. + if (wd >= 0)
  8858. + return 0; /* success */
  8859. +
  8860. + err = wd;
  8861. + put_inotify_watch(&hin->hin_watch);
  8862. + cache_free_hinotify(hin);
  8863. + hinode->hi_notify = NULL;
  8864. + }
  8865. +
  8866. + TraceErr(err);
  8867. + return err;
  8868. +}
  8869. +
  8870. +void do_free_hinotify(struct aufs_hinode *hinode)
  8871. +{
  8872. + int err;
  8873. + struct aufs_hinotify *hin;
  8874. +
  8875. + TraceEnter();
  8876. +
  8877. + hin = hinode->hi_notify;
  8878. + if (hin) {
  8879. + err = 0;
  8880. + if (atomic_read(&hin->hin_watch.count))
  8881. + err = inotify_rm_watch(in_handle, &hin->hin_watch);
  8882. +
  8883. + if (!err) {
  8884. + cache_free_hinotify(hin);
  8885. + hinode->hi_notify = NULL;
  8886. + } else
  8887. + IOErr1("failed inotify_rm_watch() %d\n", err);
  8888. + }
  8889. +}
  8890. +
  8891. +/* ---------------------------------------------------------------------- */
  8892. +
  8893. +static void ctl_hinotify(struct aufs_hinode *hinode, const __u32 mask)
  8894. +{
  8895. + struct inode *hi;
  8896. + struct inotify_watch *watch;
  8897. +
  8898. + hi = hinode->hi_inode;
  8899. + LKTRTrace("hi%lu, sb %p, 0x%x\n", hi->i_ino, hi->i_sb, mask);
  8900. + if (0 && !strcmp(current->comm, "link"))
  8901. + dump_stack();
  8902. + IMustLock(hi);
  8903. + if (!hinode->hi_notify)
  8904. + return;
  8905. +
  8906. + watch = &hinode->hi_notify->hin_watch;
  8907. +#if 0
  8908. + {
  8909. + u32 wd;
  8910. + wd = inotify_find_update_watch(in_handle, hi, mask);
  8911. + TraceErr(wd);
  8912. + // ignore an err;
  8913. + }
  8914. +#else
  8915. + watch->mask = mask;
  8916. + smp_mb();
  8917. +#endif
  8918. + LKTRTrace("watch %p, mask %u\n", watch, watch->mask);
  8919. +}
  8920. +
  8921. +#define suspend_hinotify(hi) ctl_hinotify(hi, 0)
  8922. +#define resume_hinotify(hi) ctl_hinotify(hi, in_mask)
  8923. +
  8924. +void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
  8925. + unsigned int lsc)
  8926. +{
  8927. + struct aufs_hinode *hinode;
  8928. +
  8929. + LKTRTrace("i%lu, b%d, lsc %d\n", dir->i_ino, bindex, lsc);
  8930. + DEBUG_ON(!S_ISDIR(dir->i_mode));
  8931. + hinode = itoii(dir)->ii_hinode + bindex;
  8932. + DEBUG_ON(h_dir != hinode->hi_inode);
  8933. +
  8934. + hi_lock(h_dir, lsc);
  8935. + if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
  8936. + suspend_hinotify(hinode);
  8937. +}
  8938. +
  8939. +void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
  8940. +{
  8941. + struct aufs_hinode *hinode;
  8942. +
  8943. + LKTRTrace("i%lu, b%d\n", dir->i_ino, bindex);
  8944. + DEBUG_ON(!S_ISDIR(dir->i_mode));
  8945. + hinode = itoii(dir)->ii_hinode + bindex;
  8946. + DEBUG_ON(h_dir != hinode->hi_inode);
  8947. +
  8948. + if (1 /* unlikely(au_flag_test(dir->i_sb, AuFlag_UDBA_HINOTIFY) */)
  8949. + resume_hinotify(hinode);
  8950. + i_unlock(h_dir);
  8951. +}
  8952. +
  8953. +void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
  8954. + aufs_bindex_t bindex, int issamedir)
  8955. +{
  8956. + struct aufs_hinode *hinode;
  8957. +
  8958. + LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
  8959. +
  8960. + vfsub_lock_rename(h_parents[0], h_parents[1]);
  8961. + hinode = itoii(dirs[0])->ii_hinode + bindex;
  8962. + DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
  8963. + suspend_hinotify(hinode);
  8964. + if (issamedir)
  8965. + return;
  8966. + hinode = itoii(dirs[1])->ii_hinode + bindex;
  8967. + DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
  8968. + suspend_hinotify(hinode);
  8969. +}
  8970. +
  8971. +void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
  8972. + aufs_bindex_t bindex, int issamedir)
  8973. +{
  8974. + struct aufs_hinode *hinode;
  8975. +
  8976. + LKTRTrace("%.*s, %.*s\n", DLNPair(h_parents[0]), DLNPair(h_parents[1]));
  8977. +
  8978. + hinode = itoii(dirs[0])->ii_hinode + bindex;
  8979. + DEBUG_ON(h_parents[0]->d_inode != hinode->hi_inode);
  8980. + resume_hinotify(hinode);
  8981. + if (!issamedir) {
  8982. + hinode = itoii(dirs[1])->ii_hinode + bindex;
  8983. + DEBUG_ON(h_parents[1]->d_inode != hinode->hi_inode);
  8984. + resume_hinotify(hinode);
  8985. + }
  8986. + vfsub_unlock_rename(h_parents[0], h_parents[1]);
  8987. +}
  8988. +
  8989. +void au_reset_hinotify(struct inode *inode, unsigned int flags)
  8990. +{
  8991. + aufs_bindex_t bindex, bend;
  8992. + struct inode *hi;
  8993. +
  8994. + LKTRTrace("i%lu, 0x%x\n", inode->i_ino, flags);
  8995. +
  8996. + bend = ibend(inode);
  8997. + for (bindex = ibstart(inode); bindex <= bend; bindex++) {
  8998. + hi = au_h_iptr_i(inode, bindex);
  8999. + if (hi) {
  9000. + //hi_lock(hi, AUFS_LSC_H_CHILD);
  9001. + igrab(hi);
  9002. + set_h_iptr(inode, bindex, NULL, 0);
  9003. + set_h_iptr(inode, bindex, igrab(hi), flags);
  9004. + iput(hi);
  9005. + //i_unlock(hi);
  9006. + }
  9007. + }
  9008. +}
  9009. +
  9010. +/* ---------------------------------------------------------------------- */
  9011. +
  9012. +#ifdef CONFIG_AUFS_DEBUG
  9013. +static char *in_name(u32 mask)
  9014. +{
  9015. +#define test_ret(flag) if (mask & flag) return #flag;
  9016. + test_ret(IN_ACCESS);
  9017. + test_ret(IN_MODIFY);
  9018. + test_ret(IN_ATTRIB);
  9019. + test_ret(IN_CLOSE_WRITE);
  9020. + test_ret(IN_CLOSE_NOWRITE);
  9021. + test_ret(IN_OPEN);
  9022. + test_ret(IN_MOVED_FROM);
  9023. + test_ret(IN_MOVED_TO);
  9024. + test_ret(IN_CREATE);
  9025. + test_ret(IN_DELETE);
  9026. + test_ret(IN_DELETE_SELF);
  9027. + test_ret(IN_MOVE_SELF);
  9028. + test_ret(IN_UNMOUNT);
  9029. + test_ret(IN_Q_OVERFLOW);
  9030. + test_ret(IN_IGNORED);
  9031. + return "";
  9032. +#undef test_ret
  9033. +}
  9034. +#else
  9035. +#define in_name(m) "??"
  9036. +#endif
  9037. +
  9038. +static int dec_gen_by_name(struct inode *dir, const char *_name, u32 mask)
  9039. +{
  9040. + int err;
  9041. + struct dentry *parent, *child;
  9042. + struct inode *inode;
  9043. + struct qstr *dname;
  9044. + char *name = (void*)_name;
  9045. + unsigned int len;
  9046. +
  9047. + LKTRTrace("i%lu, %s, 0x%x %s\n",
  9048. + dir->i_ino, name, mask, in_name(mask));
  9049. +
  9050. + err = -1;
  9051. + parent = d_find_alias(dir);
  9052. + if (unlikely(!parent))
  9053. + goto out;
  9054. +
  9055. +#if 0
  9056. + if (unlikely(!memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
  9057. + name += AUFS_WH_PFX_LEN;
  9058. +#endif
  9059. + len = strlen(name);
  9060. + spin_lock(&dcache_lock);
  9061. + list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
  9062. + dname = &child->d_name;
  9063. + if (len == dname->len && !memcmp(dname->name, name, len)) {
  9064. + au_digen_dec(child);
  9065. +#if 1
  9066. + //todo: why both are needed
  9067. + if (mask & IN_MOVE) {
  9068. + spin_lock(&child->d_lock);
  9069. + __d_drop(child);
  9070. + spin_unlock(&child->d_lock);
  9071. + }
  9072. +#endif
  9073. +
  9074. + inode = child->d_inode;
  9075. + if (inode)
  9076. + au_iigen_dec(inode);
  9077. + err = !!inode;
  9078. +
  9079. + // todo: the i_nlink of newly created name by link(2)
  9080. + // should be updated
  9081. + // todo: some nfs dentry doesn't notified at deleteing
  9082. + break;
  9083. + }
  9084. + }
  9085. + spin_unlock(&dcache_lock);
  9086. + dput(parent);
  9087. +
  9088. + out:
  9089. + TraceErr(err);
  9090. + return err;
  9091. +}
  9092. +
  9093. +struct postproc_args {
  9094. + struct inode *h_dir, *dir, *h_child_inode;
  9095. + char *h_child_name;
  9096. + u32 mask;
  9097. +};
  9098. +
  9099. +static void dec_gen_by_ino(struct postproc_args *a)
  9100. +{
  9101. + struct super_block *sb;
  9102. + aufs_bindex_t bindex, bend, bfound;
  9103. + struct xino xino;
  9104. + struct inode *cinode;
  9105. +
  9106. + TraceEnter();
  9107. +
  9108. + sb = a->dir->i_sb;
  9109. + DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
  9110. +
  9111. + bfound = -1;
  9112. + bend = ibend(a->dir);
  9113. + for (bindex = ibstart(a->dir); bfound == -1 && bindex <= bend; bindex++)
  9114. + if (au_h_iptr_i(a->dir, bindex) == a->h_dir)
  9115. + bfound = bindex;
  9116. + if (bfound < 0)
  9117. + return;
  9118. +
  9119. + bindex = find_brindex(sb, itoii(a->dir)->ii_hinode[bfound + 0].hi_id);
  9120. + if (bindex < 0)
  9121. + return;
  9122. + if (unlikely(xino_read(sb, bindex, a->h_child_inode->i_ino, &xino)))
  9123. + return;
  9124. + cinode = NULL;
  9125. + if (xino.ino)
  9126. + cinode = ilookup(sb, xino.ino);
  9127. + if (cinode) {
  9128. +#if 1
  9129. + if (1 || a->mask & IN_MOVE) {
  9130. + struct dentry *child;
  9131. + spin_lock(&dcache_lock);
  9132. + list_for_each_entry(child, &cinode->i_dentry, d_alias)
  9133. + au_digen_dec(child);
  9134. + spin_unlock(&dcache_lock);
  9135. + }
  9136. +#endif
  9137. + au_iigen_dec(cinode);
  9138. + iput(cinode);
  9139. + }
  9140. +}
  9141. +
  9142. +static void reset_ino(struct postproc_args *a)
  9143. +{
  9144. + aufs_bindex_t bindex, bend;
  9145. + struct super_block *sb;
  9146. + struct inode *h_dir;
  9147. +
  9148. + sb = a->dir->i_sb;
  9149. + bend = ibend(a->dir);
  9150. + for (bindex = ibstart(a->dir); bindex <= bend; bindex++) {
  9151. + h_dir = au_h_iptr_i(a->dir, bindex);
  9152. + if (h_dir && h_dir != a->h_dir)
  9153. + xino_write0(sb, bindex, h_dir->i_ino);
  9154. + /* ignore this error */
  9155. + }
  9156. +}
  9157. +
  9158. +static void postproc(void *args)
  9159. +{
  9160. + struct postproc_args *a = args;
  9161. + struct super_block *sb;
  9162. + struct aufs_vdir *vdir;
  9163. +
  9164. + //au_debug_on();
  9165. + LKTRTrace("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
  9166. + a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
  9167. + a->h_child_inode ? a->h_child_inode->i_ino : 0);
  9168. + DEBUG_ON(!a->dir);
  9169. +#if 0//def ForceInotify
  9170. + Dbg("mask 0x%x %s, i%lu, hi%lu, hci%lu\n",
  9171. + a->mask, in_name(a->mask), a->dir->i_ino, a->h_dir->i_ino,
  9172. + a->h_child_inode ? a->h_child_inode->i_ino : 0);
  9173. +#endif
  9174. +
  9175. + i_lock(a->dir);
  9176. + sb = a->dir->i_sb;
  9177. + si_read_lock(sb); // consider write_lock
  9178. + ii_write_lock_parent(a->dir);
  9179. +
  9180. + /* make dir entries obsolete */
  9181. + vdir = ivdir(a->dir);
  9182. + if (vdir)
  9183. + vdir->vd_jiffy = 0;
  9184. + a->dir->i_version++;
  9185. +
  9186. + /*
  9187. + * special handling root directory,
  9188. + * sine d_revalidate may not be called later.
  9189. + * main purpose is maintaining i_nlink.
  9190. + */
  9191. + if (unlikely(a->dir->i_ino == AUFS_ROOT_INO))
  9192. + au_cpup_attr_all(a->dir);
  9193. +
  9194. + if (a->h_child_inode && au_flag_test(sb, AuFlag_XINO))
  9195. + dec_gen_by_ino(a);
  9196. + else if (a->mask & (IN_MOVE_SELF | IN_DELETE_SELF))
  9197. + reset_ino(a);
  9198. +
  9199. + ii_write_unlock(a->dir);
  9200. + si_read_unlock(sb);
  9201. + i_unlock(a->dir);
  9202. +
  9203. + au_mntput(a->dir->i_sb);
  9204. + iput(a->h_child_inode);
  9205. + iput(a->h_dir);
  9206. + iput(a->dir);
  9207. +#if 0
  9208. + if (atomic_dec_and_test(&stosi(sb)->si_hinotify))
  9209. + wake_up_all(&stosi(sb)->si_hinotify_wq);
  9210. +#endif
  9211. + kfree(a);
  9212. + //au_debug_off();
  9213. +}
  9214. +
  9215. +static void aufs_inotify(struct inotify_watch *watch, u32 wd, u32 mask,
  9216. + u32 cookie, const char *h_child_name,
  9217. + struct inode *h_child_inode)
  9218. +{
  9219. + struct aufs_hinotify *hinotify;
  9220. + struct postproc_args *args;
  9221. + int len;
  9222. + char *p;
  9223. + struct inode *dir;
  9224. + //static DECLARE_WAIT_QUEUE_HEAD(wq);
  9225. +
  9226. + //au_debug_on();
  9227. + LKTRTrace("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
  9228. + watch->inode->i_ino, wd, mask, in_name(mask), cookie,
  9229. + h_child_name ? h_child_name : "",
  9230. + h_child_inode ? h_child_inode->i_ino : 0);
  9231. + //au_debug_off();
  9232. + //IMustLock(h_dir);
  9233. +#if 0 //defined(ForceInotify) || defined(DbgInotify)
  9234. + Dbg("i%lu, wd %d, mask 0x%x %s, cookie 0x%x, hcname %s, hi%lu\n",
  9235. + watch->inode->i_ino, wd, mask, in_name(mask), cookie,
  9236. + h_child_name ? h_child_name : "",
  9237. + h_child_inode ? h_child_inode->i_ino : 0);
  9238. +#endif
  9239. + /* if IN_UNMOUNT happens, there must be another bug */
  9240. + if (mask & (IN_IGNORED | IN_UNMOUNT)) {
  9241. + put_inotify_watch(watch);
  9242. + return;
  9243. + }
  9244. +
  9245. + switch (mask & IN_ALL_EVENTS) {
  9246. + case IN_MODIFY:
  9247. + case IN_ATTRIB:
  9248. + if (h_child_name)
  9249. + return;
  9250. + break;
  9251. +
  9252. + case IN_MOVED_FROM:
  9253. + case IN_MOVED_TO:
  9254. + case IN_CREATE:
  9255. + DEBUG_ON(!h_child_name || !h_child_inode);
  9256. + break;
  9257. + case IN_DELETE:
  9258. + /*
  9259. + * aufs never be able to get this child inode.
  9260. + * revalidation should be in d_revalide()
  9261. + * by checking i_nlink, i_generation or d_unhashed().
  9262. + */
  9263. + DEBUG_ON(!h_child_name);
  9264. + break;
  9265. +
  9266. + case IN_DELETE_SELF:
  9267. + case IN_MOVE_SELF:
  9268. + DEBUG_ON(h_child_name || h_child_inode);
  9269. + break;
  9270. +
  9271. + case IN_ACCESS:
  9272. + default:
  9273. + DEBUG_ON(1);
  9274. + }
  9275. +
  9276. +#ifdef DbgInotify
  9277. + WARN_ON(1);
  9278. +#endif
  9279. +
  9280. + /* iput() will be called in postproc() */
  9281. + hinotify = container_of(watch, struct aufs_hinotify, hin_watch);
  9282. + DEBUG_ON(!hinotify || !hinotify->hin_aufs_inode);
  9283. + dir = hinotify->hin_aufs_inode;
  9284. +
  9285. + /* force re-lookup in next d_revalidate() */
  9286. + if (dir->i_ino != AUFS_ROOT_INO)
  9287. + au_iigen_dec(dir);
  9288. + len = 0;
  9289. + if (h_child_name && dec_gen_by_name(dir, h_child_name, mask))
  9290. + len = strlen(h_child_name);
  9291. +
  9292. + //wait_event(wq, (args = kmalloc(sizeof(*args), GFP_KERNEL)));
  9293. + args = kmalloc(sizeof(*args) + len + 1, GFP_KERNEL);
  9294. + if (unlikely(!args)) {
  9295. + Err("no memory\n");
  9296. + return;
  9297. + }
  9298. + args->mask = mask;
  9299. + args->dir = igrab(dir);
  9300. + args->h_dir = igrab(watch->inode);
  9301. + args->h_child_inode = NULL;
  9302. + if (len) {
  9303. + if (h_child_inode)
  9304. + args->h_child_inode = igrab(h_child_inode);
  9305. + p = (void*)args;
  9306. + args->h_child_name = p + sizeof(*args);
  9307. + memcpy(args->h_child_name, h_child_name, len + 1);
  9308. + }
  9309. + //atomic_inc(&stosi(args->dir->i_sb)->si_hinotify);
  9310. + /* prohibit umount */
  9311. + au_mntget(args->dir->i_sb);
  9312. + au_wkq_nowait(postproc, args, /*dlgt*/0);
  9313. +}
  9314. +
  9315. +#if 0
  9316. +void hinotify_flush(struct super_block *sb)
  9317. +{
  9318. + atomic_t *p = &stosi(sb)->si_hinotify;
  9319. + wait_event(stosi(sb)->si_hinotify_wq, !atomic_read(p));
  9320. +}
  9321. +#endif
  9322. +
  9323. +static void aufs_inotify_destroy(struct inotify_watch *watch)
  9324. +{
  9325. + return;
  9326. +}
  9327. +
  9328. +static struct inotify_operations aufs_inotify_ops = {
  9329. + .handle_event = aufs_inotify,
  9330. + .destroy_watch = aufs_inotify_destroy
  9331. +};
  9332. +
  9333. +/* ---------------------------------------------------------------------- */
  9334. +
  9335. +int __init au_inotify_init(void)
  9336. +{
  9337. + in_handle = inotify_init(&aufs_inotify_ops);
  9338. + if (!IS_ERR(in_handle))
  9339. + return 0;
  9340. + TraceErrPtr(in_handle);
  9341. + return PTR_ERR(in_handle);
  9342. +}
  9343. +
  9344. +void au_inotify_fin(void)
  9345. +{
  9346. + inotify_destroy(in_handle);
  9347. +}
  9348. diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
  9349. new file mode 100755
  9350. index 0000000..1cd0453
  9351. --- /dev/null
  9352. +++ b/fs/aufs/i_op.c
  9353. @@ -0,0 +1,641 @@
  9354. +/*
  9355. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  9356. + *
  9357. + * This program, aufs is free software; you can redistribute it and/or modify
  9358. + * it under the terms of the GNU General Public License as published by
  9359. + * the Free Software Foundation; either version 2 of the License, or
  9360. + * (at your option) any later version.
  9361. + *
  9362. + * This program is distributed in the hope that it will be useful,
  9363. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9364. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9365. + * GNU General Public License for more details.
  9366. + *
  9367. + * You should have received a copy of the GNU General Public License
  9368. + * along with this program; if not, write to the Free Software
  9369. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  9370. + */
  9371. +
  9372. +/* $Id: i_op.c,v 1.30 2007/04/23 00:55:05 sfjro Exp $ */
  9373. +
  9374. +//#include <linux/fs.h>
  9375. +//#include <linux/namei.h>
  9376. +#include <linux/security.h>
  9377. +#include <asm/uaccess.h>
  9378. +#include "aufs.h"
  9379. +
  9380. +#ifdef CONFIG_AUFS_DLGT
  9381. +struct security_inode_permission_args {
  9382. + int *errp;
  9383. + struct inode *h_inode;
  9384. + int mask;
  9385. + struct nameidata *fake_nd;
  9386. +};
  9387. +
  9388. +static void call_security_inode_permission(void *args)
  9389. +{
  9390. + struct security_inode_permission_args *a = args;
  9391. + LKTRTrace("fsuid %d\n", current->fsuid);
  9392. + *a->errp = security_inode_permission(a->h_inode, a->mask, a->fake_nd);
  9393. +}
  9394. +#endif
  9395. +
  9396. +static int hidden_permission(struct inode *hidden_inode, int mask,
  9397. + struct nameidata *fake_nd, int brperm, int dlgt)
  9398. +{
  9399. + int err, submask;
  9400. + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
  9401. +
  9402. + LKTRTrace("ino %lu, mask 0x%x, brperm 0x%x\n",
  9403. + hidden_inode->i_ino, mask, brperm);
  9404. +
  9405. + err = -EACCES;
  9406. + if (unlikely(write_mask && IS_IMMUTABLE(hidden_inode)))
  9407. + goto out;
  9408. +
  9409. + /* skip hidden fs test in the case of write to ro branch */
  9410. + submask = mask & ~MAY_APPEND;
  9411. + if (unlikely((write_mask && !br_writable(brperm))
  9412. + || !hidden_inode->i_op
  9413. + || !hidden_inode->i_op->permission)) {
  9414. + //LKTRLabel(generic_permission);
  9415. + err = generic_permission(hidden_inode, submask, NULL);
  9416. + } else {
  9417. + //LKTRLabel(h_inode->permission);
  9418. + err = hidden_inode->i_op->permission(hidden_inode, submask,
  9419. + fake_nd);
  9420. + TraceErr(err);
  9421. + }
  9422. +
  9423. +#if 1
  9424. + if (!err) {
  9425. +#ifndef CONFIG_AUFS_DLGT
  9426. + err = security_inode_permission(hidden_inode, mask, fake_nd);
  9427. +#else
  9428. + if (!dlgt)
  9429. + err = security_inode_permission(hidden_inode, mask,
  9430. + fake_nd);
  9431. + else {
  9432. + struct security_inode_permission_args args = {
  9433. + .errp = &err,
  9434. + .h_inode = hidden_inode,
  9435. + .mask = mask,
  9436. + .fake_nd = fake_nd
  9437. + };
  9438. + au_wkq_wait(call_security_inode_permission, &args,
  9439. + /*dlgt*/1);
  9440. + }
  9441. +#endif
  9442. + }
  9443. +#endif
  9444. +
  9445. + out:
  9446. + TraceErr(err);
  9447. + return err;
  9448. +}
  9449. +
  9450. +static int silly_lock(struct inode *inode, struct nameidata *nd)
  9451. +{
  9452. + int locked = 0;
  9453. + struct super_block *sb = inode->i_sb;
  9454. +
  9455. + LKTRTrace("i%lu, nd %p\n", inode->i_ino, nd);
  9456. +
  9457. +#ifdef CONFIG_AUFS_FAKE_DM
  9458. + si_read_lock(sb);
  9459. + ii_read_lock_child(inode);
  9460. +#else
  9461. + if (!nd || !nd->dentry) {
  9462. + si_read_lock(sb);
  9463. + ii_read_lock_child(inode);
  9464. + } else if (nd->dentry->d_inode != inode) {
  9465. + locked = 1;
  9466. + /* lock child first, then parent */
  9467. + si_read_lock(sb);
  9468. + ii_read_lock_child(inode);
  9469. + di_read_lock_parent(nd->dentry, 0);
  9470. + } else {
  9471. + locked = 2;
  9472. + aufs_read_lock(nd->dentry, AUFS_I_RLOCK);
  9473. + }
  9474. +#endif
  9475. + return locked;
  9476. +}
  9477. +
  9478. +static void silly_unlock(int locked, struct inode *inode, struct nameidata *nd)
  9479. +{
  9480. + struct super_block *sb = inode->i_sb;
  9481. +
  9482. + LKTRTrace("locked %d, i%lu, nd %p\n", locked, inode->i_ino, nd);
  9483. +
  9484. +#ifdef CONFIG_AUFS_FAKE_DM
  9485. + ii_read_unlock(inode);
  9486. + si_read_unlock(sb);
  9487. +#else
  9488. + switch (locked) {
  9489. + case 0:
  9490. + ii_read_unlock(inode);
  9491. + si_read_unlock(sb);
  9492. + break;
  9493. + case 1:
  9494. + di_read_unlock(nd->dentry, 0);
  9495. + ii_read_unlock(inode);
  9496. + si_read_unlock(sb);
  9497. + break;
  9498. + case 2:
  9499. + aufs_read_unlock(nd->dentry, AUFS_I_RLOCK);
  9500. + break;
  9501. + default:
  9502. + BUG();
  9503. + }
  9504. +#endif
  9505. +}
  9506. +
  9507. +static int aufs_permission(struct inode *inode, int mask, struct nameidata *nd)
  9508. +{
  9509. + int err, locked, dlgt;
  9510. + aufs_bindex_t bindex, bend;
  9511. + struct inode *hidden_inode;
  9512. + struct super_block *sb;
  9513. + struct nameidata fake_nd, *p;
  9514. + const int write_mask = (mask & (MAY_WRITE | MAY_APPEND));
  9515. + const int nondir = !S_ISDIR(inode->i_mode);
  9516. +
  9517. + LKTRTrace("ino %lu, mask 0x%x, nondir %d, write_mask %d, "
  9518. + "nd %p{%p, %p}\n",
  9519. + inode->i_ino, mask, nondir, write_mask,
  9520. + nd, nd ? nd->dentry : NULL, nd ? nd->mnt : NULL);
  9521. +
  9522. + sb = inode->i_sb;
  9523. + locked = silly_lock(inode, nd);
  9524. + dlgt = need_dlgt(sb);
  9525. +
  9526. + if (nd)
  9527. + fake_nd = *nd;
  9528. + if (/* unlikely */(nondir || write_mask)) {
  9529. + hidden_inode = au_h_iptr(inode);
  9530. + DEBUG_ON(!hidden_inode
  9531. + || ((hidden_inode->i_mode & S_IFMT)
  9532. + != (inode->i_mode & S_IFMT)));
  9533. + err = 0;
  9534. + bindex = ibstart(inode);
  9535. + p = fake_dm(&fake_nd, nd, sb, bindex);
  9536. + /* actual test will be delegated to LSM */
  9537. + if (IS_ERR(p))
  9538. + DEBUG_ON(PTR_ERR(p) != -ENOENT);
  9539. + else {
  9540. + err = hidden_permission(hidden_inode, mask, p,
  9541. + sbr_perm(sb, bindex), dlgt);
  9542. + fake_dm_release(p);
  9543. + }
  9544. + if (write_mask && !err) {
  9545. + err = find_rw_br(sb, bindex);
  9546. + if (err >= 0)
  9547. + err = 0;
  9548. + }
  9549. + goto out;
  9550. + }
  9551. +
  9552. + /* non-write to dir */
  9553. + err = 0;
  9554. + bend = ibend(inode);
  9555. + for (bindex = ibstart(inode); !err && bindex <= bend; bindex++) {
  9556. + hidden_inode = au_h_iptr_i(inode, bindex);
  9557. + if (!hidden_inode)
  9558. + continue;
  9559. + DEBUG_ON(!S_ISDIR(hidden_inode->i_mode));
  9560. +
  9561. + p = fake_dm(&fake_nd, nd, sb, bindex);
  9562. + /* actual test will be delegated to LSM */
  9563. + if (IS_ERR(p))
  9564. + DEBUG_ON(PTR_ERR(p) != -ENOENT);
  9565. + else {
  9566. + err = hidden_permission(hidden_inode, mask, p,
  9567. + sbr_perm(sb, bindex), dlgt);
  9568. + fake_dm_release(p);
  9569. + }
  9570. + }
  9571. +
  9572. + out:
  9573. + silly_unlock(locked, inode, nd);
  9574. + TraceErr(err);
  9575. + return err;
  9576. +}
  9577. +
  9578. +/* ---------------------------------------------------------------------- */
  9579. +
  9580. +static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
  9581. + struct nameidata *nd)
  9582. +{
  9583. + struct dentry *ret, *parent;
  9584. + int err, npositive;
  9585. + struct inode *inode;
  9586. +
  9587. + LKTRTrace("dir %lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  9588. + DEBUG_ON(IS_ROOT(dentry));
  9589. + IMustLock(dir);
  9590. +
  9591. + parent = dentry->d_parent; // dget_parent()
  9592. + aufs_read_lock(parent, !AUFS_I_RLOCK);
  9593. + err = au_alloc_dinfo(dentry);
  9594. + //if (LktrCond) err = -1;
  9595. + ret = ERR_PTR(err);
  9596. + if (unlikely(err))
  9597. + goto out;
  9598. +
  9599. + err = npositive = lkup_dentry(dentry, dbstart(parent), /*type*/0);
  9600. + //err = -1;
  9601. + ret = ERR_PTR(err);
  9602. + if (unlikely(err < 0))
  9603. + goto out_unlock;
  9604. + inode = NULL;
  9605. + if (npositive) {
  9606. + inode = au_new_inode(dentry);
  9607. + ret = (void*)inode;
  9608. + }
  9609. + if (!IS_ERR(inode)) {
  9610. +#if 1
  9611. + /* d_splice_alias() also supports d_add() */
  9612. + ret = d_splice_alias(inode, dentry);
  9613. + if (unlikely(IS_ERR(ret) && inode))
  9614. + ii_write_unlock(inode);
  9615. +#else
  9616. + d_add(dentry, inode);
  9617. +#endif
  9618. + }
  9619. +
  9620. + out_unlock:
  9621. + di_write_unlock(dentry);
  9622. + out:
  9623. + aufs_read_unlock(parent, !AUFS_I_RLOCK);
  9624. + TraceErrPtr(ret);
  9625. + return ret;
  9626. +}
  9627. +
  9628. +/* ---------------------------------------------------------------------- */
  9629. +
  9630. +/*
  9631. + * decide the branch and the parent dir where we will create a new entry.
  9632. + * returns new bindex or an error.
  9633. + * copyup the parent dir if needed.
  9634. + */
  9635. +int wr_dir(struct dentry *dentry, int add_entry, struct dentry *src_dentry,
  9636. + aufs_bindex_t force_btgt, int do_lock_srcdir)
  9637. +{
  9638. + int err;
  9639. + aufs_bindex_t bcpup, bstart, src_bstart;
  9640. + struct dentry *hidden_parent;
  9641. + struct super_block *sb;
  9642. + struct dentry *parent, *src_parent = NULL;
  9643. + struct inode *dir, *src_dir = NULL;
  9644. +
  9645. + LKTRTrace("%.*s, add %d, src %p, force %d, lock_srcdir %d\n",
  9646. + DLNPair(dentry), add_entry, src_dentry, force_btgt,
  9647. + do_lock_srcdir);
  9648. +
  9649. + sb = dentry->d_sb;
  9650. + parent = dentry->d_parent; // dget_parent()
  9651. + bcpup = bstart = dbstart(dentry);
  9652. + if (force_btgt < 0) {
  9653. + if (src_dentry) {
  9654. + src_bstart = dbstart(src_dentry);
  9655. + if (src_bstart < bstart)
  9656. + bcpup = src_bstart;
  9657. + }
  9658. + if (test_ro(sb, bcpup, dentry->d_inode)) {
  9659. + if (!add_entry)
  9660. + di_read_lock_parent(parent, !AUFS_I_RLOCK);
  9661. + bcpup = err = find_rw_parent_br(dentry, bcpup);
  9662. + //bcpup = err = find_rw_br(sb, bcpup);
  9663. + if (!add_entry)
  9664. + di_read_unlock(parent, !AUFS_I_RLOCK);
  9665. + //err = -1;
  9666. + if (unlikely(err < 0))
  9667. + goto out;
  9668. + }
  9669. + } else {
  9670. + DEBUG_ON(bstart <= force_btgt
  9671. + || test_ro(sb, force_btgt, dentry->d_inode));
  9672. + bcpup = force_btgt;
  9673. + }
  9674. + LKTRTrace("bstart %d, bcpup %d\n", bstart, bcpup);
  9675. +
  9676. + err = bcpup;
  9677. + if (bcpup == bstart)
  9678. + goto out; /* success */
  9679. +
  9680. + /* copyup the new parent into the branch we process */
  9681. + hidden_parent = au_h_dptr(dentry)->d_parent; // dget_parent()
  9682. + if (src_dentry) {
  9683. + src_parent = src_dentry->d_parent; // dget_parent()
  9684. + src_dir = src_parent->d_inode;
  9685. + if (do_lock_srcdir)
  9686. + di_write_lock_parent2(src_parent);
  9687. + }
  9688. +
  9689. + dir = parent->d_inode;
  9690. + if (add_entry) {
  9691. + au_update_dbstart(dentry);
  9692. + IMustLock(dir);
  9693. + DiMustWriteLock(parent);
  9694. + IiMustWriteLock(dir);
  9695. + } else
  9696. + di_write_lock_parent(parent);
  9697. +
  9698. + err = 0;
  9699. + if (!au_h_dptr_i(parent, bcpup))
  9700. + err = cpup_dirs(dentry, bcpup, src_parent);
  9701. + //err = -1;
  9702. + if (!err && add_entry) {
  9703. + hidden_parent = au_h_dptr_i(parent, bcpup);
  9704. + DEBUG_ON(!hidden_parent || !hidden_parent->d_inode);
  9705. + hi_lock_parent(hidden_parent->d_inode);
  9706. + err = lkup_neg(dentry, bcpup);
  9707. + //err = -1;
  9708. + i_unlock(hidden_parent->d_inode);
  9709. + }
  9710. +
  9711. + if (!add_entry)
  9712. + di_write_unlock(parent);
  9713. + if (do_lock_srcdir)
  9714. + di_write_unlock(src_parent);
  9715. + if (!err)
  9716. + err = bcpup; /* success */
  9717. + //err = -EPERM;
  9718. + out:
  9719. + TraceErr(err);
  9720. + return err;
  9721. +}
  9722. +
  9723. +/* ---------------------------------------------------------------------- */
  9724. +
  9725. +static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
  9726. +{
  9727. + int err, isdir;
  9728. + aufs_bindex_t bstart, bcpup;
  9729. + struct inode *hidden_inode, *inode, *dir, *h_dir, *gh_dir, *gdir;
  9730. + struct dentry *hidden_dentry, *parent;
  9731. + unsigned int udba;
  9732. +
  9733. + LKTRTrace("%.*s, ia_valid 0x%x\n", DLNPair(dentry), ia->ia_valid);
  9734. + inode = dentry->d_inode;
  9735. + IMustLock(inode);
  9736. +
  9737. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  9738. + bstart = dbstart(dentry);
  9739. + bcpup = err = wr_dir(dentry, /*add*/0, /*src_dentry*/NULL,
  9740. + /*force_btgt*/-1, /*do_lock_srcdir*/0);
  9741. + //err = -1;
  9742. + if (unlikely(err < 0))
  9743. + goto out;
  9744. +
  9745. + /* crazy udba locks */
  9746. + udba = au_flag_test(dentry->d_sb, AuFlag_UDBA_INOTIFY);
  9747. + parent = NULL;
  9748. + gdir = gh_dir = dir = h_dir = NULL;
  9749. + if ((udba || bstart != bcpup) && !IS_ROOT(dentry)) {
  9750. + parent = dentry->d_parent; // dget_parent()
  9751. + dir = parent->d_inode;
  9752. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  9753. + h_dir = au_h_iptr_i(dir, bcpup);
  9754. + }
  9755. + if (parent) {
  9756. + if (unlikely(udba && !IS_ROOT(parent))) {
  9757. + gdir = parent->d_parent->d_inode; // dget_parent()
  9758. + ii_read_lock_parent2(gdir);
  9759. + gh_dir = au_h_iptr_i(gdir, bcpup);
  9760. + hgdir_lock(gh_dir, gdir, bcpup);
  9761. + }
  9762. + hdir_lock(h_dir, dir, bcpup);
  9763. + }
  9764. +
  9765. + isdir = S_ISDIR(inode->i_mode);
  9766. + hidden_dentry = au_h_dptr(dentry);
  9767. + hidden_inode = hidden_dentry->d_inode;
  9768. + DEBUG_ON(!hidden_inode);
  9769. +
  9770. +#define HiLock(bindex) do {\
  9771. + if (!isdir) \
  9772. + hi_lock_child(hidden_inode); \
  9773. + else \
  9774. + hdir2_lock(hidden_inode, inode, bindex); \
  9775. + } while (0)
  9776. +#define HiUnlock(bindex) do {\
  9777. + if (!isdir) \
  9778. + i_unlock(hidden_inode); \
  9779. + else \
  9780. + hdir_unlock(hidden_inode, inode, bindex); \
  9781. + } while (0)
  9782. +
  9783. + if (bstart != bcpup) {
  9784. + loff_t size = -1;
  9785. +
  9786. + if ((ia->ia_valid & ATTR_SIZE)
  9787. + && ia->ia_size < i_size_read(inode)) {
  9788. + size = ia->ia_size;
  9789. + ia->ia_valid &= ~ATTR_SIZE;
  9790. + }
  9791. + HiLock(bstart);
  9792. + err = sio_cpup_simple(dentry, bcpup, size,
  9793. + au_flags_cpup(CPUP_DTIME, parent));
  9794. + //err = -1;
  9795. + HiUnlock(bstart);
  9796. + if (unlikely(err || !ia->ia_valid))
  9797. + goto out_unlock;
  9798. +
  9799. + hidden_dentry = au_h_dptr(dentry);
  9800. + hidden_inode = hidden_dentry->d_inode;
  9801. + DEBUG_ON(!hidden_inode);
  9802. + }
  9803. +
  9804. + HiLock(bcpup);
  9805. + err = vfsub_notify_change(hidden_dentry, ia, need_dlgt(dentry->d_sb));
  9806. + //err = -1;
  9807. + if (!err)
  9808. + au_cpup_attr_changable(inode);
  9809. + HiUnlock(bcpup);
  9810. +#undef HiLock
  9811. +#undef HiUnlock
  9812. +
  9813. + out_unlock:
  9814. + if (parent) {
  9815. + hdir_unlock(h_dir, dir, bcpup);
  9816. + di_read_unlock(parent, AUFS_I_RLOCK);
  9817. + }
  9818. + if (unlikely(gdir)) {
  9819. + hdir_unlock(gh_dir, gdir, bcpup);
  9820. + ii_read_unlock(gdir);
  9821. + }
  9822. + out:
  9823. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  9824. + TraceErr(err);
  9825. + return err;
  9826. +}
  9827. +
  9828. +/* ---------------------------------------------------------------------- */
  9829. +
  9830. +static int hidden_readlink(struct dentry *dentry, int bindex,
  9831. + char __user * buf, int bufsiz)
  9832. +{
  9833. + struct super_block *sb;
  9834. + struct dentry *hidden_dentry;
  9835. +
  9836. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  9837. + if (unlikely(!hidden_dentry->d_inode->i_op
  9838. + || !hidden_dentry->d_inode->i_op->readlink))
  9839. + return -EINVAL;
  9840. +
  9841. + sb = dentry->d_sb;
  9842. + if (!test_ro(sb, bindex, dentry->d_inode)) {
  9843. + touch_atime(sbr_mnt(sb, bindex), hidden_dentry);
  9844. + dentry->d_inode->i_atime = hidden_dentry->d_inode->i_atime;
  9845. + }
  9846. + return hidden_dentry->d_inode->i_op->readlink
  9847. + (hidden_dentry, buf, bufsiz);
  9848. +}
  9849. +
  9850. +static int aufs_readlink(struct dentry *dentry, char __user * buf, int bufsiz)
  9851. +{
  9852. + int err;
  9853. +
  9854. + LKTRTrace("%.*s, %d\n", DLNPair(dentry), bufsiz);
  9855. +
  9856. + aufs_read_lock(dentry, AUFS_I_RLOCK);
  9857. + err = hidden_readlink(dentry, dbstart(dentry), buf, bufsiz);
  9858. + //err = -1;
  9859. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  9860. + TraceErr(err);
  9861. + return err;
  9862. +}
  9863. +
  9864. +static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
  9865. +{
  9866. + int err;
  9867. + char *buf;
  9868. + mm_segment_t old_fs;
  9869. +
  9870. + LKTRTrace("%.*s, nd %.*s\n", DLNPair(dentry), DLNPair(nd->dentry));
  9871. +
  9872. + err = -ENOMEM;
  9873. + buf = __getname();
  9874. + //buf = NULL;
  9875. + if (unlikely(!buf))
  9876. + goto out;
  9877. +
  9878. + aufs_read_lock(dentry, AUFS_I_RLOCK);
  9879. + old_fs = get_fs();
  9880. + set_fs(KERNEL_DS);
  9881. + err = hidden_readlink(dentry, dbstart(dentry), (char __user *)buf,
  9882. + PATH_MAX);
  9883. + //err = -1;
  9884. + set_fs(old_fs);
  9885. + aufs_read_unlock(dentry, AUFS_I_RLOCK);
  9886. +
  9887. + if (err >= 0) {
  9888. + buf[err] = 0;
  9889. + /* will be freed by put_link */
  9890. + nd_set_link(nd, buf);
  9891. + return NULL; /* success */
  9892. + }
  9893. + __putname(buf);
  9894. +
  9895. + out:
  9896. + path_release(nd);
  9897. + TraceErr(err);
  9898. + return ERR_PTR(err);
  9899. +}
  9900. +
  9901. +static void aufs_put_link(struct dentry *dentry, struct nameidata *nd,
  9902. + void *cookie)
  9903. +{
  9904. + LKTRTrace("%.*s\n", DLNPair(dentry));
  9905. + __putname(nd_get_link(nd));
  9906. +}
  9907. +
  9908. +/* ---------------------------------------------------------------------- */
  9909. +#if 0 // comment
  9910. +struct inode_operations {
  9911. + int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
  9912. + struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
  9913. + int (*link) (struct dentry *,struct inode *,struct dentry *);
  9914. + int (*unlink) (struct inode *,struct dentry *);
  9915. + int (*symlink) (struct inode *,struct dentry *,const char *);
  9916. + int (*mkdir) (struct inode *,struct dentry *,int);
  9917. + int (*rmdir) (struct inode *,struct dentry *);
  9918. + int (*mknod) (struct inode *,struct dentry *,int,dev_t);
  9919. + int (*rename) (struct inode *, struct dentry *,
  9920. + struct inode *, struct dentry *);
  9921. + int (*readlink) (struct dentry *, char __user *,int);
  9922. + void * (*follow_link) (struct dentry *, struct nameidata *);
  9923. + void (*put_link) (struct dentry *, struct nameidata *, void *);
  9924. + void (*truncate) (struct inode *);
  9925. + int (*permission) (struct inode *, int, struct nameidata *);
  9926. + int (*setattr) (struct dentry *, struct iattr *);
  9927. + int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
  9928. + int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
  9929. + ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
  9930. + ssize_t (*listxattr) (struct dentry *, char *, size_t);
  9931. + int (*removexattr) (struct dentry *, const char *);
  9932. + void (*truncate_range)(struct inode *, loff_t, loff_t);
  9933. +};
  9934. +#endif
  9935. +
  9936. +struct inode_operations aufs_symlink_iop = {
  9937. + .permission = aufs_permission,
  9938. + .setattr = aufs_setattr,
  9939. +
  9940. + .readlink = aufs_readlink,
  9941. + .follow_link = aufs_follow_link,
  9942. + .put_link = aufs_put_link
  9943. +};
  9944. +
  9945. +//i_op_add.c
  9946. +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
  9947. +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
  9948. +int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
  9949. + struct nameidata *nd);
  9950. +int aufs_link(struct dentry *src_dentry, struct inode *dir,
  9951. + struct dentry *dentry);
  9952. +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
  9953. +
  9954. +//i_op_del.c
  9955. +int aufs_unlink(struct inode *dir, struct dentry *dentry);
  9956. +int aufs_rmdir(struct inode *dir, struct dentry *dentry);
  9957. +
  9958. +// i_op_ren.c
  9959. +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
  9960. + struct inode *dir, struct dentry *dentry);
  9961. +
  9962. +struct inode_operations aufs_dir_iop = {
  9963. + .create = aufs_create,
  9964. + .lookup = aufs_lookup,
  9965. + .link = aufs_link,
  9966. + .unlink = aufs_unlink,
  9967. + .symlink = aufs_symlink,
  9968. + .mkdir = aufs_mkdir,
  9969. + .rmdir = aufs_rmdir,
  9970. + .mknod = aufs_mknod,
  9971. + .rename = aufs_rename,
  9972. +
  9973. + .permission = aufs_permission,
  9974. + .setattr = aufs_setattr,
  9975. +
  9976. +#if 0 // xattr
  9977. + .setxattr = aufs_setxattr,
  9978. + .getxattr = aufs_getxattr,
  9979. + .listxattr = aufs_listxattr,
  9980. + .removexattr = aufs_removexattr
  9981. +#endif
  9982. +};
  9983. +
  9984. +struct inode_operations aufs_iop = {
  9985. + .permission = aufs_permission,
  9986. + .setattr = aufs_setattr,
  9987. +
  9988. +#if 0 // xattr
  9989. + .setxattr = aufs_setxattr,
  9990. + .getxattr = aufs_getxattr,
  9991. + .listxattr = aufs_listxattr,
  9992. + .removexattr = aufs_removexattr
  9993. +#endif
  9994. +};
  9995. diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
  9996. new file mode 100755
  9997. index 0000000..977d773
  9998. --- /dev/null
  9999. +++ b/fs/aufs/i_op_add.c
  10000. @@ -0,0 +1,621 @@
  10001. +/*
  10002. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  10003. + *
  10004. + * This program, aufs is free software; you can redistribute it and/or modify
  10005. + * it under the terms of the GNU General Public License as published by
  10006. + * the Free Software Foundation; either version 2 of the License, or
  10007. + * (at your option) any later version.
  10008. + *
  10009. + * This program is distributed in the hope that it will be useful,
  10010. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10011. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10012. + * GNU General Public License for more details.
  10013. + *
  10014. + * You should have received a copy of the GNU General Public License
  10015. + * along with this program; if not, write to the Free Software
  10016. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  10017. + */
  10018. +
  10019. +/* $Id: i_op_add.c,v 1.37 2007/05/07 03:46:08 sfjro Exp $ */
  10020. +
  10021. +//#include <linux/fs.h>
  10022. +//#include <linux/namei.h>
  10023. +#include "aufs.h"
  10024. +
  10025. +/*
  10026. + * final procedure of adding a new entry, except link(2).
  10027. + * remove whiteout, instantiate, copyup the parent dir's times and size
  10028. + * and update version.
  10029. + * if it failed, re-create the removed whiteout.
  10030. + */
  10031. +static int epilog(struct dentry *wh_dentry, struct dentry *dentry)
  10032. +{
  10033. + int err, rerr;
  10034. + aufs_bindex_t bwh;
  10035. + struct inode *inode, *dir;
  10036. + struct dentry *wh;
  10037. + struct lkup_args lkup;
  10038. +
  10039. + LKTRTrace("wh %p, %.*s\n", wh_dentry, DLNPair(dentry));
  10040. +
  10041. + lkup.dlgt = need_dlgt(dentry->d_sb);
  10042. + bwh = -1;
  10043. + if (wh_dentry) {
  10044. + bwh = dbwh(dentry);
  10045. + err = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode,
  10046. + wh_dentry, dentry, lkup.dlgt);
  10047. + //err = -1;
  10048. + if (unlikely(err))
  10049. + goto out;
  10050. + }
  10051. +
  10052. + inode = au_new_inode(dentry);
  10053. + //inode = ERR_PTR(-1);
  10054. + if (!IS_ERR(inode)) {
  10055. + d_instantiate(dentry, inode);
  10056. + dir = dentry->d_parent->d_inode;
  10057. + /* or always cpup dir mtime? */
  10058. + if (ibstart(dir) == dbstart(dentry))
  10059. + au_cpup_attr_timesizes(dir);
  10060. + dir->i_version++;
  10061. + return 0; /* success */
  10062. + }
  10063. +
  10064. + err = PTR_ERR(inode);
  10065. + if (!wh_dentry)
  10066. + goto out;
  10067. +
  10068. + /* revert */
  10069. + lkup.nfsmnt = au_nfsmnt(dentry->d_sb, bwh);
  10070. + wh = simple_create_wh(dentry, bwh, wh_dentry->d_parent, &lkup);
  10071. + //wh = ERR_PTR(-1);
  10072. + rerr = PTR_ERR(wh);
  10073. + if (!IS_ERR(wh)) {
  10074. + dput(wh);
  10075. + goto out;
  10076. + }
  10077. + IOErr("%.*s reverting whiteout failed(%d, %d)\n",
  10078. + DLNPair(dentry), err, rerr);
  10079. + err = -EIO;
  10080. +
  10081. + out:
  10082. + TraceErr(err);
  10083. + return err;
  10084. +}
  10085. +
  10086. +/*
  10087. + * initial procedure of adding a new entry.
  10088. + * prepare writable branch and the parent dir, lock it,
  10089. + * lookup whiteout for the new entry.
  10090. + */
  10091. +static struct dentry *
  10092. +lock_hdir_lkup_wh(struct dentry *dentry, struct dtime *dt,
  10093. + struct dentry *src_dentry, int do_lock_srcdir)
  10094. +{
  10095. + struct dentry *wh_dentry, *parent, *hidden_parent;
  10096. + int err;
  10097. + aufs_bindex_t bstart, bcpup;
  10098. + struct inode *dir, *h_dir;
  10099. + struct lkup_args lkup;
  10100. +
  10101. + LKTRTrace("%.*s, src %p\n", DLNPair(dentry), src_dentry);
  10102. +
  10103. + parent = dentry->d_parent;
  10104. + bstart = dbstart(dentry);
  10105. + bcpup = err = wr_dir(dentry, 1, src_dentry, -1, do_lock_srcdir);
  10106. + //err = -1;
  10107. + wh_dentry = ERR_PTR(err);
  10108. + if (unlikely(err < 0))
  10109. + goto out;
  10110. +
  10111. + dir = parent->d_inode;
  10112. + hidden_parent = au_h_dptr_i(parent, bcpup);
  10113. + h_dir = hidden_parent->d_inode;
  10114. + hdir_lock(h_dir, dir, bcpup);
  10115. + if (dt)
  10116. + dtime_store(dt, parent, hidden_parent);
  10117. + if (/* bcpup != bstart || */ bcpup != dbwh(dentry))
  10118. + return NULL; /* success */
  10119. +
  10120. + lkup.nfsmnt = au_nfsmnt(parent->d_sb, bcpup);
  10121. + lkup.dlgt = need_dlgt(parent->d_sb);
  10122. + wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, &lkup);
  10123. + //wh_dentry = ERR_PTR(-1);
  10124. + if (IS_ERR(wh_dentry))
  10125. + hdir_unlock(h_dir, dir, bcpup);
  10126. +
  10127. + out:
  10128. + TraceErrPtr(wh_dentry);
  10129. + return wh_dentry;
  10130. +}
  10131. +
  10132. +/* ---------------------------------------------------------------------- */
  10133. +
  10134. +enum {Mknod, Symlink, Creat};
  10135. +struct simple_arg {
  10136. + int type;
  10137. + union {
  10138. + struct {
  10139. + int mode;
  10140. + struct nameidata *nd;
  10141. + } c;
  10142. + struct {
  10143. + const char *symname;
  10144. + } s;
  10145. + struct {
  10146. + int mode;
  10147. + dev_t dev;
  10148. + } m;
  10149. + } u;
  10150. +};
  10151. +
  10152. +static int add_simple(struct inode *dir, struct dentry *dentry,
  10153. + struct simple_arg *arg)
  10154. +{
  10155. + int err, dlgt;
  10156. + struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent;
  10157. + struct inode *hidden_dir;
  10158. + struct dtime dt;
  10159. +
  10160. + LKTRTrace("type %d, %.*s\n", arg->type, DLNPair(dentry));
  10161. + IMustLock(dir);
  10162. +
  10163. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10164. + parent = dentry->d_parent;
  10165. + di_write_lock_parent(parent);
  10166. + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
  10167. + /*do_lock_srcdir*/0);
  10168. + //wh_dentry = ERR_PTR(-1);
  10169. + err = PTR_ERR(wh_dentry);
  10170. + if (IS_ERR(wh_dentry))
  10171. + goto out;
  10172. +
  10173. + hidden_dentry = au_h_dptr(dentry);
  10174. + hidden_parent = hidden_dentry->d_parent;
  10175. + hidden_dir = hidden_parent->d_inode;
  10176. + IMustLock(hidden_dir);
  10177. + dlgt = need_dlgt(dir->i_sb);
  10178. +
  10179. +#if 1 // partial testing
  10180. + switch (arg->type) {
  10181. + case Creat:
  10182. +#if 0
  10183. + if (arg->u.c.nd) {
  10184. + struct nameidata fake_nd;
  10185. + fake_nd = *arg->u.c.nd;
  10186. + fake_nd.dentry = dget(hidden_parent);
  10187. + fake_nd.mnt = sbr_mnt(dentry->d_sb, dbstart(dentry));
  10188. + mntget(fake_nd.mnt);
  10189. + err = vfsub_create(hidden_dir, hidden_dentry,
  10190. + arg->u.c.mode, &fake_nd, dlgt);
  10191. + path_release(&fake_nd);
  10192. + } else
  10193. +#endif
  10194. + err = vfsub_create(hidden_dir, hidden_dentry,
  10195. + arg->u.c.mode, NULL, dlgt);
  10196. + break;
  10197. + case Symlink:
  10198. + err = vfsub_symlink(hidden_dir, hidden_dentry,
  10199. + arg->u.s.symname, S_IALLUGO, dlgt);
  10200. + break;
  10201. + case Mknod:
  10202. + err = vfsub_mknod(hidden_dir, hidden_dentry,
  10203. + arg->u.m.mode, arg->u.m.dev, dlgt);
  10204. + break;
  10205. + default:
  10206. + BUG();
  10207. + }
  10208. +#else
  10209. + err = -1;
  10210. +#endif
  10211. + if (!err)
  10212. + err = epilog(wh_dentry, dentry);
  10213. + //err = -1;
  10214. +
  10215. + /* revert */
  10216. + if (unlikely(err && hidden_dentry->d_inode)) {
  10217. + int rerr;
  10218. + rerr = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
  10219. + //rerr = -1;
  10220. + if (rerr) {
  10221. + IOErr("%.*s revert failure(%d, %d)\n",
  10222. + DLNPair(dentry), err, rerr);
  10223. + err = -EIO;
  10224. + }
  10225. + dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
  10226. + d_drop(dentry);
  10227. + }
  10228. +
  10229. + hdir_unlock(hidden_dir, dir, dbstart(dentry));
  10230. + dput(wh_dentry);
  10231. +
  10232. + out:
  10233. + if (unlikely(err)) {
  10234. + au_update_dbstart(dentry);
  10235. + d_drop(dentry);
  10236. + }
  10237. + di_write_unlock(parent);
  10238. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  10239. + TraceErr(err);
  10240. + return err;
  10241. +}
  10242. +
  10243. +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
  10244. +{
  10245. + struct simple_arg arg = {
  10246. + .type = Mknod,
  10247. + .u.m = {.mode = mode, .dev = dev}
  10248. + };
  10249. + return add_simple(dir, dentry, &arg);
  10250. +}
  10251. +
  10252. +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
  10253. +{
  10254. + struct simple_arg arg = {
  10255. + .type = Symlink,
  10256. + .u.s.symname = symname
  10257. + };
  10258. + return add_simple(dir, dentry, &arg);
  10259. +}
  10260. +
  10261. +int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
  10262. + struct nameidata *nd)
  10263. +{
  10264. + struct simple_arg arg = {
  10265. + .type = Creat,
  10266. + .u.c = {.mode = mode, .nd = nd}
  10267. + };
  10268. + return add_simple(dir, dentry, &arg);
  10269. +}
  10270. +
  10271. +/* ---------------------------------------------------------------------- */
  10272. +
  10273. +struct link_arg {
  10274. + aufs_bindex_t bdst, bsrc;
  10275. + int issamedir, dlgt;
  10276. + struct dentry *src_parent, *parent, *hidden_dentry;
  10277. + struct inode *hidden_dir, *inode;
  10278. +};
  10279. +
  10280. +static int cpup_before_link(struct dentry *src_dentry, struct inode *dir,
  10281. + struct link_arg *a)
  10282. +{
  10283. + int err;
  10284. + unsigned int flags;
  10285. + struct inode *hi, *hdir = NULL, *src_dir;
  10286. +
  10287. + TraceEnter();
  10288. +
  10289. + err = 0;
  10290. + flags = au_flags_cpup(CPUP_DTIME, a->parent);
  10291. + src_dir = a->src_parent->d_inode;
  10292. + if (!a->issamedir) {
  10293. + // todo: dead lock?
  10294. + di_read_lock_parent2(a->src_parent, AUFS_I_RLOCK);
  10295. + // this temporary unlock/lock is safe
  10296. + hdir_unlock(a->hidden_dir, dir, a->bdst);
  10297. + err = test_and_cpup_dirs(src_dentry, a->bdst, a->parent);
  10298. + //err = -1;
  10299. + if (!err) {
  10300. + hdir = au_h_iptr_i(src_dir, a->bdst);
  10301. + hdir_lock(hdir, src_dir, a->bdst);
  10302. + flags = au_flags_cpup(CPUP_DTIME, a->src_parent);
  10303. + }
  10304. + }
  10305. +
  10306. + if (!err) {
  10307. + hi = au_h_dptr(src_dentry)->d_inode;
  10308. + hi_lock_child(hi);
  10309. + err = sio_cpup_simple(src_dentry, a->bdst, -1, flags);
  10310. + //err = -1;
  10311. + i_unlock(hi);
  10312. + }
  10313. +
  10314. + if (!a->issamedir) {
  10315. + if (hdir)
  10316. + hdir_unlock(hdir, src_dir, a->bdst);
  10317. + hdir_lock(a->hidden_dir, dir, a->bdst);
  10318. + di_read_unlock(a->src_parent, AUFS_I_RLOCK);
  10319. + }
  10320. +
  10321. + TraceErr(err);
  10322. + return err;
  10323. +}
  10324. +
  10325. +static int cpup_or_link(struct dentry *src_dentry, struct link_arg *a)
  10326. +{
  10327. + int err;
  10328. + struct inode *inode, *h_inode, *h_dst_inode;
  10329. + struct dentry *h_dentry;
  10330. + aufs_bindex_t bstart;
  10331. + struct super_block *sb;
  10332. +
  10333. + TraceEnter();
  10334. +
  10335. + sb = src_dentry->d_sb;
  10336. + inode = src_dentry->d_inode;
  10337. + h_dentry = au_h_dptr(src_dentry);
  10338. + h_inode = h_dentry->d_inode;
  10339. + bstart = ibstart(inode);
  10340. + h_dst_inode = NULL;
  10341. + if (bstart <= a->bdst)
  10342. + h_dst_inode = au_h_iptr_i(inode, a->bdst);
  10343. +
  10344. + if (!h_dst_inode) {
  10345. + /* copyup src_dentry as the name of dentry. */
  10346. + set_dbstart(src_dentry, a->bdst);
  10347. + set_h_dptr(src_dentry, a->bdst, dget(a->hidden_dentry));
  10348. + hi_lock_child(h_inode);
  10349. + err = sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
  10350. + au_flags_cpup(!CPUP_DTIME, a->parent));
  10351. + //err = -1;
  10352. + i_unlock(h_inode);
  10353. + set_h_dptr(src_dentry, a->bdst, NULL);
  10354. + set_dbstart(src_dentry, a->bsrc);
  10355. + } else {
  10356. + /* the inode of src_dentry already exists on a.bdst branch */
  10357. + h_dentry = d_find_alias(h_dst_inode);
  10358. + if (h_dentry) {
  10359. + err = vfsub_link(h_dentry, a->hidden_dir,
  10360. + a->hidden_dentry, a->dlgt);
  10361. + dput(h_dentry);
  10362. + } else {
  10363. + IOErr("no dentry found for i%lu on b%d\n",
  10364. + h_dst_inode->i_ino, a->bdst);
  10365. + err = -EIO;
  10366. + }
  10367. + }
  10368. +
  10369. + if (!err)
  10370. + append_plink(sb, a->inode, a->hidden_dentry, a->bdst);
  10371. +
  10372. + TraceErr(err);
  10373. + return err;
  10374. +}
  10375. +
  10376. +int aufs_link(struct dentry *src_dentry, struct inode *dir,
  10377. + struct dentry *dentry)
  10378. +{
  10379. + int err, rerr;
  10380. + struct dentry *hidden_parent, *wh_dentry, *hidden_src_dentry;
  10381. + struct dtime dt;
  10382. + struct link_arg a;
  10383. + struct super_block *sb;
  10384. +
  10385. + LKTRTrace("src %.*s, i%lu, dst %.*s\n",
  10386. + DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
  10387. + IMustLock(dir);
  10388. + IMustLock(src_dentry->d_inode);
  10389. +
  10390. + aufs_read_and_write_lock2(dentry, src_dentry, /*isdir*/0);
  10391. + a.src_parent = src_dentry->d_parent;
  10392. + a.parent = dentry->d_parent;
  10393. + a.issamedir = (a.src_parent == a.parent);
  10394. + di_write_lock_parent(a.parent);
  10395. + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, !a.issamedir);
  10396. + //wh_dentry = ERR_PTR(-1);
  10397. + err = PTR_ERR(wh_dentry);
  10398. + if (IS_ERR(wh_dentry))
  10399. + goto out;
  10400. +
  10401. + a.inode = src_dentry->d_inode;
  10402. + a.hidden_dentry = au_h_dptr(dentry);
  10403. + hidden_parent = a.hidden_dentry->d_parent;
  10404. + a.hidden_dir = hidden_parent->d_inode;
  10405. + IMustLock(a.hidden_dir);
  10406. +
  10407. + err = 0;
  10408. + sb = dentry->d_sb;
  10409. + a.dlgt = need_dlgt(sb);
  10410. +
  10411. + //todo: minor optimize, their sb may be same while their bindex differs.
  10412. + a.bsrc = dbstart(src_dentry);
  10413. + a.bdst = dbstart(dentry);
  10414. + hidden_src_dentry = au_h_dptr(src_dentry);
  10415. + if (unlikely(!au_flag_test(sb, AuFlag_PLINK))) {
  10416. + /*
  10417. + * copyup src_dentry to the branch we process,
  10418. + * and then link(2) to it.
  10419. + * gave up 'pseudo link by cpup' approach,
  10420. + * since nlink may be one and some applications will not work.
  10421. + */
  10422. + if (a.bdst < a.bsrc
  10423. + /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
  10424. + err = cpup_before_link(src_dentry, dir, &a);
  10425. + if (!err) {
  10426. + hidden_src_dentry = au_h_dptr(src_dentry);
  10427. + err = vfsub_link(hidden_src_dentry, a.hidden_dir,
  10428. + a.hidden_dentry, a.dlgt);
  10429. + //err = -1;
  10430. + }
  10431. + } else {
  10432. + if (a.bdst < a.bsrc
  10433. + /* && hidden_src_dentry->d_sb != a.hidden_dentry->d_sb */)
  10434. + err = cpup_or_link(src_dentry, &a);
  10435. + else {
  10436. + hidden_src_dentry = au_h_dptr(src_dentry);
  10437. + err = vfsub_link(hidden_src_dentry, a.hidden_dir,
  10438. + a.hidden_dentry, a.dlgt);
  10439. + //err = -1;
  10440. + }
  10441. + }
  10442. + if (unlikely(err))
  10443. + goto out_unlock;
  10444. + if (wh_dentry) {
  10445. + err = au_unlink_wh_dentry(a.hidden_dir, wh_dentry, dentry,
  10446. + a.dlgt);
  10447. + //err = -1;
  10448. + if (unlikely(err))
  10449. + goto out_revert;
  10450. + }
  10451. +
  10452. + dir->i_version++;
  10453. + if (ibstart(dir) == dbstart(dentry))
  10454. + au_cpup_attr_timesizes(dir);
  10455. + if (!d_unhashed(a.hidden_dentry)
  10456. + /* || hidden_old_inode->i_nlink <= nlink */
  10457. + /* || SB_NFS(hidden_src_dentry->d_sb) */) {
  10458. + dentry->d_inode = igrab(a.inode);
  10459. + d_instantiate(dentry, a.inode);
  10460. + a.inode->i_nlink++;
  10461. + a.inode->i_ctime = dir->i_ctime;
  10462. + } else
  10463. + /* nfs case (< 2.6.15) */
  10464. + d_drop(dentry);
  10465. +#if 0
  10466. + au_debug_on();
  10467. + DbgInode(a.inode);
  10468. + au_debug_off();
  10469. + {
  10470. + aufs_bindex_t i;
  10471. + for (i = ibstart(a.inode); i <= ibend(a.inode); i++) {
  10472. + struct xino xino;
  10473. + struct inode *hi;
  10474. + hi = au_h_iptr_i(a.inode, i);
  10475. + if (hi) {
  10476. + xino_read(sb, i, hi->i_ino, &xino);
  10477. + Dbg("hi%lu, i%lu\n", hi->i_ino, xino.ino);
  10478. + }
  10479. + }
  10480. + }
  10481. +#endif
  10482. + goto out_unlock; /* success */
  10483. +
  10484. + out_revert:
  10485. +#if 0 // remove
  10486. + if (d_unhashed(a.hidden_dentry)) {
  10487. + /* hardlink on nfs (< 2.6.15) */
  10488. + struct dentry *d;
  10489. + const struct qstr *name = &a.hidden_dentry->d_name;
  10490. + DEBUG_ON(a.hidden_dentry->d_parent->d_inode != a.hidden_dir);
  10491. + // do not superio.
  10492. + d = lkup_one(name->name, a.hidden_dentry->d_parent, name->len,
  10493. + au_nfsmnt(sb, a.bdst)??, need_dlgt(sb));
  10494. + rerr = PTR_ERR(d);
  10495. + if (IS_ERR(d))
  10496. + goto out_rerr;
  10497. + dput(a.hidden_dentry);
  10498. + a.hidden_dentry = d;
  10499. + DEBUG_ON(!d->d_inode);
  10500. + }
  10501. +#endif
  10502. + rerr = vfsub_unlink(a.hidden_dir, a.hidden_dentry, a.dlgt);
  10503. + //rerr = -1;
  10504. + if (!rerr)
  10505. + goto out_dt;
  10506. +// out_rerr:
  10507. + IOErr("%.*s reverting failed(%d, %d)\n", DLNPair(dentry), err, rerr);
  10508. + err = -EIO;
  10509. + out_dt:
  10510. + d_drop(dentry);
  10511. + dtime_revert(&dt, !CPUP_LOCKED_GHDIR);
  10512. + out_unlock:
  10513. + hdir_unlock(a.hidden_dir, dir, a.bdst);
  10514. + dput(wh_dentry);
  10515. + out:
  10516. + if (unlikely(err)) {
  10517. + au_update_dbstart(dentry);
  10518. + d_drop(dentry);
  10519. + }
  10520. + di_write_unlock(a.parent);
  10521. + aufs_read_and_write_unlock2(dentry, src_dentry);
  10522. + TraceErr(err);
  10523. + return err;
  10524. +}
  10525. +
  10526. +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  10527. +{
  10528. + int err, rerr, diropq, dlgt;
  10529. + struct dentry *hidden_dentry, *hidden_parent, *wh_dentry, *parent,
  10530. + *opq_dentry;
  10531. + struct inode *hidden_dir, *hidden_inode;
  10532. + struct dtime dt;
  10533. + aufs_bindex_t bindex;
  10534. + struct super_block *sb;
  10535. +
  10536. + LKTRTrace("i%lu, %.*s, mode 0%o\n", dir->i_ino, DLNPair(dentry), mode);
  10537. + IMustLock(dir);
  10538. +
  10539. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10540. + parent = dentry->d_parent;
  10541. + di_write_lock_parent(parent);
  10542. + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL,
  10543. + /*do_lock_srcdir*/0);
  10544. + //wh_dentry = ERR_PTR(-1);
  10545. + err = PTR_ERR(wh_dentry);
  10546. + if (IS_ERR(wh_dentry))
  10547. + goto out;
  10548. +
  10549. + sb = dentry->d_sb;
  10550. + bindex = dbstart(dentry);
  10551. + hidden_dentry = au_h_dptr(dentry);
  10552. + hidden_parent = hidden_dentry->d_parent;
  10553. + hidden_dir = hidden_parent->d_inode;
  10554. + IMustLock(hidden_dir);
  10555. + dlgt = need_dlgt(sb);
  10556. +
  10557. + err = vfsub_mkdir(hidden_dir, hidden_dentry, mode, dlgt);
  10558. + //err = -1;
  10559. + if (unlikely(err))
  10560. + goto out_unlock;
  10561. + hidden_inode = hidden_dentry->d_inode;
  10562. +
  10563. + /* make the dir opaque */
  10564. + diropq = 0;
  10565. + if (unlikely(wh_dentry || au_flag_test(sb, AuFlag_ALWAYS_DIROPQ))) {
  10566. + hi_lock_child(hidden_inode);
  10567. + opq_dentry = create_diropq(dentry, bindex, dlgt);
  10568. + //opq_dentry = ERR_PTR(-1);
  10569. + i_unlock(hidden_inode);
  10570. + err = PTR_ERR(opq_dentry);
  10571. + if (IS_ERR(opq_dentry))
  10572. + goto out_dir;
  10573. + dput(opq_dentry);
  10574. + diropq = 1;
  10575. + }
  10576. +
  10577. + err = epilog(wh_dentry, dentry);
  10578. + //err = -1;
  10579. + if (!err) {
  10580. + dir->i_nlink++;
  10581. + goto out_unlock; /* success */
  10582. + }
  10583. +
  10584. + /* revert */
  10585. + if (unlikely(diropq)) {
  10586. + LKTRLabel(revert opq);
  10587. + hi_lock_child(hidden_inode);
  10588. + rerr = remove_diropq(dentry, bindex, dlgt);
  10589. + //rerr = -1;
  10590. + i_unlock(hidden_inode);
  10591. + if (rerr) {
  10592. + IOErr("%.*s reverting diropq failed(%d, %d)\n",
  10593. + DLNPair(dentry), err, rerr);
  10594. + err = -EIO;
  10595. + }
  10596. + }
  10597. +
  10598. + out_dir:
  10599. + LKTRLabel(revert dir);
  10600. + rerr = vfsub_rmdir(hidden_dir, hidden_dentry, dlgt);
  10601. + //rerr = -1;
  10602. + if (rerr) {
  10603. + IOErr("%.*s reverting dir failed(%d, %d)\n",
  10604. + DLNPair(dentry), err, rerr);
  10605. + err = -EIO;
  10606. + }
  10607. + d_drop(dentry);
  10608. + dtime_revert(&dt, /*fake flag*/CPUP_LOCKED_GHDIR);
  10609. + out_unlock:
  10610. + hdir_unlock(hidden_dir, dir, bindex);
  10611. + dput(wh_dentry);
  10612. + out:
  10613. + if (unlikely(err)) {
  10614. + au_update_dbstart(dentry);
  10615. + d_drop(dentry);
  10616. + }
  10617. + di_write_unlock(parent);
  10618. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  10619. + TraceErr(err);
  10620. + return err;
  10621. +}
  10622. diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
  10623. new file mode 100755
  10624. index 0000000..f29b204
  10625. --- /dev/null
  10626. +++ b/fs/aufs/i_op_del.c
  10627. @@ -0,0 +1,414 @@
  10628. +/*
  10629. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  10630. + *
  10631. + * This program, aufs is free software; you can redistribute it and/or modify
  10632. + * it under the terms of the GNU General Public License as published by
  10633. + * the Free Software Foundation; either version 2 of the License, or
  10634. + * (at your option) any later version.
  10635. + *
  10636. + * This program is distributed in the hope that it will be useful,
  10637. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10638. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10639. + * GNU General Public License for more details.
  10640. + *
  10641. + * You should have received a copy of the GNU General Public License
  10642. + * along with this program; if not, write to the Free Software
  10643. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  10644. + */
  10645. +
  10646. +/* $Id: i_op_del.c,v 1.35 2007/05/14 03:41:52 sfjro Exp $ */
  10647. +
  10648. +#include "aufs.h"
  10649. +
  10650. +/* returns,
  10651. + * 0: wh is unnecessary
  10652. + * plus: wh is necessary
  10653. + * minus: error
  10654. + */
  10655. +int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
  10656. + struct dentry *locked)
  10657. +{
  10658. + int need_wh, err;
  10659. + aufs_bindex_t bstart;
  10660. + struct dentry *hidden_dentry;
  10661. + struct super_block *sb;
  10662. +
  10663. + LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n",
  10664. + DLNPair(dentry), isdir, *bcpup, locked);
  10665. + sb = dentry->d_sb;
  10666. +
  10667. + bstart = dbstart(dentry);
  10668. + LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
  10669. + hidden_dentry = au_h_dptr(dentry);
  10670. + if (*bcpup < 0) {
  10671. + *bcpup = bstart;
  10672. + if (test_ro(sb, bstart, dentry->d_inode)) {
  10673. + *bcpup = err = find_rw_parent_br(dentry, bstart);
  10674. + //*bcpup = err = find_rw_br(sb, bstart);
  10675. + //err = -1;
  10676. + if (unlikely(err < 0))
  10677. + goto out;
  10678. + }
  10679. + } else {
  10680. + /* braces are added to stop a warning */
  10681. + DEBUG_ON(bstart < *bcpup
  10682. + || test_ro(sb, *bcpup, dentry->d_inode));
  10683. + }
  10684. + LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart);
  10685. +
  10686. + if (*bcpup != bstart) {
  10687. + err = cpup_dirs(dentry, *bcpup, locked);
  10688. + //err = -1;
  10689. + if (unlikely(err))
  10690. + goto out;
  10691. + need_wh = 1;
  10692. + } else {
  10693. + //struct nameidata nd;
  10694. + aufs_bindex_t old_bend, new_bend, bdiropq = -1;
  10695. + old_bend = dbend(dentry);
  10696. + if (isdir) {
  10697. + bdiropq = dbdiropq(dentry);
  10698. + set_dbdiropq(dentry, -1);
  10699. + }
  10700. + err = need_wh = lkup_dentry(dentry, bstart + 1, /*type*/0);
  10701. + //err = -1;
  10702. + if (isdir)
  10703. + set_dbdiropq(dentry, bdiropq);
  10704. + if (unlikely(err < 0))
  10705. + goto out;
  10706. + new_bend = dbend(dentry);
  10707. + if (!need_wh && old_bend != new_bend) {
  10708. + set_h_dptr(dentry, new_bend, NULL);
  10709. + set_dbend(dentry, old_bend);
  10710. +#if 0
  10711. + } else if (!au_h_dptr_i(dentry, new_bend)->d_inode) {
  10712. + LKTRTrace("negative\n");
  10713. + set_h_dptr(dentry, new_bend, NULL);
  10714. + set_dbend(dentry, old_bend);
  10715. + need_wh = 0;
  10716. +#endif
  10717. + }
  10718. + }
  10719. + LKTRTrace("need_wh %d\n", need_wh);
  10720. + err = need_wh;
  10721. +
  10722. + out:
  10723. + TraceErr(err);
  10724. + return err;
  10725. +}
  10726. +
  10727. +static struct dentry *
  10728. +lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
  10729. + struct dtime *dt)
  10730. +{
  10731. + struct dentry *wh_dentry;
  10732. + int err, need_wh;
  10733. + struct dentry *hidden_parent, *parent;
  10734. + struct inode *dir, *h_dir;
  10735. + struct lkup_args lkup;
  10736. +
  10737. + LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir);
  10738. +
  10739. + err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL);
  10740. + //err = -1;
  10741. + wh_dentry = ERR_PTR(err);
  10742. + if (unlikely(err < 0))
  10743. + goto out;
  10744. +
  10745. + parent = dentry->d_parent;
  10746. + dir = parent->d_inode;
  10747. + hidden_parent = au_h_dptr_i(parent, *bcpup);
  10748. + h_dir = hidden_parent->d_inode;
  10749. + hdir_lock(h_dir, dir, *bcpup);
  10750. + dtime_store(dt, parent, hidden_parent);
  10751. + if (!need_wh)
  10752. + return NULL; /* success, no need to create whiteout */
  10753. +
  10754. + lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup);
  10755. + lkup.dlgt = need_dlgt(dentry->d_sb);
  10756. + wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup);
  10757. + //wh_dentry = ERR_PTR(-1);
  10758. + if (!IS_ERR(wh_dentry))
  10759. + goto out; /* success */
  10760. + /* returns with the parent is locked and wh_dentry is DGETed */
  10761. +
  10762. + hdir_unlock(h_dir, dir, *bcpup);
  10763. +
  10764. + out:
  10765. + TraceErrPtr(wh_dentry);
  10766. + return wh_dentry;
  10767. +}
  10768. +
  10769. +static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
  10770. + struct aufs_nhash *whlist, struct inode *dir)
  10771. +{
  10772. + int rmdir_later, err;
  10773. + struct dentry *hidden_dentry;
  10774. +
  10775. + LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
  10776. +
  10777. + err = rename_whtmp(dentry, bindex);
  10778. + //err = -1;
  10779. +#if 0
  10780. + //todo: bug
  10781. + if (unlikely(err)) {
  10782. + au_direval_inc(dentry->d_parent);
  10783. + return err;
  10784. + }
  10785. +#endif
  10786. +
  10787. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  10788. + if (!au_is_nfs(hidden_dentry->d_sb)) {
  10789. + const int dirwh = stosi(dentry->d_sb)->si_dirwh;
  10790. + rmdir_later = (dirwh <= 1);
  10791. + if (!rmdir_later)
  10792. + rmdir_later = is_longer_wh(whlist, bindex, dirwh);
  10793. + if (rmdir_later)
  10794. + return rmdir_later;
  10795. + }
  10796. +
  10797. + err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode);
  10798. + //err = -1;
  10799. + if (unlikely(err)) {
  10800. + IOErr("rmdir %.*s, b%d failed, %d. ignored\n",
  10801. + DLNPair(hidden_dentry), bindex, err);
  10802. + err = 0;
  10803. + }
  10804. + TraceErr(err);
  10805. + return err;
  10806. +}
  10807. +
  10808. +static void epilog(struct inode *dir, struct dentry *dentry,
  10809. + aufs_bindex_t bindex)
  10810. +{
  10811. + d_drop(dentry);
  10812. + dentry->d_inode->i_ctime = dir->i_ctime;
  10813. + if (atomic_read(&dentry->d_count) == 1) {
  10814. + set_h_dptr(dentry, dbstart(dentry), NULL);
  10815. + au_update_dbstart(dentry);
  10816. + }
  10817. + if (ibstart(dir) == bindex)
  10818. + au_cpup_attr_timesizes(dir);
  10819. + dir->i_version++;
  10820. +}
  10821. +
  10822. +static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry,
  10823. + aufs_bindex_t bwh, struct dtime *dt, int dlgt)
  10824. +{
  10825. + int rerr;
  10826. +
  10827. + rerr = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode, wh_dentry,
  10828. + dentry, dlgt);
  10829. + //rerr = -1;
  10830. + if (!rerr) {
  10831. + set_dbwh(dentry, bwh);
  10832. + dtime_revert(dt, !CPUP_LOCKED_GHDIR);
  10833. + return 0;
  10834. + }
  10835. +
  10836. + IOErr("%.*s reverting whiteout failed(%d, %d)\n",
  10837. + DLNPair(dentry), err, rerr);
  10838. + return -EIO;
  10839. +}
  10840. +
  10841. +/* ---------------------------------------------------------------------- */
  10842. +
  10843. +int aufs_unlink(struct inode *dir, struct dentry *dentry)
  10844. +{
  10845. + int err, dlgt;
  10846. + struct inode *inode, *hidden_dir;
  10847. + struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
  10848. + struct dtime dt;
  10849. + aufs_bindex_t bwh, bindex, bstart;
  10850. + struct super_block *sb;
  10851. +
  10852. + LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  10853. + IMustLock(dir);
  10854. + inode = dentry->d_inode;
  10855. + if (unlikely(!inode))
  10856. + return -ENOENT; // possible?
  10857. + IMustLock(inode);
  10858. +
  10859. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10860. + parent = dentry->d_parent;
  10861. + di_write_lock_parent(parent);
  10862. +
  10863. + bstart = dbstart(dentry);
  10864. + bwh = dbwh(dentry);
  10865. + bindex = -1;
  10866. + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt);
  10867. + //wh_dentry = ERR_PTR(-1);
  10868. + err = PTR_ERR(wh_dentry);
  10869. + if (IS_ERR(wh_dentry))
  10870. + goto out;
  10871. +
  10872. + sb = dir->i_sb;
  10873. + dlgt = need_dlgt(sb);
  10874. + hidden_dentry = au_h_dptr(dentry);
  10875. + dget(hidden_dentry);
  10876. + hidden_parent = hidden_dentry->d_parent;
  10877. + hidden_dir = hidden_parent->d_inode;
  10878. +
  10879. + if (bindex == bstart) {
  10880. + err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt);
  10881. + //err = -1;
  10882. + } else {
  10883. + DEBUG_ON(!wh_dentry);
  10884. + hidden_parent = wh_dentry->d_parent;
  10885. + DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
  10886. + hidden_dir = hidden_parent->d_inode;
  10887. + IMustLock(hidden_dir);
  10888. + err = 0;
  10889. + }
  10890. +
  10891. + if (!err) {
  10892. + inode->i_nlink--;
  10893. + epilog(dir, dentry, bindex);
  10894. +#if 0
  10895. + xino_write0(sb, bstart, hidden_dentry->d_inode->i_ino);
  10896. + /* ignore this error */
  10897. +#endif
  10898. + goto out_unlock; /* success */
  10899. + }
  10900. +
  10901. + /* revert */
  10902. + if (wh_dentry) {
  10903. + int rerr;
  10904. + rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt);
  10905. + if (rerr)
  10906. + err = rerr;
  10907. + }
  10908. +
  10909. + out_unlock:
  10910. + hdir_unlock(hidden_dir, dir, bindex);
  10911. + dput(wh_dentry);
  10912. + dput(hidden_dentry);
  10913. + out:
  10914. + di_write_unlock(parent);
  10915. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  10916. + TraceErr(err);
  10917. + return err;
  10918. +}
  10919. +
  10920. +int aufs_rmdir(struct inode *dir, struct dentry *dentry)
  10921. +{
  10922. + int err, rmdir_later;
  10923. + struct inode *inode, *hidden_dir;
  10924. + struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent;
  10925. + struct dtime dt;
  10926. + aufs_bindex_t bwh, bindex, bstart;
  10927. + struct rmdir_whtmp_arg *arg;
  10928. + struct aufs_nhash *whlist;
  10929. + struct super_block *sb;
  10930. +
  10931. + LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  10932. + IMustLock(dir);
  10933. + inode = dentry->d_inode;
  10934. + if (unlikely(!inode))
  10935. + return -ENOENT; // possible?
  10936. + IMustLock(inode);
  10937. +
  10938. + whlist = nhash_new(GFP_KERNEL);
  10939. + err = PTR_ERR(whlist);
  10940. + if (IS_ERR(whlist))
  10941. + goto out;
  10942. +
  10943. + err = -ENOMEM;
  10944. + arg = kmalloc(sizeof(*arg), GFP_KERNEL);
  10945. + //arg = NULL;
  10946. + if (unlikely(!arg))
  10947. + goto out_whlist;
  10948. +
  10949. + aufs_read_lock(dentry, AUFS_D_WLOCK);
  10950. + parent = dentry->d_parent;
  10951. + di_write_lock_parent(parent);
  10952. + err = test_empty(dentry, whlist);
  10953. + //err = -1;
  10954. + if (unlikely(err))
  10955. + goto out_arg;
  10956. +
  10957. + bstart = dbstart(dentry);
  10958. + bwh = dbwh(dentry);
  10959. + bindex = -1;
  10960. + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/ 1, &bindex, &dt);
  10961. + //wh_dentry = ERR_PTR(-1);
  10962. + err = PTR_ERR(wh_dentry);
  10963. + if (IS_ERR(wh_dentry))
  10964. + goto out_arg;
  10965. +
  10966. + hidden_dentry = au_h_dptr(dentry);
  10967. + dget(hidden_dentry);
  10968. + hidden_parent = hidden_dentry->d_parent;
  10969. + hidden_dir = hidden_parent->d_inode;
  10970. +
  10971. + rmdir_later = 0;
  10972. + if (bindex == bstart) {
  10973. + IMustLock(hidden_dir);
  10974. + err = renwh_and_rmdir(dentry, bstart, whlist, dir);
  10975. + //err = -1;
  10976. + if (err > 0) {
  10977. + rmdir_later = err;
  10978. + err = 0;
  10979. + }
  10980. + } else {
  10981. + DEBUG_ON(!wh_dentry);
  10982. + hidden_parent = wh_dentry->d_parent;
  10983. + DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex));
  10984. + hidden_dir = hidden_parent->d_inode;
  10985. + IMustLock(hidden_dir);
  10986. + err = 0;
  10987. + }
  10988. +
  10989. + sb = dentry->d_sb;
  10990. + if (!err) {
  10991. + //aufs_bindex_t bi, bend;
  10992. +
  10993. + au_reset_hinotify(inode, /*flags*/0);
  10994. + inode->i_nlink = 0;
  10995. + set_dbdiropq(dentry, -1);
  10996. + epilog(dir, dentry, bindex);
  10997. +
  10998. + if (rmdir_later) {
  10999. + kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir,
  11000. + inode, arg);
  11001. + arg = NULL;
  11002. + }
  11003. +
  11004. +#if 0
  11005. + bend = dbend(dentry);
  11006. + for (bi = bstart; bi <= bend; bi++) {
  11007. + struct dentry *hd;
  11008. + hd = au_h_dptr_i(dentry, bi);
  11009. + if (hd && hd->d_inode)
  11010. + xino_write0(sb, bi, hd->d_inode->i_ino);
  11011. + /* ignore this error */
  11012. + }
  11013. +#endif
  11014. +
  11015. + goto out_unlock; /* success */
  11016. + }
  11017. +
  11018. + /* revert */
  11019. + LKTRLabel(revert);
  11020. + if (wh_dentry) {
  11021. + int rerr;
  11022. + rerr = do_revert(err, wh_dentry, dentry, bwh, &dt,
  11023. + need_dlgt(sb));
  11024. + if (rerr)
  11025. + err = rerr;
  11026. + }
  11027. +
  11028. + out_unlock:
  11029. + hdir_unlock(hidden_dir, dir, bindex);
  11030. + dput(wh_dentry);
  11031. + dput(hidden_dentry);
  11032. + out_arg:
  11033. + di_write_unlock(parent);
  11034. + aufs_read_unlock(dentry, AUFS_D_WLOCK);
  11035. + kfree(arg);
  11036. + out_whlist:
  11037. + nhash_del(whlist);
  11038. + out:
  11039. + TraceErr(err);
  11040. + return err;
  11041. +}
  11042. diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
  11043. new file mode 100755
  11044. index 0000000..08137f9
  11045. --- /dev/null
  11046. +++ b/fs/aufs/i_op_ren.c
  11047. @@ -0,0 +1,637 @@
  11048. +/*
  11049. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  11050. + *
  11051. + * This program, aufs is free software; you can redistribute it and/or modify
  11052. + * it under the terms of the GNU General Public License as published by
  11053. + * the Free Software Foundation; either version 2 of the License, or
  11054. + * (at your option) any later version.
  11055. + *
  11056. + * This program is distributed in the hope that it will be useful,
  11057. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11058. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11059. + * GNU General Public License for more details.
  11060. + *
  11061. + * You should have received a copy of the GNU General Public License
  11062. + * along with this program; if not, write to the Free Software
  11063. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  11064. + */
  11065. +
  11066. +/* $Id: i_op_ren.c,v 1.39 2007/05/14 03:41:52 sfjro Exp $ */
  11067. +
  11068. +//#include <linux/fs.h>
  11069. +//#include <linux/namei.h>
  11070. +#include "aufs.h"
  11071. +
  11072. +enum {SRC, DST};
  11073. +struct rename_args {
  11074. + struct dentry *hidden_dentry[2], *parent[2], *hidden_parent[2];
  11075. + struct aufs_nhash whlist;
  11076. + aufs_bindex_t btgt, bstart[2];
  11077. + struct super_block *sb;
  11078. +
  11079. + unsigned int isdir:1;
  11080. + unsigned int issamedir:1;
  11081. + unsigned int whsrc:1;
  11082. + unsigned int whdst:1;
  11083. + unsigned int dlgt:1;
  11084. +} __attribute__((aligned(sizeof(long))));
  11085. +
  11086. +static int do_rename(struct inode *src_dir, struct dentry *src_dentry,
  11087. + struct inode *dir, struct dentry *dentry,
  11088. + struct rename_args *a)
  11089. +{
  11090. + int err, need_diropq, bycpup, rerr;
  11091. + struct rmdir_whtmp_arg *tharg;
  11092. + struct dentry *wh_dentry[2], *hidden_dst, *hg_parent;
  11093. + struct inode *hidden_dir[2];
  11094. + aufs_bindex_t bindex, bend;
  11095. + unsigned int flags;
  11096. + struct lkup_args lkup = {.dlgt = a->dlgt};
  11097. +
  11098. + LKTRTrace("%.*s/%.*s, %.*s/%.*s, "
  11099. + "hd{%p, %p}, hp{%p, %p}, wh %p, btgt %d, bstart{%d, %d}, "
  11100. + "flags{%d, %d, %d, %d}\n",
  11101. + DLNPair(a->parent[SRC]), DLNPair(src_dentry),
  11102. + DLNPair(a->parent[DST]), DLNPair(dentry),
  11103. + a->hidden_dentry[SRC], a->hidden_dentry[DST],
  11104. + a->hidden_parent[SRC], a->hidden_parent[DST],
  11105. + &a->whlist, a->btgt,
  11106. + a->bstart[SRC], a->bstart[DST],
  11107. + a->isdir, a->issamedir, a->whsrc, a->whdst);
  11108. + hidden_dir[SRC] = a->hidden_parent[SRC]->d_inode;
  11109. + hidden_dir[DST] = a->hidden_parent[DST]->d_inode;
  11110. + IMustLock(hidden_dir[SRC]);
  11111. + IMustLock(hidden_dir[DST]);
  11112. +
  11113. + /* prepare workqueue arg */
  11114. + hidden_dst = NULL;
  11115. + tharg = NULL;
  11116. + if (a->isdir && a->hidden_dentry[DST]->d_inode) {
  11117. + err = -ENOMEM;
  11118. + tharg = kmalloc(sizeof(*tharg), GFP_KERNEL);
  11119. + //tharg = NULL;
  11120. + if (unlikely(!tharg))
  11121. + goto out;
  11122. + hidden_dst = dget(a->hidden_dentry[DST]);
  11123. + }
  11124. +
  11125. + wh_dentry[SRC] = wh_dentry[DST] = NULL;
  11126. + lkup.nfsmnt = au_nfsmnt(a->sb, a->btgt);
  11127. + /* create whiteout for src_dentry */
  11128. + if (a->whsrc) {
  11129. + wh_dentry[SRC] = simple_create_wh(src_dentry, a->btgt,
  11130. + a->hidden_parent[SRC], &lkup);
  11131. + //wh_dentry[SRC] = ERR_PTR(-1);
  11132. + err = PTR_ERR(wh_dentry[SRC]);
  11133. + if (IS_ERR(wh_dentry[SRC]))
  11134. + goto out_tharg;
  11135. + }
  11136. +
  11137. + /* lookup whiteout for dentry */
  11138. + if (a->whdst) {
  11139. + struct dentry *d;
  11140. + d = lkup_wh(a->hidden_parent[DST], &dentry->d_name, &lkup);
  11141. + //d = ERR_PTR(-1);
  11142. + err = PTR_ERR(d);
  11143. + if (IS_ERR(d))
  11144. + goto out_whsrc;
  11145. + if (!d->d_inode)
  11146. + dput(d);
  11147. + else
  11148. + wh_dentry[DST] = d;
  11149. + }
  11150. +
  11151. + /* rename dentry to tmpwh */
  11152. + if (tharg) {
  11153. + err = rename_whtmp(dentry, a->btgt);
  11154. + //err = -1;
  11155. + if (unlikely(err))
  11156. + goto out_whdst;
  11157. + set_h_dptr(dentry, a->btgt, NULL);
  11158. + err = lkup_neg(dentry, a->btgt);
  11159. + //err = -1;
  11160. + if (unlikely(err))
  11161. + goto out_whtmp;
  11162. + a->hidden_dentry[DST] = au_h_dptr_i(dentry, a->btgt);
  11163. + }
  11164. +
  11165. + /* cpup src */
  11166. + if (a->hidden_dentry[DST]->d_inode && a->bstart[SRC] != a->btgt) {
  11167. + flags = au_flags_cpup(!CPUP_DTIME, a->parent[SRC]);
  11168. + hg_parent = a->hidden_parent[SRC]->d_parent;
  11169. + if (!(flags & CPUP_LOCKED_GHDIR)
  11170. + && hg_parent == a->hidden_parent[DST])
  11171. + flags |= CPUP_LOCKED_GHDIR;
  11172. +
  11173. + hi_lock_child(a->hidden_dentry[SRC]->d_inode);
  11174. + err = sio_cpup_simple(src_dentry, a->btgt, -1, flags);
  11175. + //err = -1; // untested dir
  11176. + i_unlock(a->hidden_dentry[SRC]->d_inode);
  11177. + if (unlikely(err))
  11178. + goto out_whtmp;
  11179. + }
  11180. +
  11181. +#if 0
  11182. + /* clear the target ino in xino */
  11183. + LKTRTrace("dir %d, dst inode %p\n", a->isdir, a->hidden_dentry[DST]->d_inode);
  11184. + if (a->isdir && a->hidden_dentry[DST]->d_inode) {
  11185. + Dbg("here\n");
  11186. + err = xino_write(a->sb, a->btgt,
  11187. + a->hidden_dentry[DST]->d_inode->i_ino, 0);
  11188. + if (unlikely(err))
  11189. + goto out_whtmp;
  11190. + }
  11191. +#endif
  11192. +
  11193. + /* rename by vfs_rename or cpup */
  11194. + need_diropq = a->isdir
  11195. + && (wh_dentry[DST]
  11196. + || dbdiropq(dentry) == a->btgt
  11197. + || au_flag_test(a->sb, AuFlag_ALWAYS_DIROPQ));
  11198. + bycpup = 0;
  11199. + if (dbstart(src_dentry) == a->btgt) {
  11200. + if (need_diropq && dbdiropq(src_dentry) == a->btgt)
  11201. + need_diropq = 0;
  11202. + err = vfsub_rename(hidden_dir[SRC], au_h_dptr(src_dentry),
  11203. + hidden_dir[DST], a->hidden_dentry[DST],
  11204. + a->dlgt);
  11205. + //err = -1;
  11206. + } else {
  11207. + bycpup = 1;
  11208. + flags = au_flags_cpup(!CPUP_DTIME, a->parent[DST]);
  11209. + hg_parent = a->hidden_parent[DST]->d_parent;
  11210. + if (!(flags & CPUP_LOCKED_GHDIR)
  11211. + && hg_parent == a->hidden_parent[SRC])
  11212. + flags |= CPUP_LOCKED_GHDIR;
  11213. +
  11214. + hi_lock_child(a->hidden_dentry[SRC]->d_inode);
  11215. + set_dbstart(src_dentry, a->btgt);
  11216. + set_h_dptr(src_dentry, a->btgt, dget(a->hidden_dentry[DST]));
  11217. + //DbgDentry(src_dentry);
  11218. + //DbgInode(src_dentry->d_inode);
  11219. + err = sio_cpup_single(src_dentry, a->btgt, a->bstart[SRC], -1,
  11220. + flags);
  11221. + //err = -1; // untested dir
  11222. + if (unlikely(err)) {
  11223. + set_h_dptr(src_dentry, a->btgt, NULL);
  11224. + set_dbstart(src_dentry, a->bstart[SRC]);
  11225. + }
  11226. + i_unlock(a->hidden_dentry[SRC]->d_inode);
  11227. + }
  11228. + if (unlikely(err))
  11229. + goto out_whtmp;
  11230. +
  11231. + /* make dir opaque */
  11232. + if (need_diropq) {
  11233. + struct dentry *diropq;
  11234. + struct inode *h_inode;
  11235. +
  11236. + h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
  11237. + hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
  11238. + diropq = create_diropq(src_dentry, a->btgt, a->dlgt);
  11239. + //diropq = ERR_PTR(-1);
  11240. + hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
  11241. + err = PTR_ERR(diropq);
  11242. + if (IS_ERR(diropq))
  11243. + goto out_rename;
  11244. + dput(diropq);
  11245. + }
  11246. +
  11247. + /* remove whiteout for dentry */
  11248. + if (wh_dentry[DST]) {
  11249. + err = au_unlink_wh_dentry(hidden_dir[DST], wh_dentry[DST],
  11250. + dentry, a->dlgt);
  11251. + //err = -1;
  11252. + if (unlikely(err))
  11253. + goto out_diropq;
  11254. + }
  11255. +
  11256. + /* remove whtmp */
  11257. + if (tharg) {
  11258. + if (au_is_nfs(hidden_dst->d_sb)
  11259. + || !is_longer_wh(&a->whlist, a->btgt,
  11260. + stosi(a->sb)->si_dirwh)) {
  11261. + err = rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
  11262. + dentry->d_inode);
  11263. + if (unlikely(err))
  11264. + Warn("failed removing whtmp dir %.*s (%d), "
  11265. + "ignored.\n", DLNPair(hidden_dst), err);
  11266. + } else {
  11267. + kick_rmdir_whtmp(hidden_dst, &a->whlist, a->btgt, dir,
  11268. + dentry->d_inode, tharg);
  11269. + dput(hidden_dst);
  11270. + tharg = NULL;
  11271. + }
  11272. + }
  11273. + err = 0;
  11274. + goto out_success;
  11275. +
  11276. +#define RevertFailure(fmt, args...) do { \
  11277. + IOErrWhck("revert failure: " fmt " (%d, %d)\n", \
  11278. + ##args, err, rerr); \
  11279. + err = -EIO; \
  11280. + } while(0)
  11281. +
  11282. + out_diropq:
  11283. + if (need_diropq) {
  11284. + struct inode *h_inode;
  11285. +
  11286. + h_inode = au_h_dptr_i(src_dentry, a->btgt)->d_inode;
  11287. + // i_lock simplly since inotify is not set to h_inode.
  11288. + hi_lock_parent(h_inode);
  11289. + //hdir_lock(h_inode, src_dentry->d_inode, a->btgt);
  11290. + rerr = remove_diropq(src_dentry, a->btgt, a->dlgt);
  11291. + //rerr = -1;
  11292. + //hdir_unlock(h_inode, src_dentry->d_inode, a->btgt);
  11293. + i_unlock(h_inode);
  11294. + if (rerr)
  11295. + RevertFailure("remove diropq %.*s",
  11296. + DLNPair(src_dentry));
  11297. + }
  11298. + out_rename:
  11299. + if (!bycpup) {
  11300. + struct dentry *d;
  11301. + struct qstr *name = &src_dentry->d_name;
  11302. + d = lkup_one(name->name, a->hidden_parent[SRC], name->len,
  11303. + &lkup);
  11304. + //d = ERR_PTR(-1);
  11305. + rerr = PTR_ERR(d);
  11306. + if (IS_ERR(d)) {
  11307. + RevertFailure("lkup_one %.*s", DLNPair(src_dentry));
  11308. + goto out_whtmp;
  11309. + }
  11310. + DEBUG_ON(d->d_inode);
  11311. + rerr = vfsub_rename
  11312. + (hidden_dir[DST], au_h_dptr_i(src_dentry, a->btgt),
  11313. + hidden_dir[SRC], d, a->dlgt);
  11314. + //rerr = -1;
  11315. + d_drop(d);
  11316. + dput(d);
  11317. + //set_h_dptr(src_dentry, a->btgt, NULL);
  11318. + if (rerr)
  11319. + RevertFailure("rename %.*s", DLNPair(src_dentry));
  11320. + } else {
  11321. + rerr = vfsub_unlink(hidden_dir[DST], a->hidden_dentry[DST],
  11322. + a->dlgt);
  11323. + //rerr = -1;
  11324. + set_h_dptr(src_dentry, a->btgt, NULL);
  11325. + set_dbstart(src_dentry, a->bstart[SRC]);
  11326. + if (rerr)
  11327. + RevertFailure("unlink %.*s",
  11328. + DLNPair(a->hidden_dentry[DST]));
  11329. + }
  11330. + out_whtmp:
  11331. + if (tharg) {
  11332. + struct dentry *d;
  11333. + struct qstr *name = &dentry->d_name;
  11334. + LKTRLabel(here);
  11335. + d = lkup_one(name->name, a->hidden_parent[DST], name->len,
  11336. + &lkup);
  11337. + //d = ERR_PTR(-1);
  11338. + rerr = PTR_ERR(d);
  11339. + if (IS_ERR(d)) {
  11340. + RevertFailure("lookup %.*s", LNPair(name));
  11341. + goto out_whdst;
  11342. + }
  11343. + if (d->d_inode) {
  11344. + d_drop(d);
  11345. + dput(d);
  11346. + goto out_whdst;
  11347. + }
  11348. + DEBUG_ON(d->d_inode);
  11349. + rerr = vfsub_rename(hidden_dir[DST], hidden_dst,
  11350. + hidden_dir[DST], d, a->dlgt);
  11351. + //rerr = -1;
  11352. + d_drop(d);
  11353. + dput(d);
  11354. + if (rerr) {
  11355. + RevertFailure("rename %.*s", DLNPair(hidden_dst));
  11356. + goto out_whdst;
  11357. + }
  11358. + set_h_dptr(dentry, a->btgt, NULL);
  11359. + set_h_dptr(dentry, a->btgt, dget(hidden_dst));
  11360. + }
  11361. + out_whdst:
  11362. + dput(wh_dentry[DST]);
  11363. + wh_dentry[DST] = NULL;
  11364. + out_whsrc:
  11365. + if (wh_dentry[SRC]) {
  11366. + LKTRLabel(here);
  11367. + rerr = au_unlink_wh_dentry(hidden_dir[SRC], wh_dentry[SRC],
  11368. + src_dentry, a->dlgt);
  11369. + //rerr = -1;
  11370. + if (rerr)
  11371. + RevertFailure("unlink %.*s", DLNPair(wh_dentry[SRC]));
  11372. + }
  11373. +#undef RevertFailure
  11374. + d_drop(src_dentry);
  11375. + bend = dbend(src_dentry);
  11376. + for (bindex = dbstart(src_dentry); bindex <= bend; bindex++) {
  11377. + struct dentry *hd;
  11378. + hd = au_h_dptr_i(src_dentry, bindex);
  11379. + if (hd)
  11380. + d_drop(hd);
  11381. + }
  11382. + d_drop(dentry);
  11383. + bend = dbend(dentry);
  11384. + for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
  11385. + struct dentry *hd;
  11386. + hd = au_h_dptr_i(dentry, bindex);
  11387. + if (hd)
  11388. + d_drop(hd);
  11389. + }
  11390. + au_update_dbstart(dentry);
  11391. + if (tharg)
  11392. + d_drop(hidden_dst);
  11393. + out_success:
  11394. + dput(wh_dentry[SRC]);
  11395. + dput(wh_dentry[DST]);
  11396. + out_tharg:
  11397. + if (tharg) {
  11398. + dput(hidden_dst);
  11399. + kfree(tharg);
  11400. + }
  11401. + out:
  11402. + TraceErr(err);
  11403. + return err;
  11404. +}
  11405. +
  11406. +/*
  11407. + * test if @dentry dir can be rename destination or not.
  11408. + * success means, it is a logically empty dir.
  11409. + */
  11410. +static int may_rename_dstdir(struct dentry *dentry, aufs_bindex_t btgt,
  11411. + struct aufs_nhash *whlist)
  11412. +{
  11413. + LKTRTrace("%.*s\n", DLNPair(dentry));
  11414. +
  11415. + return test_empty(dentry, whlist);
  11416. +}
  11417. +
  11418. +/*
  11419. + * test if @dentry dir can be rename source or not.
  11420. + * if it can, return 0 and @children is filled.
  11421. + * success means,
  11422. + * - or, it is a logically empty dir.
  11423. + * - or, it exists on writable branch and has no children including whiteouts
  11424. + * on the lower branch.
  11425. + */
  11426. +static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
  11427. +{
  11428. + int err;
  11429. + aufs_bindex_t bstart;
  11430. +
  11431. + LKTRTrace("%.*s\n", DLNPair(dentry));
  11432. +
  11433. + bstart = dbstart(dentry);
  11434. + if (bstart != btgt) {
  11435. + struct aufs_nhash *whlist;
  11436. +
  11437. + whlist = nhash_new(GFP_KERNEL);
  11438. + err = PTR_ERR(whlist);
  11439. + if (IS_ERR(whlist))
  11440. + goto out;
  11441. + err = test_empty(dentry, whlist);
  11442. + nhash_del(whlist);
  11443. + goto out;
  11444. + }
  11445. +
  11446. + if (bstart == dbtaildir(dentry))
  11447. + return 0; /* success */
  11448. +
  11449. + err = au_test_empty_lower(dentry);
  11450. +
  11451. + out:
  11452. + if (/* unlikely */(err == -ENOTEMPTY))
  11453. + err = -EXDEV;
  11454. + TraceErr(err);
  11455. + return err;
  11456. +}
  11457. +
  11458. +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
  11459. + struct inode *dir, struct dentry *dentry)
  11460. +{
  11461. + int err, do_dt_dstdir;
  11462. + aufs_bindex_t bend, bindex;
  11463. + struct inode *inode, *dirs[2];
  11464. + enum {PARENT, CHILD};
  11465. + /* reduce stack space */
  11466. + struct {
  11467. + struct rename_args a;
  11468. + struct dtime dt[2][2];
  11469. + } *p;
  11470. +
  11471. + LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
  11472. + src_dir->i_ino, DLNPair(src_dentry),
  11473. + dir->i_ino, DLNPair(dentry));
  11474. + IMustLock(src_dir);
  11475. + IMustLock(dir);
  11476. + /* braces are added to stop a warning */
  11477. + if (dentry->d_inode) {
  11478. + IMustLock(dentry->d_inode);
  11479. + }
  11480. +
  11481. + err = -ENOMEM;
  11482. + BUILD_BUG_ON(sizeof(*p) > PAGE_SIZE);
  11483. + p = kmalloc(sizeof(*p), GFP_KERNEL);
  11484. + if (unlikely(!p))
  11485. + goto out;
  11486. +
  11487. + err = -ENOTDIR;
  11488. + p->a.sb = src_dentry->d_sb;
  11489. + inode = src_dentry->d_inode;
  11490. + p->a.isdir = !!S_ISDIR(inode->i_mode);
  11491. + if (unlikely(p->a.isdir && dentry->d_inode
  11492. + && !S_ISDIR(dentry->d_inode->i_mode)))
  11493. + goto out_free;
  11494. +
  11495. + aufs_read_and_write_lock2(dentry, src_dentry, p->a.isdir);
  11496. + p->a.dlgt = !!need_dlgt(p->a.sb);
  11497. + p->a.parent[SRC] = p->a.parent[DST] = dentry->d_parent;
  11498. + p->a.issamedir = (src_dir == dir);
  11499. + if (p->a.issamedir)
  11500. + di_write_lock_parent(p->a.parent[DST]);
  11501. + else {
  11502. + p->a.parent[SRC] = src_dentry->d_parent;
  11503. + di_write_lock2_parent(p->a.parent[SRC], p->a.parent[DST],
  11504. + /*isdir*/1);
  11505. + }
  11506. +
  11507. + /* which branch we process */
  11508. + p->a.bstart[DST] = dbstart(dentry);
  11509. + p->a.btgt = err = wr_dir(dentry, 1, src_dentry, /*force_btgt*/-1,
  11510. + /*do_lock_srcdir*/0);
  11511. + if (unlikely(err < 0))
  11512. + goto out_unlock;
  11513. +
  11514. + /* are they available to be renamed */
  11515. + err = 0;
  11516. + nhash_init(&p->a.whlist);
  11517. + if (p->a.isdir && dentry->d_inode) {
  11518. + set_dbstart(dentry, p->a.bstart[DST]);
  11519. + err = may_rename_dstdir(dentry, p->a.btgt, &p->a.whlist);
  11520. + set_dbstart(dentry, p->a.btgt);
  11521. + }
  11522. + p->a.hidden_dentry[DST] = au_h_dptr(dentry);
  11523. + if (unlikely(err))
  11524. + goto out_unlock;
  11525. + //todo: minor optimize, their sb may be same while their bindex differs.
  11526. + p->a.bstart[SRC] = dbstart(src_dentry);
  11527. + p->a.hidden_dentry[SRC] = au_h_dptr(src_dentry);
  11528. + if (p->a.isdir) {
  11529. + err = may_rename_srcdir(src_dentry, p->a.btgt);
  11530. + if (unlikely(err))
  11531. + goto out_children;
  11532. + }
  11533. +
  11534. + /* prepare the writable parent dir on the same branch */
  11535. + err = wr_dir_need_wh(src_dentry, p->a.isdir, &p->a.btgt,
  11536. + p->a.issamedir ? NULL : p->a.parent[DST]);
  11537. + if (unlikely(err < 0))
  11538. + goto out_children;
  11539. + p->a.whsrc = !!err;
  11540. + p->a.whdst = (p->a.bstart[DST] == p->a.btgt);
  11541. + if (!p->a.whdst) {
  11542. + err = cpup_dirs(dentry, p->a.btgt,
  11543. + p->a.issamedir ? NULL : p->a.parent[SRC]);
  11544. + if (unlikely(err))
  11545. + goto out_children;
  11546. + }
  11547. +
  11548. + p->a.hidden_parent[SRC] = au_h_dptr_i(p->a.parent[SRC], p->a.btgt);
  11549. + p->a.hidden_parent[DST] = au_h_dptr_i(p->a.parent[DST], p->a.btgt);
  11550. + dirs[0] = src_dir;
  11551. + dirs[1] = dir;
  11552. + hdir_lock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
  11553. +
  11554. + /* store timestamps to be revertible */
  11555. + dtime_store(p->dt[PARENT] + SRC, p->a.parent[SRC],
  11556. + p->a.hidden_parent[SRC]);
  11557. + if (!p->a.issamedir)
  11558. + dtime_store(p->dt[PARENT] + DST, p->a.parent[DST],
  11559. + p->a.hidden_parent[DST]);
  11560. + do_dt_dstdir = 0;
  11561. + if (p->a.isdir) {
  11562. + dtime_store(p->dt[CHILD] + SRC, src_dentry,
  11563. + p->a.hidden_dentry[SRC]);
  11564. + if (p->a.hidden_dentry[DST]->d_inode) {
  11565. + do_dt_dstdir = 1;
  11566. + dtime_store(p->dt[CHILD] + DST, dentry,
  11567. + p->a.hidden_dentry[DST]);
  11568. + }
  11569. + }
  11570. +
  11571. + err = do_rename(src_dir, src_dentry, dir, dentry, &p->a);
  11572. + if (unlikely(err))
  11573. + goto out_dt;
  11574. + hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
  11575. +
  11576. + /* update dir attributes */
  11577. + dir->i_version++;
  11578. + if (p->a.isdir)
  11579. + au_cpup_attr_nlink(dir);
  11580. + if (ibstart(dir) == p->a.btgt)
  11581. + au_cpup_attr_timesizes(dir);
  11582. +
  11583. + if (!p->a.issamedir) {
  11584. + src_dir->i_version++;
  11585. + if (p->a.isdir)
  11586. + au_cpup_attr_nlink(src_dir);
  11587. + if (ibstart(src_dir) == p->a.btgt)
  11588. + au_cpup_attr_timesizes(src_dir);
  11589. + }
  11590. +
  11591. + // is this updating defined in POSIX?
  11592. + if (unlikely(p->a.isdir)) {
  11593. + //i_lock(inode);
  11594. + au_cpup_attr_timesizes(inode);
  11595. + //i_unlock(inode);
  11596. + }
  11597. +
  11598. +#if 0
  11599. + d_drop(src_dentry);
  11600. +#else
  11601. + /* dput/iput all lower dentries */
  11602. + set_dbwh(src_dentry, -1);
  11603. + bend = dbend(src_dentry);
  11604. + for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
  11605. + struct dentry *hd;
  11606. + hd = au_h_dptr_i(src_dentry, bindex);
  11607. + if (hd)
  11608. + set_h_dptr(src_dentry, bindex, NULL);
  11609. + }
  11610. + set_dbend(src_dentry, p->a.btgt);
  11611. +
  11612. + bend = ibend(inode);
  11613. + for (bindex = p->a.btgt + 1; bindex <= bend; bindex++) {
  11614. + struct inode *hi;
  11615. + hi = au_h_iptr_i(inode, bindex);
  11616. + if (hi)
  11617. + set_h_iptr(inode, bindex, NULL, 0);
  11618. + }
  11619. + set_ibend(inode, p->a.btgt);
  11620. +#endif
  11621. +
  11622. +#if 0
  11623. + //au_debug_on();
  11624. + //DbgDentry(dentry);
  11625. + //DbgInode(dentry->d_inode);
  11626. + //au_debug_off();
  11627. + inode = dentry->d_inode;
  11628. + if (inode) {
  11629. + aufs_bindex_t bindex, bend;
  11630. + struct dentry *hd;
  11631. + bend = dbend(dentry);
  11632. + for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
  11633. + hd = au_h_dptr_i(dentry, bindex);
  11634. + if (hd && hd->d_inode)
  11635. + xino_write0(p->a.sb, bindex, hd->d_inode->i_ino);
  11636. + /* ignore this error */
  11637. + }
  11638. + }
  11639. +#endif
  11640. +
  11641. + goto out_children; /* success */
  11642. +
  11643. + out_dt:
  11644. + dtime_revert(p->dt[PARENT] + SRC,
  11645. + p->a.hidden_parent[SRC]->d_parent
  11646. + == p->a.hidden_parent[DST]);
  11647. + if (!p->a.issamedir)
  11648. + dtime_revert(p->dt[PARENT] + DST,
  11649. + p->a.hidden_parent[DST]->d_parent
  11650. + == p->a.hidden_parent[SRC]);
  11651. + if (p->a.isdir && err != -EIO) {
  11652. + struct dentry *hd;
  11653. +
  11654. + hd = p->dt[CHILD][SRC].dt_h_dentry;
  11655. + hi_lock_child(hd->d_inode);
  11656. + dtime_revert(p->dt[CHILD] + SRC, 1);
  11657. + i_unlock(hd->d_inode);
  11658. + if (do_dt_dstdir) {
  11659. + hd = p->dt[CHILD][DST].dt_h_dentry;
  11660. + hi_lock_child(hd->d_inode);
  11661. + dtime_revert(p->dt[CHILD] + DST, 1);
  11662. + i_unlock(hd->d_inode);
  11663. + }
  11664. + }
  11665. + hdir_unlock_rename(p->a.hidden_parent, dirs, p->a.btgt, p->a.issamedir);
  11666. + out_children:
  11667. + nhash_fin(&p->a.whlist);
  11668. + out_unlock:
  11669. + //if (unlikely(err /* && p->a.isdir */)) {
  11670. + if (unlikely(err && p->a.isdir)) {
  11671. + au_update_dbstart(dentry);
  11672. + d_drop(dentry);
  11673. + }
  11674. + if (p->a.issamedir)
  11675. + di_write_unlock(p->a.parent[DST]);
  11676. + else
  11677. + di_write_unlock2(p->a.parent[SRC], p->a.parent[DST]);
  11678. + aufs_read_and_write_unlock2(dentry, src_dentry);
  11679. + out_free:
  11680. + kfree(p);
  11681. + out:
  11682. + TraceErr(err);
  11683. + return err;
  11684. +}
  11685. diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c
  11686. new file mode 100755
  11687. index 0000000..9efbd38
  11688. --- /dev/null
  11689. +++ b/fs/aufs/iinfo.c
  11690. @@ -0,0 +1,286 @@
  11691. +/*
  11692. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  11693. + *
  11694. + * This program, aufs is free software; you can redistribute it and/or modify
  11695. + * it under the terms of the GNU General Public License as published by
  11696. + * the Free Software Foundation; either version 2 of the License, or
  11697. + * (at your option) any later version.
  11698. + *
  11699. + * This program is distributed in the hope that it will be useful,
  11700. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11701. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11702. + * GNU General Public License for more details.
  11703. + *
  11704. + * You should have received a copy of the GNU General Public License
  11705. + * along with this program; if not, write to the Free Software
  11706. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  11707. + */
  11708. +
  11709. +/* $Id: iinfo.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
  11710. +
  11711. +//#include <linux/mm.h>
  11712. +#include "aufs.h"
  11713. +
  11714. +struct aufs_iinfo *itoii(struct inode *inode)
  11715. +{
  11716. + struct aufs_iinfo *iinfo;
  11717. +
  11718. + iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
  11719. + /* bad_inode case */
  11720. + if (unlikely(!iinfo->ii_hinode))
  11721. + return NULL;
  11722. + DEBUG_ON(!iinfo->ii_hinode
  11723. + /* || stosi(inode->i_sb)->si_bend < iinfo->ii_bend */
  11724. + || iinfo->ii_bend < iinfo->ii_bstart);
  11725. + return iinfo;
  11726. +}
  11727. +
  11728. +aufs_bindex_t ibstart(struct inode *inode)
  11729. +{
  11730. + IiMustAnyLock(inode);
  11731. + return itoii(inode)->ii_bstart;
  11732. +}
  11733. +
  11734. +aufs_bindex_t ibend(struct inode *inode)
  11735. +{
  11736. + IiMustAnyLock(inode);
  11737. + return itoii(inode)->ii_bend;
  11738. +}
  11739. +
  11740. +struct aufs_vdir *ivdir(struct inode *inode)
  11741. +{
  11742. + IiMustAnyLock(inode);
  11743. + DEBUG_ON(!S_ISDIR(inode->i_mode));
  11744. + return itoii(inode)->ii_vdir;
  11745. +}
  11746. +
  11747. +struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex)
  11748. +{
  11749. + struct inode *hidden_inode;
  11750. +
  11751. + IiMustAnyLock(inode);
  11752. + DEBUG_ON(bindex < 0 || ibend(inode) < bindex);
  11753. + hidden_inode = itoii(inode)->ii_hinode[0 + bindex].hi_inode;
  11754. + DEBUG_ON(hidden_inode && atomic_read(&hidden_inode->i_count) <= 0);
  11755. + return hidden_inode;
  11756. +}
  11757. +
  11758. +struct inode *au_h_iptr(struct inode *inode)
  11759. +{
  11760. + return au_h_iptr_i(inode, ibstart(inode));
  11761. +}
  11762. +
  11763. +aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex)
  11764. +{
  11765. + IiMustAnyLock(inode);
  11766. + DEBUG_ON(bindex < 0
  11767. + || ibend(inode) < bindex
  11768. + || !itoii(inode)->ii_hinode[0 + bindex].hi_inode);
  11769. + return itoii(inode)->ii_hinode[0 + bindex].hi_id;
  11770. +}
  11771. +
  11772. +// hard/soft set
  11773. +void set_ibstart(struct inode *inode, aufs_bindex_t bindex)
  11774. +{
  11775. + struct aufs_iinfo *iinfo = itoii(inode);
  11776. + struct inode *h_inode;
  11777. +
  11778. + IiMustWriteLock(inode);
  11779. + DEBUG_ON(sbend(inode->i_sb) < bindex);
  11780. + iinfo->ii_bstart = bindex;
  11781. + h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
  11782. + if (h_inode)
  11783. + au_cpup_igen(inode, h_inode);
  11784. +}
  11785. +
  11786. +void set_ibend(struct inode *inode, aufs_bindex_t bindex)
  11787. +{
  11788. + IiMustWriteLock(inode);
  11789. + DEBUG_ON(sbend(inode->i_sb) < bindex
  11790. + || bindex < ibstart(inode));
  11791. + itoii(inode)->ii_bend = bindex;
  11792. +}
  11793. +
  11794. +void set_ivdir(struct inode *inode, struct aufs_vdir *vdir)
  11795. +{
  11796. + IiMustWriteLock(inode);
  11797. + DEBUG_ON(!S_ISDIR(inode->i_mode)
  11798. + || (itoii(inode)->ii_vdir && vdir));
  11799. + itoii(inode)->ii_vdir = vdir;
  11800. +}
  11801. +
  11802. +void aufs_hiput(struct aufs_hinode *hinode)
  11803. +{
  11804. + if (unlikely(hinode->hi_notify))
  11805. + do_free_hinotify(hinode);
  11806. + if (hinode->hi_inode)
  11807. + iput(hinode->hi_inode);
  11808. +}
  11809. +
  11810. +unsigned int au_hi_flags(struct inode *inode, int isdir)
  11811. +{
  11812. + unsigned int flags;
  11813. + struct super_block *sb = inode->i_sb;
  11814. +
  11815. + flags = 0;
  11816. + if (au_flag_test(sb, AuFlag_XINO))
  11817. + flags = AUFS_HI_XINO;
  11818. + if (unlikely(isdir && au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
  11819. + flags |= AUFS_HI_NOTIFY;
  11820. + return flags;
  11821. +}
  11822. +
  11823. +void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
  11824. + struct inode *h_inode, unsigned int flags)
  11825. +{
  11826. + struct aufs_hinode *hinode;
  11827. + struct inode *hi;
  11828. + struct aufs_iinfo *iinfo = itoii(inode);
  11829. +
  11830. + LKTRTrace("i%lu, b%d, hi%lu, flags 0x%x\n",
  11831. + inode->i_ino, bindex, h_inode ? h_inode->i_ino : 0, flags);
  11832. + IiMustWriteLock(inode);
  11833. + hinode = iinfo->ii_hinode + bindex;
  11834. + hi = hinode->hi_inode;
  11835. + DEBUG_ON(bindex < ibstart(inode) || ibend(inode) < bindex
  11836. + || (h_inode && atomic_read(&h_inode->i_count) <= 0)
  11837. + || (h_inode && hi));
  11838. +
  11839. + if (hi)
  11840. + aufs_hiput(hinode);
  11841. + hinode->hi_inode = h_inode;
  11842. + if (h_inode) {
  11843. + int err;
  11844. + struct super_block *sb = inode->i_sb;
  11845. +
  11846. + if (bindex == iinfo->ii_bstart)
  11847. + au_cpup_igen(inode, h_inode);
  11848. + hinode->hi_id = sbr_id(sb, bindex);
  11849. + if (flags & AUFS_HI_XINO) {
  11850. + struct xino xino = {
  11851. + .ino = inode->i_ino,
  11852. + //.h_gen = h_inode->i_generation
  11853. + };
  11854. + //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
  11855. + err = xino_write(sb, bindex, h_inode->i_ino, &xino);
  11856. + if (unlikely(err)) {
  11857. + IOErr1("failed xino_write() %d, force noxino\n",
  11858. + err);
  11859. + au_flag_clr(sb, AuFlag_XINO);
  11860. + }
  11861. + }
  11862. + if (flags & AUFS_HI_NOTIFY) {
  11863. + err = alloc_hinotify(hinode, inode, h_inode);
  11864. + if (unlikely(err))
  11865. + IOErr1("alloc_hinotify() %d\n", err);
  11866. + else {
  11867. + /* braces are added to stop a warning */
  11868. + DEBUG_ON(!hinode->hi_notify);
  11869. + }
  11870. + }
  11871. + }
  11872. +}
  11873. +
  11874. +void au_update_iigen(struct inode *inode)
  11875. +{
  11876. + //IiMustWriteLock(inode);
  11877. + DEBUG_ON(!inode->i_sb);
  11878. + atomic_set(&itoii(inode)->ii_generation, au_sigen(inode->i_sb));
  11879. +}
  11880. +
  11881. +/* it may be called at remount time, too */
  11882. +void au_update_brange(struct inode *inode, int do_put_zero)
  11883. +{
  11884. + struct aufs_iinfo *iinfo;
  11885. +
  11886. + LKTRTrace("i%lu, %d\n", inode->i_ino, do_put_zero);
  11887. + IiMustWriteLock(inode);
  11888. +
  11889. + iinfo = itoii(inode);
  11890. + if (unlikely(!iinfo) || iinfo->ii_bstart < 0)
  11891. + return;
  11892. +
  11893. + if (do_put_zero) {
  11894. + aufs_bindex_t bindex;
  11895. + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
  11896. + bindex++) {
  11897. + struct inode *h_i;
  11898. + h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
  11899. + if (h_i && !h_i->i_nlink)
  11900. + set_h_iptr(inode, bindex, NULL, 0);
  11901. + }
  11902. + }
  11903. +
  11904. + iinfo->ii_bstart = -1;
  11905. + while (++iinfo->ii_bstart <= iinfo->ii_bend)
  11906. + if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode)
  11907. + break;
  11908. + if (iinfo->ii_bstart > iinfo->ii_bend) {
  11909. + iinfo->ii_bend = iinfo->ii_bstart = -1;
  11910. + return;
  11911. + }
  11912. +
  11913. + iinfo->ii_bend++;
  11914. + while (0 <= --iinfo->ii_bend)
  11915. + if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
  11916. + break;
  11917. +}
  11918. +
  11919. +/* ---------------------------------------------------------------------- */
  11920. +
  11921. +int au_iinfo_init(struct inode *inode)
  11922. +{
  11923. + struct aufs_iinfo *iinfo;
  11924. + struct super_block *sb;
  11925. + int nbr, i;
  11926. +
  11927. + sb = inode->i_sb;
  11928. + DEBUG_ON(!sb);
  11929. + iinfo = &(container_of(inode, struct aufs_icntnr, vfs_inode)->iinfo);
  11930. + DEBUG_ON(iinfo->ii_hinode);
  11931. + nbr = sbend(sb) + 1;
  11932. + if (unlikely(!nbr))
  11933. + nbr++;
  11934. + iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_KERNEL);
  11935. + //iinfo->ii_hinode = NULL;
  11936. + if (iinfo->ii_hinode) {
  11937. + for (i = 0; i < nbr; i++)
  11938. + iinfo->ii_hinode[i].hi_id = -1;
  11939. + atomic_set(&iinfo->ii_generation, au_sigen(sb));
  11940. + rw_init_nolock(&iinfo->ii_rwsem);
  11941. + iinfo->ii_bstart = -1;
  11942. + iinfo->ii_bend = -1;
  11943. + iinfo->ii_vdir = NULL;
  11944. + return 0;
  11945. + }
  11946. + return -ENOMEM;
  11947. +}
  11948. +
  11949. +void au_iinfo_fin(struct inode *inode)
  11950. +{
  11951. + struct aufs_iinfo *iinfo;
  11952. +
  11953. + iinfo = itoii(inode);
  11954. + /* bad_inode case */
  11955. + if (unlikely(!iinfo))
  11956. + return;
  11957. +
  11958. + if (unlikely(iinfo->ii_vdir))
  11959. + free_vdir(iinfo->ii_vdir);
  11960. +
  11961. + if (iinfo->ii_bstart >= 0) {
  11962. + aufs_bindex_t bend;
  11963. + struct aufs_hinode *hi;
  11964. + hi = iinfo->ii_hinode + iinfo->ii_bstart;
  11965. + bend = iinfo->ii_bend;
  11966. + while (iinfo->ii_bstart++ <= bend) {
  11967. + if (hi->hi_inode)
  11968. + aufs_hiput(hi);
  11969. + hi++;
  11970. + }
  11971. + //iinfo->ii_bstart = iinfo->ii_bend = -1;
  11972. + }
  11973. +
  11974. + kfree(iinfo->ii_hinode);
  11975. + //iinfo->ii_hinode = NULL;
  11976. +}
  11977. diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c
  11978. new file mode 100755
  11979. index 0000000..f18b5d8
  11980. --- /dev/null
  11981. +++ b/fs/aufs/inode.c
  11982. @@ -0,0 +1,339 @@
  11983. +/*
  11984. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  11985. + *
  11986. + * This program, aufs is free software; you can redistribute it and/or modify
  11987. + * it under the terms of the GNU General Public License as published by
  11988. + * the Free Software Foundation; either version 2 of the License, or
  11989. + * (at your option) any later version.
  11990. + *
  11991. + * This program is distributed in the hope that it will be useful,
  11992. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11993. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11994. + * GNU General Public License for more details.
  11995. + *
  11996. + * You should have received a copy of the GNU General Public License
  11997. + * along with this program; if not, write to the Free Software
  11998. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  11999. + */
  12000. +
  12001. +/* $Id: inode.c,v 1.22 2007/05/07 03:44:35 sfjro Exp $ */
  12002. +
  12003. +#include "aufs.h"
  12004. +
  12005. +int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
  12006. +{
  12007. + int err, new_sz, update, isdir;
  12008. + struct inode *first;
  12009. + struct aufs_hinode *p, *q, tmp;
  12010. + struct super_block *sb;
  12011. + struct aufs_iinfo *iinfo;
  12012. + aufs_bindex_t bindex, bend, new_bindex;
  12013. + unsigned int flags;
  12014. +
  12015. + LKTRTrace("%.*s\n", DLNPair(dentry));
  12016. + IiMustWriteLock(inode);
  12017. +
  12018. + err = -ENOMEM;
  12019. + sb = dentry->d_sb;
  12020. + bend = sbend(sb);
  12021. + new_sz = sizeof(*iinfo->ii_hinode) * (bend + 1);
  12022. + iinfo = itoii(inode);
  12023. + p = au_kzrealloc(iinfo->ii_hinode, sizeof(*p) * (iinfo->ii_bend + 1),
  12024. + new_sz, GFP_KERNEL);
  12025. + //p = NULL;
  12026. + if (unlikely(!p))
  12027. + goto out;
  12028. +
  12029. + iinfo->ii_hinode = p;
  12030. + err = 0;
  12031. + update = 0;
  12032. + p = iinfo->ii_hinode + iinfo->ii_bstart;
  12033. + first = p->hi_inode;
  12034. + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
  12035. + bindex++, p++) {
  12036. + if (unlikely(!p->hi_inode))
  12037. + continue;
  12038. +
  12039. + new_bindex = find_brindex(sb, p->hi_id);
  12040. + if (new_bindex == bindex)
  12041. + continue;
  12042. + if (new_bindex < 0) {
  12043. + update++;
  12044. + aufs_hiput(p);
  12045. + p->hi_inode = NULL;
  12046. + continue;
  12047. + }
  12048. +
  12049. + if (new_bindex < iinfo->ii_bstart)
  12050. + iinfo->ii_bstart = new_bindex;
  12051. + if (iinfo->ii_bend < new_bindex)
  12052. + iinfo->ii_bend = new_bindex;
  12053. + /* swap two hidden inode, and loop again */
  12054. + q = iinfo->ii_hinode + new_bindex;
  12055. + tmp = *q;
  12056. + *q = *p;
  12057. + *p = tmp;
  12058. + if (tmp.hi_inode) {
  12059. + bindex--;
  12060. + p--;
  12061. + }
  12062. + }
  12063. +
  12064. + isdir = S_ISDIR(inode->i_mode);
  12065. + flags = au_hi_flags(inode, isdir);
  12066. + bend = dbend(dentry);
  12067. + for (bindex = dbstart(dentry); bindex <= bend; bindex++) {
  12068. + struct inode *hi;
  12069. + struct dentry *hd;
  12070. +
  12071. + hd = au_h_dptr_i(dentry, bindex);
  12072. + if (!hd || !hd->d_inode)
  12073. + continue;
  12074. +
  12075. + if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
  12076. + hi = au_h_iptr_i(inode, bindex);
  12077. + if (hi) {
  12078. + if (hi == hd->d_inode)
  12079. + continue;
  12080. + //Dbg("here\n");
  12081. + err = -ESTALE;
  12082. + break;
  12083. + }
  12084. + }
  12085. + if (bindex < iinfo->ii_bstart)
  12086. + iinfo->ii_bstart = bindex;
  12087. + if (iinfo->ii_bend < bindex)
  12088. + iinfo->ii_bend = bindex;
  12089. + set_h_iptr(inode, bindex, igrab(hd->d_inode), flags);
  12090. + update++;
  12091. + }
  12092. +
  12093. + bend = iinfo->ii_bend;
  12094. + p = iinfo->ii_hinode;
  12095. + for (bindex = 0; bindex <= bend; bindex++, p++)
  12096. + if (p->hi_inode) {
  12097. + iinfo->ii_bstart = bindex;
  12098. + break;
  12099. + }
  12100. + p = iinfo->ii_hinode + bend;
  12101. + for (bindex = bend; bindex > iinfo->ii_bstart; bindex--, p--)
  12102. + if (p->hi_inode) {
  12103. + iinfo->ii_bend = bindex;
  12104. + break;
  12105. + }
  12106. + DEBUG_ON(iinfo->ii_bstart > bend || iinfo->ii_bend < 0);
  12107. +
  12108. + if (unlikely(err))
  12109. + goto out;
  12110. +
  12111. + if (1 || first != au_h_iptr(inode))
  12112. + au_cpup_attr_all(inode);
  12113. + if (update && isdir)
  12114. + inode->i_version++;
  12115. + au_update_iigen(inode);
  12116. +
  12117. + out:
  12118. + //au_debug_on();
  12119. + TraceErr(err);
  12120. + //au_debug_off();
  12121. + return err;
  12122. +}
  12123. +
  12124. +static int set_inode(struct inode *inode, struct dentry *dentry)
  12125. +{
  12126. + int err, isdir;
  12127. + struct dentry *hidden_dentry;
  12128. + struct inode *hidden_inode;
  12129. + umode_t mode;
  12130. + aufs_bindex_t bindex, bstart, btail;
  12131. + struct aufs_iinfo *iinfo;
  12132. + unsigned int flags;
  12133. +
  12134. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
  12135. + DEBUG_ON(!(inode->i_state & I_NEW));
  12136. + IiMustWriteLock(inode);
  12137. + hidden_dentry = au_h_dptr(dentry);
  12138. + DEBUG_ON(!hidden_dentry);
  12139. + hidden_inode = hidden_dentry->d_inode;
  12140. + DEBUG_ON(!hidden_inode);
  12141. +
  12142. + err = 0;
  12143. + isdir = 0;
  12144. + bstart = dbstart(dentry);
  12145. + mode = hidden_inode->i_mode;
  12146. + switch (mode & S_IFMT) {
  12147. + case S_IFREG:
  12148. + btail = dbtail(dentry);
  12149. + break;
  12150. + case S_IFDIR:
  12151. + isdir = 1;
  12152. + btail = dbtaildir(dentry);
  12153. + inode->i_op = &aufs_dir_iop;
  12154. + inode->i_fop = &aufs_dir_fop;
  12155. + break;
  12156. + case S_IFLNK:
  12157. + btail = dbtail(dentry);
  12158. + inode->i_op = &aufs_symlink_iop;
  12159. + break;
  12160. + case S_IFBLK:
  12161. + case S_IFCHR:
  12162. + case S_IFIFO:
  12163. + case S_IFSOCK:
  12164. + btail = dbtail(dentry);
  12165. + init_special_inode(inode, mode, hidden_inode->i_rdev);
  12166. + break;
  12167. + default:
  12168. + IOErr("Unknown file type 0%o\n", mode);
  12169. + err = -EIO;
  12170. + goto out;
  12171. + }
  12172. +
  12173. + flags = au_hi_flags(inode, isdir);
  12174. + iinfo = itoii(inode);
  12175. + iinfo->ii_bstart = bstart;
  12176. + iinfo->ii_bend = btail;
  12177. + for (bindex = bstart; bindex <= btail; bindex++) {
  12178. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  12179. + if (!hidden_dentry)
  12180. + continue;
  12181. + DEBUG_ON(!hidden_dentry->d_inode);
  12182. + set_h_iptr(inode, bindex, igrab(hidden_dentry->d_inode), flags);
  12183. + }
  12184. + au_cpup_attr_all(inode);
  12185. +
  12186. + out:
  12187. + TraceErr(err);
  12188. + return err;
  12189. +}
  12190. +
  12191. +/* successful returns with iinfo write_locked */
  12192. +//todo: return with unlocked?
  12193. +static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
  12194. +{
  12195. + int err;
  12196. + struct inode *h_inode, *h_dinode;
  12197. + aufs_bindex_t bindex, bend;
  12198. + //const int udba = !au_flag_test(inode->i_sb, AuFlag_UDBA_NONE);
  12199. +
  12200. + LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry));
  12201. +
  12202. + *matched = 0;
  12203. +
  12204. + /*
  12205. + * before this function, if aufs got any iinfo lock, it must be only
  12206. + * one, the parent dir.
  12207. + * it can happen by UDBA and the obsoleted inode number.
  12208. + */
  12209. + err = -EIO;
  12210. + if (unlikely(inode->i_ino == parent_ino(dentry)))
  12211. + goto out;
  12212. +
  12213. + h_dinode = au_h_dptr(dentry)->d_inode;
  12214. + hi_lock_child(inode); // bad name, this is not a hidden inode.
  12215. + ii_write_lock_new(inode);
  12216. + bend = ibend(inode);
  12217. + for (bindex = ibstart(inode); bindex <= bend; bindex++) {
  12218. + h_inode = au_h_iptr_i(inode, bindex);
  12219. + if (h_inode && h_inode == h_dinode) {
  12220. + //&& (ibs != bstart || !au_test_higen(inode, h_inode)));
  12221. + *matched = 1;
  12222. + err = 0;
  12223. + if (unlikely(au_iigen(inode) != au_digen(dentry)))
  12224. + err = au_refresh_hinode(inode, dentry);
  12225. + break;
  12226. + }
  12227. + }
  12228. + i_unlock(inode);
  12229. + if (unlikely(err))
  12230. + ii_write_unlock(inode);
  12231. +
  12232. + out:
  12233. + TraceErr(err);
  12234. + return err;
  12235. +}
  12236. +
  12237. +/* successful returns with iinfo write_locked */
  12238. +//todo: return with unlocked?
  12239. +struct inode *au_new_inode(struct dentry *dentry)
  12240. +{
  12241. + struct inode *inode, *h_inode;
  12242. + struct dentry *h_dentry;
  12243. + ino_t h_ino;
  12244. + struct super_block *sb;
  12245. + int err, match;
  12246. + aufs_bindex_t bstart;
  12247. + struct xino xino;
  12248. +
  12249. + LKTRTrace("%.*s\n", DLNPair(dentry));
  12250. + sb = dentry->d_sb;
  12251. + h_dentry = au_h_dptr(dentry);
  12252. + DEBUG_ON(!h_dentry);
  12253. + h_inode = h_dentry->d_inode;
  12254. + DEBUG_ON(!h_inode);
  12255. +
  12256. + bstart = dbstart(dentry);
  12257. + h_ino = h_inode->i_ino;
  12258. + err = xino_read(sb, bstart, h_ino, &xino);
  12259. + //err = -1;
  12260. + inode = ERR_PTR(err);
  12261. + if (unlikely(err))
  12262. + goto out;
  12263. + new_ino:
  12264. + if (!xino.ino) {
  12265. + xino.ino = xino_new_ino(sb);
  12266. + if (!xino.ino) {
  12267. + inode = ERR_PTR(-EIO);
  12268. + goto out;
  12269. + }
  12270. + }
  12271. +
  12272. + LKTRTrace("i%lu\n", xino.ino);
  12273. + err = -ENOMEM;
  12274. + inode = iget_locked(sb, xino.ino);
  12275. + if (unlikely(!inode))
  12276. + goto out;
  12277. + err = PTR_ERR(inode);
  12278. + if (IS_ERR(inode))
  12279. + goto out;
  12280. + err = -ENOMEM;
  12281. + if (unlikely(is_bad_inode(inode)))
  12282. + goto out_iput;
  12283. +
  12284. + LKTRTrace("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
  12285. + if (inode->i_state & I_NEW) {
  12286. + sb->s_op->read_inode(inode);
  12287. + if (!is_bad_inode(inode)) {
  12288. + ii_write_lock_new(inode);
  12289. + err = set_inode(inode, dentry);
  12290. + //err = -1;
  12291. + }
  12292. + unlock_new_inode(inode);
  12293. + if (!err)
  12294. + goto out; /* success */
  12295. + ii_write_unlock(inode);
  12296. + goto out_iput;
  12297. + } else {
  12298. + err = reval_inode(inode, dentry, &match);
  12299. + if (!err)
  12300. + goto out; /* success */
  12301. + else if (match)
  12302. + goto out_iput;
  12303. + }
  12304. +
  12305. + Warn1("broken ino, b%d, %.*s/%.*s, hi%lu, i%lu. Try udba=inotify.\n",
  12306. + bstart, DLNPair(dentry->d_parent), DLNPair(dentry), h_ino,
  12307. + xino.ino);
  12308. + xino.ino = 0;
  12309. + err = xino_write0(sb, bstart, h_ino);
  12310. + if (!err) {
  12311. + iput(inode);
  12312. + goto new_ino;
  12313. + }
  12314. +
  12315. + out_iput:
  12316. + iput(inode);
  12317. + inode = ERR_PTR(err);
  12318. + out:
  12319. + TraceErrPtr(inode);
  12320. + return inode;
  12321. +}
  12322. diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h
  12323. new file mode 100755
  12324. index 0000000..b001ac3
  12325. --- /dev/null
  12326. +++ b/fs/aufs/inode.h
  12327. @@ -0,0 +1,377 @@
  12328. +/*
  12329. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  12330. + *
  12331. + * This program, aufs is free software; you can redistribute it and/or modify
  12332. + * it under the terms of the GNU General Public License as published by
  12333. + * the Free Software Foundation; either version 2 of the License, or
  12334. + * (at your option) any later version.
  12335. + *
  12336. + * This program is distributed in the hope that it will be useful,
  12337. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12338. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12339. + * GNU General Public License for more details.
  12340. + *
  12341. + * You should have received a copy of the GNU General Public License
  12342. + * along with this program; if not, write to the Free Software
  12343. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  12344. + */
  12345. +
  12346. +/* $Id: inode.h,v 1.32 2007/05/14 03:41:52 sfjro Exp $ */
  12347. +
  12348. +#ifndef __AUFS_INODE_H__
  12349. +#define __AUFS_INODE_H__
  12350. +
  12351. +#ifdef __KERNEL__
  12352. +
  12353. +#include <linux/fs.h>
  12354. +#include <linux/inotify.h>
  12355. +#include <linux/version.h>
  12356. +#include <linux/aufs_type.h>
  12357. +#include "misc.h"
  12358. +#include "vfsub.h"
  12359. +
  12360. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  12361. +#else
  12362. +struct inotify_watch {};
  12363. +#endif
  12364. +
  12365. +/* ---------------------------------------------------------------------- */
  12366. +
  12367. +struct aufs_hinotify {
  12368. + struct inotify_watch hin_watch;
  12369. + struct inode *hin_aufs_inode; /* no get/put */
  12370. +};
  12371. +
  12372. +struct aufs_hinode {
  12373. + struct inode *hi_inode;
  12374. + aufs_bindex_t hi_id;
  12375. + struct aufs_hinotify *hi_notify;
  12376. +};
  12377. +
  12378. +struct aufs_vdir;
  12379. +struct aufs_iinfo {
  12380. + atomic_t ii_generation;
  12381. + struct super_block *ii_hsb1; /* no get/put */
  12382. +
  12383. + struct aufs_rwsem ii_rwsem;
  12384. + aufs_bindex_t ii_bstart, ii_bend;
  12385. + struct aufs_hinode *ii_hinode;
  12386. + struct aufs_vdir *ii_vdir;
  12387. +};
  12388. +
  12389. +struct aufs_icntnr {
  12390. + struct aufs_iinfo iinfo;
  12391. + struct inode vfs_inode;
  12392. +};
  12393. +
  12394. +/* ---------------------------------------------------------------------- */
  12395. +
  12396. +/* inode.c */
  12397. +int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
  12398. +struct inode *au_new_inode(struct dentry *dentry);
  12399. +
  12400. +/* i_op.c */
  12401. +extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
  12402. +int wr_dir(struct dentry *dentry, int negative, struct dentry *src_dentry,
  12403. + aufs_bindex_t force_btgt, int do_lock_srcdir);
  12404. +
  12405. +/* i_op_del.c */
  12406. +int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup,
  12407. + struct dentry *locked);
  12408. +
  12409. +/* iinfo.c */
  12410. +struct aufs_iinfo *itoii(struct inode *inode);
  12411. +aufs_bindex_t ibstart(struct inode *inode);
  12412. +aufs_bindex_t ibend(struct inode *inode);
  12413. +struct aufs_vdir *ivdir(struct inode *inode);
  12414. +struct inode *au_h_iptr_i(struct inode *inode, aufs_bindex_t bindex);
  12415. +struct inode *au_h_iptr(struct inode *inode);
  12416. +aufs_bindex_t itoid_index(struct inode *inode, aufs_bindex_t bindex);
  12417. +
  12418. +void set_ibstart(struct inode *inode, aufs_bindex_t bindex);
  12419. +void set_ibend(struct inode *inode, aufs_bindex_t bindex);
  12420. +void set_ivdir(struct inode *inode, struct aufs_vdir *vdir);
  12421. +void aufs_hiput(struct aufs_hinode *hinode);
  12422. +#define AUFS_HI_XINO 1
  12423. +#define AUFS_HI_NOTIFY 2
  12424. +unsigned int au_hi_flags(struct inode *inode, int isdir);
  12425. +void set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
  12426. + struct inode *h_inode, unsigned int flags);
  12427. +void au_update_iigen(struct inode *inode);
  12428. +void au_update_brange(struct inode *inode, int do_put_zero);
  12429. +
  12430. +int au_iinfo_init(struct inode *inode);
  12431. +void au_iinfo_fin(struct inode *inode);
  12432. +
  12433. +/* plink.c */
  12434. +#ifdef CONFIG_AUFS_DEBUG
  12435. +void au_list_plink(struct super_block *sb);
  12436. +#else
  12437. +static inline void au_list_plink(struct super_block *sb)
  12438. +{
  12439. + /* nothing */
  12440. +}
  12441. +#endif
  12442. +int au_is_plinked(struct super_block *sb, struct inode *inode);
  12443. +struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
  12444. + struct inode *inode);
  12445. +void append_plink(struct super_block *sb, struct inode *inode,
  12446. + struct dentry *h_dentry, aufs_bindex_t bindex);
  12447. +void au_put_plink(struct super_block *sb);
  12448. +void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id);
  12449. +
  12450. +/* ---------------------------------------------------------------------- */
  12451. +
  12452. +/* lock subclass for hidden inode */
  12453. +/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
  12454. +// todo: reduce it by dcsub.
  12455. +enum {
  12456. + AuLsc_Begin = I_MUTEX_QUOTA,
  12457. + AuLsc_HI_GPARENT, /* setattr with inotify */
  12458. + AuLsc_HI_PARENT, /* hidden inode, parent first */
  12459. + AuLsc_HI_CHILD,
  12460. + AuLsc_HI_PARENT2, /* copyup dirs */
  12461. + AuLsc_HI_CHILD2,
  12462. + AuLsc_End
  12463. +};
  12464. +
  12465. +/* simple abstraction */
  12466. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
  12467. +static inline void i_lock(struct inode *i)
  12468. +{
  12469. + down(&i->i_sem);
  12470. +}
  12471. +
  12472. +static inline void i_unlock(struct inode *i)
  12473. +{
  12474. + up(&i->i_sem);
  12475. +}
  12476. +
  12477. +static inline int i_trylock(struct inode *i)
  12478. +{
  12479. + return down_trylock(&i->i_sem);
  12480. +}
  12481. +
  12482. +static inline void hi_lock(struct inode *i, unsigned int lsc)
  12483. +{
  12484. + i_lock(i);
  12485. +}
  12486. +
  12487. +#define IMustLock(i) DEBUG_ON(!down_trylock(&(i)->i_sem))
  12488. +#else
  12489. +static inline void i_lock(struct inode *i)
  12490. +{
  12491. + mutex_lock(&i->i_mutex);
  12492. +}
  12493. +
  12494. +static inline void i_unlock(struct inode *i)
  12495. +{
  12496. + mutex_unlock(&i->i_mutex);
  12497. +}
  12498. +
  12499. +static inline int i_trylock(struct inode *i)
  12500. +{
  12501. + return mutex_trylock(&i->i_mutex);
  12502. +}
  12503. +
  12504. +static inline void hi_lock(struct inode *i, unsigned int lsc)
  12505. +{
  12506. + mutex_lock_nested(&i->i_mutex, lsc);
  12507. +}
  12508. +
  12509. +#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
  12510. +#endif
  12511. +
  12512. +/*
  12513. + * hi_lock_gparent, hi_lock_parent, hi_lock_parent2, hi_lock_child,
  12514. + * hi_lock_child2, hi_lock_whplink
  12515. + */
  12516. +#define LockFunc(name, lsc) \
  12517. +static inline void hi_lock_##name(struct inode *h_i) \
  12518. +{hi_lock(h_i, AuLsc_HI_##lsc);}
  12519. +
  12520. +LockFunc(gparent, GPARENT);
  12521. +LockFunc(parent, PARENT);
  12522. +LockFunc(parent2, PARENT2);
  12523. +LockFunc(child, CHILD);
  12524. +LockFunc(child2, CHILD2);
  12525. +LockFunc(whplink, CHILD2); /* sharing lock-subclass */
  12526. +
  12527. +#undef LockFunc
  12528. +
  12529. +/* ---------------------------------------------------------------------- */
  12530. +
  12531. +/* tiny test for inode number */
  12532. +/* tmpfs generation is too rough */
  12533. +static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
  12534. +{
  12535. + //IiMustAnyLock(inode);
  12536. + return !(itoii(inode)->ii_hsb1 == h_inode->i_sb
  12537. + && inode->i_generation == h_inode->i_generation);
  12538. +}
  12539. +
  12540. +static inline int au_iigen(struct inode *inode)
  12541. +{
  12542. + return atomic_read(&itoii(inode)->ii_generation);
  12543. +}
  12544. +
  12545. +#ifdef CONFIG_AUFS_HINOTIFY
  12546. +static inline void au_iigen_dec(struct inode *inode)
  12547. +{
  12548. + //Dbg("i%lu\n", inode->i_ino);
  12549. + atomic_dec(&itoii(inode)->ii_generation);
  12550. +}
  12551. +
  12552. +/* hinotify.c */
  12553. +int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
  12554. + struct inode *h_inode);
  12555. +void do_free_hinotify(struct aufs_hinode *hinode);
  12556. +void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
  12557. + unsigned int lsc);
  12558. +void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex);
  12559. +void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
  12560. + aufs_bindex_t bindex, int issamedir);
  12561. +void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
  12562. + aufs_bindex_t bindex, int issamedir);
  12563. +void au_reset_hinotify(struct inode *inode, unsigned int flags);
  12564. +int __init au_inotify_init(void);
  12565. +void au_inotify_fin(void);
  12566. +#else
  12567. +static inline
  12568. +int alloc_hinotify(struct aufs_hinode *hinode, struct inode *inode,
  12569. + struct inode *h_inode)
  12570. +{
  12571. + return -EOPNOTSUPP;
  12572. +}
  12573. +
  12574. +static inline void do_free_hinotify(struct aufs_hinode *hinode)
  12575. +{
  12576. + /* nothing */
  12577. +}
  12578. +
  12579. +static inline
  12580. +void do_hdir_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex,
  12581. + unsigned int lsc)
  12582. +{
  12583. + hi_lock(h_dir, lsc);
  12584. +}
  12585. +
  12586. +static inline
  12587. +void hdir_unlock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex)
  12588. +{
  12589. + i_unlock(h_dir);
  12590. +}
  12591. +
  12592. +static inline
  12593. +void hdir_lock_rename(struct dentry **h_parents, struct inode **dirs,
  12594. + aufs_bindex_t bindex, int issamedir)
  12595. +{
  12596. + vfsub_lock_rename(h_parents[0], h_parents[1]);
  12597. +}
  12598. +
  12599. +static inline
  12600. +void hdir_unlock_rename(struct dentry **h_parents, struct inode **dirs,
  12601. + aufs_bindex_t bindex, int issamedir)
  12602. +{
  12603. + vfsub_unlock_rename(h_parents[0], h_parents[1]);
  12604. +}
  12605. +
  12606. +static inline void au_reset_hinotify(struct inode *inode, unsigned int flags)
  12607. +{
  12608. + /* nothing */
  12609. +}
  12610. +
  12611. +#define au_inotify_init() 0
  12612. +#define au_inotify_fin() /* */
  12613. +#endif /* CONFIG_AUFS_HINOTIFY */
  12614. +
  12615. +static inline void free_hinotify(struct inode *inode, aufs_bindex_t bindex)
  12616. +{
  12617. + do_free_hinotify(itoii(inode)->ii_hinode + bindex);
  12618. +}
  12619. +
  12620. +/*
  12621. + * hgdir_lock, hdir_lock, hdir2_lock
  12622. + */
  12623. +#define LockFunc(name, lsc) \
  12624. +static inline \
  12625. +void name##_lock(struct inode *h_dir, struct inode *dir, aufs_bindex_t bindex) \
  12626. +{do_hdir_lock(h_dir, dir, bindex, AuLsc_HI_##lsc);}
  12627. +
  12628. +LockFunc(hgdir, GPARENT);
  12629. +LockFunc(hdir, PARENT);
  12630. +LockFunc(hdir2, PARENT2);
  12631. +
  12632. +#undef LockFunc
  12633. +
  12634. +/* ---------------------------------------------------------------------- */
  12635. +
  12636. +/* lock subclass for iinfo */
  12637. +enum {
  12638. + AuLsc_II_CHILD, /* child first */
  12639. + AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hinotify */
  12640. + AuLsc_II_CHILD3, /* copyup dirs */
  12641. + AuLsc_II_PARENT,
  12642. + AuLsc_II_PARENT2,
  12643. + AuLsc_II_PARENT3,
  12644. + AuLsc_II_NEW /* new inode */
  12645. +};
  12646. +
  12647. +/*
  12648. + * ii_read_lock_child, ii_write_lock_child,
  12649. + * ii_read_lock_child2, ii_write_lock_child2,
  12650. + * ii_read_lock_child3, ii_write_lock_child3,
  12651. + * ii_read_lock_parent, ii_write_lock_parent,
  12652. + * ii_read_lock_parent2, ii_write_lock_parent2,
  12653. + * ii_read_lock_parent3, ii_write_lock_parent3,
  12654. + * ii_read_lock_new, ii_write_lock_new
  12655. + */
  12656. +#define ReadLockFunc(name, lsc) \
  12657. +static inline void ii_read_lock_##name(struct inode *i) \
  12658. +{rw_read_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
  12659. +
  12660. +#define WriteLockFunc(name, lsc) \
  12661. +static inline void ii_write_lock_##name(struct inode *i) \
  12662. +{rw_write_lock_nested(&itoii(i)->ii_rwsem, AuLsc_II_##lsc);}
  12663. +
  12664. +#define RWLockFuncs(name, lsc) \
  12665. + ReadLockFunc(name, lsc); \
  12666. + WriteLockFunc(name, lsc)
  12667. +
  12668. +RWLockFuncs(child, CHILD);
  12669. +RWLockFuncs(child2, CHILD2);
  12670. +RWLockFuncs(child3, CHILD3);
  12671. +RWLockFuncs(parent, PARENT);
  12672. +RWLockFuncs(parent2, PARENT2);
  12673. +RWLockFuncs(parent3, PARENT3);
  12674. +RWLockFuncs(new, NEW);
  12675. +
  12676. +#undef ReadLockFunc
  12677. +#undef WriteLockFunc
  12678. +#undef RWLockFunc
  12679. +
  12680. +/*
  12681. + * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
  12682. + */
  12683. +SimpleUnlockRwsemFuncs(ii, struct inode *i, itoii(i)->ii_rwsem);
  12684. +
  12685. +/* to debug easier, do not make them inlined functions */
  12686. +#define IiMustReadLock(i) do { \
  12687. + SiMustAnyLock((i)->i_sb); \
  12688. + RwMustReadLock(&itoii(i)->ii_rwsem); \
  12689. +} while (0)
  12690. +
  12691. +#define IiMustWriteLock(i) do { \
  12692. + SiMustAnyLock((i)->i_sb); \
  12693. + RwMustWriteLock(&itoii(i)->ii_rwsem); \
  12694. +} while (0)
  12695. +
  12696. +#define IiMustAnyLock(i) do { \
  12697. + SiMustAnyLock((i)->i_sb); \
  12698. + RwMustAnyLock(&itoii(i)->ii_rwsem); \
  12699. +} while (0)
  12700. +
  12701. +#define IiMustNoWaiters(i) RwMustNoWaiters(&itoii(i)->ii_rwsem)
  12702. +
  12703. +#endif /* __KERNEL__ */
  12704. +#endif /* __AUFS_INODE_H__ */
  12705. diff --git a/fs/aufs/misc.c b/fs/aufs/misc.c
  12706. new file mode 100755
  12707. index 0000000..32e0549
  12708. --- /dev/null
  12709. +++ b/fs/aufs/misc.c
  12710. @@ -0,0 +1,228 @@
  12711. +/*
  12712. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  12713. + *
  12714. + * This program, aufs is free software; you can redistribute it and/or modify
  12715. + * it under the terms of the GNU General Public License as published by
  12716. + * the Free Software Foundation; either version 2 of the License, or
  12717. + * (at your option) any later version.
  12718. + *
  12719. + * This program is distributed in the hope that it will be useful,
  12720. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12721. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12722. + * GNU General Public License for more details.
  12723. + *
  12724. + * You should have received a copy of the GNU General Public License
  12725. + * along with this program; if not, write to the Free Software
  12726. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  12727. + */
  12728. +
  12729. +/* $Id: misc.c,v 1.31 2007/05/14 03:41:52 sfjro Exp $ */
  12730. +
  12731. +//#include <linux/fs.h>
  12732. +//#include <linux/namei.h>
  12733. +//#include <linux/mm.h>
  12734. +//#include <asm/uaccess.h>
  12735. +#include "aufs.h"
  12736. +
  12737. +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
  12738. +{
  12739. + void *q;
  12740. +
  12741. + LKTRTrace("p %p, nused %d, sz %d, ksize %d\n",
  12742. + p, nused, new_sz, ksize(p));
  12743. + DEBUG_ON(new_sz <= 0);
  12744. + if (new_sz <= nused)
  12745. + return p;
  12746. + if (new_sz <= ksize(p)) {
  12747. + memset(p + nused, 0, new_sz - nused);
  12748. + return p;
  12749. + }
  12750. +
  12751. + q = kmalloc(new_sz, gfp);
  12752. + //q = NULL;
  12753. + if (unlikely(!q))
  12754. + return NULL;
  12755. + memcpy(q, p, nused);
  12756. + memset(q + nused, 0, new_sz - nused);
  12757. + //smp_mb();
  12758. + kfree(p);
  12759. + return q;
  12760. +}
  12761. +
  12762. +/* ---------------------------------------------------------------------- */
  12763. +
  12764. +// todo: make it inline
  12765. +struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
  12766. + struct super_block *sb, aufs_bindex_t bindex)
  12767. +{
  12768. + LKTRTrace("nd %p, b%d\n", nd, bindex);
  12769. +
  12770. + if (!nd)
  12771. + return NULL;
  12772. +
  12773. + fake_nd->dentry = NULL;
  12774. + fake_nd->mnt = NULL;
  12775. +
  12776. +#ifndef CONFIG_AUFS_FAKE_DM
  12777. + DiMustAnyLock(nd->dentry);
  12778. +
  12779. + if (bindex <= dbend(nd->dentry))
  12780. + fake_nd->dentry = au_h_dptr_i(nd->dentry, bindex);
  12781. + if (fake_nd->dentry) {
  12782. + dget(fake_nd->dentry);
  12783. + fake_nd->mnt = sbr_mnt(sb, bindex);
  12784. + DEBUG_ON(!fake_nd->mnt);
  12785. + mntget(fake_nd->mnt);
  12786. + } else
  12787. + fake_nd = ERR_PTR(-ENOENT);
  12788. +#endif
  12789. +
  12790. + TraceErrPtr(fake_nd);
  12791. + return fake_nd;
  12792. +}
  12793. +
  12794. +void fake_dm_release(struct nameidata *fake_nd)
  12795. +{
  12796. +#ifndef CONFIG_AUFS_FAKE_DM
  12797. + if (fake_nd) {
  12798. + mntput(fake_nd->mnt);
  12799. + dput(fake_nd->dentry);
  12800. + }
  12801. +#endif
  12802. +}
  12803. +
  12804. +/* ---------------------------------------------------------------------- */
  12805. +
  12806. +int au_copy_file(struct file *dst, struct file *src, loff_t len,
  12807. + struct super_block *sb, int *sparse)
  12808. +{
  12809. + int err, all_zero, dlgt;
  12810. + unsigned long blksize;
  12811. + char *buf;
  12812. + /* reduce stack space */
  12813. + struct iattr *ia;
  12814. +
  12815. + LKTRTrace("%.*s, %.*s\n",
  12816. + DLNPair(dst->f_dentry), DLNPair(src->f_dentry));
  12817. + DEBUG_ON(!(dst->f_mode & FMODE_WRITE));
  12818. + IMustLock(dst->f_dentry->d_parent->d_inode);
  12819. +
  12820. + err = -ENOMEM;
  12821. + blksize = dst->f_dentry->d_sb->s_blocksize;
  12822. + if (!blksize || PAGE_SIZE < blksize)
  12823. + blksize = PAGE_SIZE;
  12824. + LKTRTrace("blksize %lu\n", blksize);
  12825. + buf = kmalloc(blksize, GFP_KERNEL);
  12826. + //buf = NULL;
  12827. + if (unlikely(!buf))
  12828. + goto out;
  12829. + ia = kmalloc(sizeof(*ia), GFP_KERNEL);
  12830. + if (unlikely(!ia))
  12831. + goto out_buf;
  12832. +
  12833. + dlgt = need_dlgt(sb);
  12834. + err = all_zero = 0;
  12835. + dst->f_pos = src->f_pos = 0;
  12836. + while (len) {
  12837. + size_t sz, rbytes, wbytes, i;
  12838. + char *p;
  12839. +
  12840. + LKTRTrace("len %lld\n", len);
  12841. + sz = blksize;
  12842. + if (len < blksize)
  12843. + sz = len;
  12844. +
  12845. + /* support LSM and notify */
  12846. + rbytes = 0;
  12847. + while (!rbytes || err == -EAGAIN || err == -EINTR)
  12848. + err = rbytes = vfsub_read_k(src, buf, sz, &src->f_pos,
  12849. + dlgt);
  12850. + if (unlikely(err < 0))
  12851. + break;
  12852. +
  12853. + all_zero = 0;
  12854. + if (len >= rbytes && rbytes == blksize) {
  12855. + all_zero = 1;
  12856. + p = buf;
  12857. + for (i = 0; all_zero && i < rbytes; i++)
  12858. + all_zero = !*p++;
  12859. + }
  12860. + if (!all_zero) {
  12861. + wbytes = rbytes;
  12862. + p = buf;
  12863. + while (wbytes) {
  12864. + size_t b;
  12865. + /* support LSM and notify */
  12866. + err = b = vfsub_write_k(dst, p, wbytes,
  12867. + &dst->f_pos, dlgt);
  12868. + if (unlikely(err == -EAGAIN || err == -EINTR))
  12869. + continue;
  12870. + if (unlikely(err < 0))
  12871. + break;
  12872. + wbytes -= b;
  12873. + p += b;
  12874. + }
  12875. + } else {
  12876. + loff_t res;
  12877. + LKTRLabel(hole);
  12878. + *sparse = 1;
  12879. + err = res = vfsub_llseek(dst, rbytes, SEEK_CUR);
  12880. + if (unlikely(res < 0))
  12881. + break;
  12882. + }
  12883. + len -= rbytes;
  12884. + err = 0;
  12885. + }
  12886. +
  12887. + /* the last block may be a hole */
  12888. + if (unlikely(!err && all_zero)) {
  12889. + struct dentry *h_d = dst->f_dentry;
  12890. + struct inode *h_i = h_d->d_inode;
  12891. +
  12892. + LKTRLabel(last hole);
  12893. + do {
  12894. + err = vfsub_write_k(dst, "\0", 1, &dst->f_pos, dlgt);
  12895. + } while (err == -EAGAIN || err == -EINTR);
  12896. + if (err == 1) {
  12897. + ia->ia_size = dst->f_pos;
  12898. + ia->ia_valid = ATTR_SIZE | ATTR_FILE;
  12899. + ia->ia_file = dst;
  12900. + hi_lock_child2(h_i);
  12901. + err = vfsub_notify_change(h_d, ia, dlgt);
  12902. + i_unlock(h_i);
  12903. + }
  12904. + }
  12905. +
  12906. + kfree(ia);
  12907. + out_buf:
  12908. + kfree(buf);
  12909. + out:
  12910. + TraceErr(err);
  12911. + return err;
  12912. +}
  12913. +
  12914. +/* ---------------------------------------------------------------------- */
  12915. +
  12916. +int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode)
  12917. +{
  12918. + int err;
  12919. +
  12920. + err = br_rdonly(stobr(sb, bindex));
  12921. + if (!err && inode) {
  12922. + struct inode *hi = au_h_iptr_i(inode, bindex);
  12923. + if (hi)
  12924. + err = IS_IMMUTABLE(hi) ? -EROFS : 0;
  12925. + }
  12926. + return err;
  12927. +}
  12928. +
  12929. +int au_test_perm(struct inode *hidden_inode, int mask, int dlgt)
  12930. +{
  12931. + if (!current->fsuid)
  12932. + return 0;
  12933. + if (unlikely(au_is_nfs(hidden_inode->i_sb)
  12934. + && (mask & MAY_WRITE)
  12935. + && S_ISDIR(hidden_inode->i_mode)))
  12936. + mask |= MAY_READ; /* force permission check */
  12937. + return vfsub_permission(hidden_inode, mask, NULL, dlgt);
  12938. +}
  12939. diff --git a/fs/aufs/misc.h b/fs/aufs/misc.h
  12940. new file mode 100755
  12941. index 0000000..fea4a2c
  12942. --- /dev/null
  12943. +++ b/fs/aufs/misc.h
  12944. @@ -0,0 +1,187 @@
  12945. +/*
  12946. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  12947. + *
  12948. + * This program, aufs is free software; you can redistribute it and/or modify
  12949. + * it under the terms of the GNU General Public License as published by
  12950. + * the Free Software Foundation; either version 2 of the License, or
  12951. + * (at your option) any later version.
  12952. + *
  12953. + * This program is distributed in the hope that it will be useful,
  12954. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12955. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12956. + * GNU General Public License for more details.
  12957. + *
  12958. + * You should have received a copy of the GNU General Public License
  12959. + * along with this program; if not, write to the Free Software
  12960. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  12961. + */
  12962. +
  12963. +/* $Id: misc.h,v 1.25 2007/05/14 03:41:52 sfjro Exp $ */
  12964. +
  12965. +#ifndef __AUFS_MISC_H__
  12966. +#define __AUFS_MISC_H__
  12967. +
  12968. +#ifdef __KERNEL__
  12969. +
  12970. +#include <linux/fs.h>
  12971. +#include <linux/namei.h>
  12972. +#include <linux/sched.h>
  12973. +#include <linux/version.h>
  12974. +#include <linux/aufs_type.h>
  12975. +
  12976. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  12977. +#define I_MUTEX_QUOTA 0
  12978. +#define lockdep_off() /* */
  12979. +#define lockdep_on() /* */
  12980. +#define mutex_lock_nested(mtx, lsc) mutex_lock(mtx)
  12981. +#define down_write_nested(rw, lsc) down_write(rw)
  12982. +#define down_read_nested(rw, lsc) down_read(rw)
  12983. +#endif
  12984. +
  12985. +/* ---------------------------------------------------------------------- */
  12986. +
  12987. +struct aufs_rwsem {
  12988. + struct rw_semaphore rwsem;
  12989. +#ifdef CONFIG_AUFS_DEBUG
  12990. + atomic_t rcnt;
  12991. +#endif
  12992. +};
  12993. +
  12994. +#ifdef CONFIG_AUFS_DEBUG
  12995. +#define DbgRcntInit(rw) atomic_set(&(rw)->rcnt, 0)
  12996. +#define DbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
  12997. +#define DbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
  12998. +#else
  12999. +#define DbgRcntInit(rw) /* */
  13000. +#define DbgRcntInc(rw) /* */
  13001. +#define DbgRcntDec(rw) /* */
  13002. +#endif
  13003. +
  13004. +static inline void rw_init_nolock(struct aufs_rwsem *rw)
  13005. +{
  13006. + DbgRcntInit(rw);
  13007. + init_rwsem(&rw->rwsem);
  13008. +}
  13009. +
  13010. +static inline void rw_init_wlock(struct aufs_rwsem *rw)
  13011. +{
  13012. + rw_init_nolock(rw);
  13013. + down_write(&rw->rwsem);
  13014. +}
  13015. +
  13016. +static inline void rw_init_wlock_nested(struct aufs_rwsem *rw, unsigned int lsc)
  13017. +{
  13018. + rw_init_nolock(rw);
  13019. + down_write_nested(&rw->rwsem, lsc);
  13020. +}
  13021. +
  13022. +static inline void rw_read_lock(struct aufs_rwsem *rw)
  13023. +{
  13024. + down_read(&rw->rwsem);
  13025. + DbgRcntInc(rw);
  13026. +}
  13027. +
  13028. +static inline void rw_read_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
  13029. +{
  13030. + down_read_nested(&rw->rwsem, lsc);
  13031. + DbgRcntInc(rw);
  13032. +}
  13033. +
  13034. +static inline void rw_read_unlock(struct aufs_rwsem *rw)
  13035. +{
  13036. + DbgRcntDec(rw);
  13037. + up_read(&rw->rwsem);
  13038. +}
  13039. +
  13040. +static inline void rw_dgrade_lock(struct aufs_rwsem *rw)
  13041. +{
  13042. + DbgRcntInc(rw);
  13043. + downgrade_write(&rw->rwsem);
  13044. +}
  13045. +
  13046. +static inline void rw_write_lock(struct aufs_rwsem *rw)
  13047. +{
  13048. + down_write(&rw->rwsem);
  13049. +}
  13050. +
  13051. +static inline void rw_write_lock_nested(struct aufs_rwsem *rw, unsigned int lsc)
  13052. +{
  13053. + down_write_nested(&rw->rwsem, lsc);
  13054. +}
  13055. +
  13056. +static inline void rw_write_unlock(struct aufs_rwsem *rw)
  13057. +{
  13058. + up_write(&rw->rwsem);
  13059. +}
  13060. +
  13061. +#if 0 // why is not _nested version defined
  13062. +static inline int rw_read_trylock(struct aufs_rwsem *rw)
  13063. +{
  13064. + int ret = down_read_trylock(&rw->rwsem);
  13065. + if (ret)
  13066. + DbgRcntInc(rw);
  13067. + return ret;
  13068. +}
  13069. +
  13070. +static inline int rw_write_trylock(struct aufs_rwsem *rw)
  13071. +{
  13072. + return down_write_trylock(&rw->rwsem);
  13073. +}
  13074. +#endif
  13075. +
  13076. +#undef DbgRcntInit
  13077. +#undef DbgRcntInc
  13078. +#undef DbgRcntDec
  13079. +
  13080. +/* to debug easier, do not make them inlined functions */
  13081. +#define RwMustNoWaiters(rw) DEBUG_ON(!list_empty(&(rw)->rwsem.wait_list))
  13082. +#define RwMustAnyLock(rw) DEBUG_ON(down_write_trylock(&(rw)->rwsem))
  13083. +#ifdef CONFIG_AUFS_DEBUG
  13084. +#define RwMustReadLock(rw) do { \
  13085. + RwMustAnyLock(rw); \
  13086. + DEBUG_ON(!atomic_read(&(rw)->rcnt)); \
  13087. +} while (0)
  13088. +#define RwMustWriteLock(rw) do { \
  13089. + RwMustAnyLock(rw); \
  13090. + DEBUG_ON(atomic_read(&(rw)->rcnt)); \
  13091. +} while (0)
  13092. +#else
  13093. +#define RwMustReadLock(rw) RwMustAnyLock(rw)
  13094. +#define RwMustWriteLock(rw) RwMustAnyLock(rw)
  13095. +#endif
  13096. +
  13097. +#define SimpleLockRwsemFuncs(prefix, param, rwsem) \
  13098. +static inline void prefix##_read_lock(param) {rw_read_lock(&(rwsem));} \
  13099. +static inline void prefix##_write_lock(param) {rw_write_lock(&(rwsem));}
  13100. +//static inline void prefix##_read_trylock(param) {rw_read_trylock(&(rwsem));}
  13101. +//static inline void prefix##_write_trylock(param) {rw_write_trylock(&(rwsem));}
  13102. +//static inline void prefix##_read_trylock_nested(param, lsc)
  13103. +//{rw_read_trylock_nested(&(rwsem, lsc));}
  13104. +//static inline void prefix##_write_trylock_nestd(param, lsc)
  13105. +//{rw_write_trylock_nested(&(rwsem), nested);}
  13106. +
  13107. +#define SimpleUnlockRwsemFuncs(prefix, param, rwsem) \
  13108. +static inline void prefix##_read_unlock(param) {rw_read_unlock(&(rwsem));} \
  13109. +static inline void prefix##_write_unlock(param) {rw_write_unlock(&(rwsem));} \
  13110. +static inline void prefix##_downgrade_lock(param) {rw_dgrade_lock(&(rwsem));}
  13111. +
  13112. +#define SimpleRwsemFuncs(prefix, param, rwsem) \
  13113. + SimpleLockRwsemFuncs(prefix, param, rwsem); \
  13114. + SimpleUnlockRwsemFuncs(prefix, param, rwsem)
  13115. +
  13116. +/* ---------------------------------------------------------------------- */
  13117. +
  13118. +typedef ssize_t (*readf_t)(struct file*, char __user*, size_t, loff_t*);
  13119. +typedef ssize_t (*writef_t)(struct file*, const char __user*, size_t, loff_t*);
  13120. +
  13121. +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
  13122. +struct nameidata *fake_dm(struct nameidata *fake_nd, struct nameidata *nd,
  13123. + struct super_block *sb, aufs_bindex_t bindex);
  13124. +void fake_dm_release(struct nameidata *fake_nd);
  13125. +int au_copy_file(struct file *dst, struct file *src, loff_t len,
  13126. + struct super_block *sb, int *sparse);
  13127. +int test_ro(struct super_block *sb, aufs_bindex_t bindex, struct inode *inode);
  13128. +int au_test_perm(struct inode *h_inode, int mask, int dlgt);
  13129. +
  13130. +#endif /* __KERNEL__ */
  13131. +#endif /* __AUFS_MISC_H__ */
  13132. diff --git a/fs/aufs/module.c b/fs/aufs/module.c
  13133. new file mode 100755
  13134. index 0000000..06c563e
  13135. --- /dev/null
  13136. +++ b/fs/aufs/module.c
  13137. @@ -0,0 +1,334 @@
  13138. +/*
  13139. + * Copyright (C) 2007 Junjiro Okajima
  13140. + *
  13141. + * This program, aufs is free software; you can redistribute it and/or modify
  13142. + * it under the terms of the GNU General Public License as published by
  13143. + * the Free Software Foundation; either version 2 of the License, or
  13144. + * (at your option) any later version.
  13145. + *
  13146. + * This program is distributed in the hope that it will be useful,
  13147. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13148. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13149. + * GNU General Public License for more details.
  13150. + *
  13151. + * You should have received a copy of the GNU General Public License
  13152. + * along with this program; if not, write to the Free Software
  13153. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  13154. + */
  13155. +
  13156. +/* $Id: module.c,v 1.9 2007/04/30 05:46:32 sfjro Exp $ */
  13157. +
  13158. +//#include <linux/init.h>
  13159. +//#include <linux/kobject.h>
  13160. +#include <linux/module.h>
  13161. +//#include <linux/seq_file.h>
  13162. +//#include <linux/sysfs.h>
  13163. +#include "aufs.h"
  13164. +
  13165. +/* ---------------------------------------------------------------------- */
  13166. +
  13167. +/*
  13168. + * aufs caches
  13169. + */
  13170. +struct kmem_cache *aufs_cachep[AuCache_Last];
  13171. +static int __init create_cache(void)
  13172. +{
  13173. +#define Cache(type) kmem_cache_create(#type, sizeof(struct type), 0, \
  13174. + SLAB_RECLAIM_ACCOUNT, NULL, NULL)
  13175. +
  13176. + if ((aufs_cachep[AuCache_DINFO] = Cache(aufs_dinfo))
  13177. + && (aufs_cachep[AuCache_ICNTNR] = Cache(aufs_icntnr))
  13178. + && (aufs_cachep[AuCache_FINFO] = Cache(aufs_finfo))
  13179. + //&& (aufs_cachep[AuCache_FINFO] = NULL)
  13180. + && (aufs_cachep[AuCache_VDIR] = Cache(aufs_vdir))
  13181. + && (aufs_cachep[AuCache_DEHSTR] = Cache(aufs_dehstr))
  13182. + && (aufs_cachep[AuCache_HINOTIFY] = Cache(aufs_hinotify)))
  13183. + return 0;
  13184. + return -ENOMEM;
  13185. +
  13186. +#undef Cache
  13187. +}
  13188. +
  13189. +static void destroy_cache(void)
  13190. +{
  13191. + int i;
  13192. + for (i = 0; i < AuCache_Last; i++)
  13193. + if (aufs_cachep[i])
  13194. + kmem_cache_destroy(aufs_cachep[i]);
  13195. +}
  13196. +
  13197. +/* ---------------------------------------------------------------------- */
  13198. +
  13199. +char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
  13200. +int au_dir_roflags;
  13201. +extern struct file_system_type aufs_fs_type;
  13202. +
  13203. +#ifdef DbgDlgt
  13204. +#include <linux/security.h>
  13205. +#include "dbg_dlgt.c"
  13206. +#else
  13207. +#define dbg_dlgt_init() 0
  13208. +#define dbg_dlgt_fin() /* */
  13209. +#endif
  13210. +
  13211. +/*
  13212. + * functions for module interface.
  13213. + */
  13214. +MODULE_LICENSE("GPL");
  13215. +MODULE_AUTHOR("Junjiro Okajima");
  13216. +MODULE_DESCRIPTION(AUFS_NAME " -- Another unionfs");
  13217. +MODULE_VERSION(AUFS_VERSION);
  13218. +
  13219. +/* it should be 'byte', but param_set_byte() prints by "%c" */
  13220. +short aufs_nwkq = AUFS_NWKQ_DEF;
  13221. +MODULE_PARM_DESC(nwkq, "the number of workqueue thread, " AUFS_WKQ_NAME);
  13222. +module_param_named(nwkq, aufs_nwkq, short, 0444);
  13223. +
  13224. +int sysaufs_brs = 0;
  13225. +MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/brs");
  13226. +module_param_named(brs, sysaufs_brs, int, 0444);
  13227. +
  13228. +static int __init aufs_init(void)
  13229. +{
  13230. + int err, i;
  13231. + char *p;
  13232. +
  13233. + //sbinfo->si_xino is atomic_long_t
  13234. + BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
  13235. +
  13236. +#ifdef CONFIG_AUFS_DEBUG
  13237. + {
  13238. + struct aufs_destr destr;
  13239. + destr.len = -1;
  13240. + DEBUG_ON(destr.len < NAME_MAX);
  13241. + }
  13242. +
  13243. +#ifdef CONFIG_4KSTACKS
  13244. + printk("CONFIG_4KSTACKS is defined.\n");
  13245. +#endif
  13246. +#if 0 // verbose debug
  13247. + {
  13248. + union {
  13249. + struct aufs_branch *br;
  13250. + struct aufs_dinfo *di;
  13251. + struct aufs_finfo *fi;
  13252. + struct aufs_iinfo *ii;
  13253. + struct aufs_hinode *hi;
  13254. + struct aufs_sbinfo *si;
  13255. + struct aufs_destr *destr;
  13256. + struct aufs_de *de;
  13257. + struct aufs_wh *wh;
  13258. + struct aufs_vdir *vd;
  13259. + } u;
  13260. +
  13261. + printk("br{"
  13262. + "xino %d, readf %d, writef %d, "
  13263. + "id %d, perm %d, mnt %d, count %d, "
  13264. + "wh_sem %d, wh %d, run %d} %d\n",
  13265. + offsetof(typeof(*u.br), br_xino),
  13266. + offsetof(typeof(*u.br), br_xino_read),
  13267. + offsetof(typeof(*u.br), br_xino_write),
  13268. + offsetof(typeof(*u.br), br_id),
  13269. + offsetof(typeof(*u.br), br_perm),
  13270. + offsetof(typeof(*u.br), br_mnt),
  13271. + offsetof(typeof(*u.br), br_count),
  13272. + offsetof(typeof(*u.br), br_wh_rwsem),
  13273. + offsetof(typeof(*u.br), br_wh),
  13274. + offsetof(typeof(*u.br), br_wh_running),
  13275. + sizeof(*u.br));
  13276. + printk("di{gen %d, rwsem %d, bstart %d, bend %d, bwh %d, "
  13277. + "bdiropq %d, hdentry %d, reval %d} %d\n",
  13278. + offsetof(typeof(*u.di), di_generation),
  13279. + offsetof(typeof(*u.di), di_rwsem),
  13280. + offsetof(typeof(*u.di), di_bstart),
  13281. + offsetof(typeof(*u.di), di_bend),
  13282. + offsetof(typeof(*u.di), di_bwh),
  13283. + offsetof(typeof(*u.di), di_bdiropq),
  13284. + offsetof(typeof(*u.di), di_hdentry),
  13285. + offsetof(typeof(*u.di), di_reval),
  13286. + sizeof(*u.di));
  13287. + printk("fi{gen %d, rwsem %d, hfile %d, bstart %d, bend %d, "
  13288. + "h_vm_ops %d, vdir_cach %d} %d\n",
  13289. + offsetof(typeof(*u.fi), fi_generation),
  13290. + offsetof(typeof(*u.fi), fi_rwsem),
  13291. + offsetof(typeof(*u.fi), fi_hfile),
  13292. + offsetof(typeof(*u.fi), fi_bstart),
  13293. + offsetof(typeof(*u.fi), fi_bend),
  13294. + offsetof(typeof(*u.fi), fi_h_vm_ops),
  13295. + offsetof(typeof(*u.fi), fi_vdir_cache),
  13296. + sizeof(*u.fi));
  13297. + printk("ii{rwsem %d, bstart %d, bend %d, hinode %d, vdir %d} "
  13298. + "%d\n",
  13299. + offsetof(typeof(*u.ii), ii_rwsem),
  13300. + offsetof(typeof(*u.ii), ii_bstart),
  13301. + offsetof(typeof(*u.ii), ii_bend),
  13302. + offsetof(typeof(*u.ii), ii_hinode),
  13303. + offsetof(typeof(*u.ii), ii_vdir),
  13304. + sizeof(*u.ii));
  13305. + printk("hi{inode %d, id %d, notify %d} %d\n",
  13306. + offsetof(typeof(*u.hi), hi_inode),
  13307. + offsetof(typeof(*u.hi), hi_id),
  13308. + offsetof(typeof(*u.hi), hi_notify),
  13309. + sizeof(*u.hi));
  13310. + printk("si{rwsem %d, gen %d, "
  13311. + "failed_refresh %d, "
  13312. + "bend %d, last id %d, br %d, "
  13313. + "flags %d, "
  13314. + "xino %d, "
  13315. + "rdcache %d, "
  13316. + "dirwh %d, "
  13317. + "pl_lock %d, pl %d, "
  13318. + "kobj %d} %d\n",
  13319. + offsetof(typeof(*u.si), si_rwsem),
  13320. + offsetof(typeof(*u.si), si_generation),
  13321. + -1,//offsetof(typeof(*u.si), si_failed_refresh_dirs),
  13322. + offsetof(typeof(*u.si), si_bend),
  13323. + offsetof(typeof(*u.si), si_last_br_id),
  13324. + offsetof(typeof(*u.si), si_branch),
  13325. + offsetof(typeof(*u.si), si_flags),
  13326. + offsetof(typeof(*u.si), si_xino),
  13327. + offsetof(typeof(*u.si), si_rdcache),
  13328. + offsetof(typeof(*u.si), si_dirwh),
  13329. + offsetof(typeof(*u.si), si_plink_lock),
  13330. + offsetof(typeof(*u.si), si_plink),
  13331. + offsetof(typeof(*u.si), si_kobj),
  13332. + sizeof(*u.si));
  13333. + printk("destr{len %d, name %d} %d\n",
  13334. + offsetof(typeof(*u.destr), len),
  13335. + offsetof(typeof(*u.destr), name),
  13336. + sizeof(*u.destr));
  13337. + printk("de{ino %d, type %d, str %d} %d\n",
  13338. + offsetof(typeof(*u.de), de_ino),
  13339. + offsetof(typeof(*u.de), de_type),
  13340. + offsetof(typeof(*u.de), de_str),
  13341. + sizeof(*u.de));
  13342. + printk("wh{hash %d, bindex %d, str %d} %d\n",
  13343. + offsetof(typeof(*u.wh), wh_hash),
  13344. + offsetof(typeof(*u.wh), wh_bindex),
  13345. + offsetof(typeof(*u.wh), wh_str),
  13346. + sizeof(*u.wh));
  13347. + printk("vd{deblk %d, nblk %d, last %d, ver %d, jiffy %d} %d\n",
  13348. + offsetof(typeof(*u.vd), vd_deblk),
  13349. + offsetof(typeof(*u.vd), vd_nblk),
  13350. + offsetof(typeof(*u.vd), vd_last),
  13351. + offsetof(typeof(*u.vd), vd_version),
  13352. + offsetof(typeof(*u.vd), vd_jiffy),
  13353. + sizeof(*u.vd));
  13354. + }
  13355. +#endif
  13356. +#endif
  13357. +
  13358. + p = au_esc_chars;
  13359. + for (i = 1; i <= ' '; i++)
  13360. + *p++ = i;
  13361. + *p++ = '\\';
  13362. + *p++ = '\x7f';
  13363. + *p = 0;
  13364. +
  13365. + au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
  13366. +#ifndef CONFIG_AUFS_SYSAUFS
  13367. + sysaufs_brs = 0;
  13368. +#endif
  13369. +
  13370. + err = -EINVAL;
  13371. + if (unlikely(aufs_nwkq <= 0))
  13372. + goto out;
  13373. + err = create_cache();
  13374. + if (unlikely(err))
  13375. + goto out;
  13376. + err = sysaufs_init();
  13377. + if (unlikely(err))
  13378. + goto out_cache;
  13379. + err = au_wkq_init();
  13380. + if (unlikely(err))
  13381. + goto out_kobj;
  13382. + err = au_inotify_init();
  13383. + if (unlikely(err))
  13384. + goto out_wkq;
  13385. + err = dbg_dlgt_init();
  13386. + if (unlikely(err))
  13387. + goto out_inotify;
  13388. + err = register_filesystem(&aufs_fs_type);
  13389. + if (unlikely(err))
  13390. + goto out_dlgt;
  13391. + printk(AUFS_NAME " " AUFS_VERSION "\n");
  13392. + return 0; /* success */
  13393. +
  13394. + out_dlgt:
  13395. + dbg_dlgt_fin();
  13396. + out_inotify:
  13397. + au_inotify_fin();
  13398. + out_wkq:
  13399. + au_wkq_fin();
  13400. + out_kobj:
  13401. + sysaufs_fin();
  13402. + out_cache:
  13403. + destroy_cache();
  13404. + out:
  13405. + TraceErr(err);
  13406. + return err;
  13407. +}
  13408. +
  13409. +static void __exit aufs_exit(void)
  13410. +{
  13411. + unregister_filesystem(&aufs_fs_type);
  13412. + dbg_dlgt_fin();
  13413. + au_inotify_fin();
  13414. + au_wkq_fin();
  13415. + sysaufs_fin();
  13416. + destroy_cache();
  13417. +}
  13418. +
  13419. +module_init(aufs_init);
  13420. +module_exit(aufs_exit);
  13421. +
  13422. +/* ---------------------------------------------------------------------- */
  13423. +
  13424. +// fake Kconfig
  13425. +#if 1
  13426. +#ifdef CONFIG_AUFS_HINOTIFY
  13427. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  13428. +#error CONFIG_AUFS_HINOTIFY is supported in linux-2.6.18 and later.
  13429. +#endif
  13430. +#ifndef CONFIG_INOTIFY
  13431. +#error enable CONFIG_INOTIFY to use CONFIG_AUFS_HINOTIFY.
  13432. +#endif
  13433. +#endif
  13434. +
  13435. +#if AUFS_BRANCH_MAX > 511 && BITS_PER_LONG == 64 && PAGE_SIZE == 4096
  13436. +#warning For 4k pagesize and 64bit environment, \
  13437. + CONFIG_AUFS_BRANCH_MAX_511 or smaller is recommended.
  13438. +#endif
  13439. +
  13440. +#ifdef CONFIG_AUFS_SYSAUFS
  13441. +#ifndef CONFIG_SYSFS
  13442. +#error CONFIG_AUFS_SYSAUFS requires CONFIG_SYSFS.
  13443. +#endif
  13444. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  13445. +#error CONFIG_AUFS_SYSAUFS requires linux-2.6.18 and later.
  13446. +#endif
  13447. +#endif
  13448. +
  13449. +#ifdef CONFIG_AUFS_EXPORT
  13450. +#if !defined(CONFIG_EXPORTFS) && !defined(CONFIG_EXPORTFS_MODULE)
  13451. +#error CONFIG_AUFS_EXPORT requires CONFIG_EXPORTFS
  13452. +#endif
  13453. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  13454. +#error CONFIG_AUFS_EXPORT requires linux-2.6.18 and later.
  13455. +#endif
  13456. +#if defined(CONFIG_EXPORTFS_MODULE) && defined(CONFIG_AUFS)
  13457. +#error need CONFIG_EXPORTFS=y to link aufs statically with CONFIG_AUFS_EXPORT
  13458. +#endif
  13459. +#endif
  13460. +
  13461. +#ifdef CONFIG_DEBUG_PROVE_LOCKING
  13462. +#if MAX_LOCKDEP_SUBCLASSES < AuLsc_End
  13463. +#warning lockdep will not work since aufs uses deeper locks.
  13464. +#endif
  13465. +#endif
  13466. +
  13467. +#ifdef CONFIG_AUFS_COMPAT
  13468. +#warning CONFIG_AUFS_COMPAT will be removed in the near future.
  13469. +#endif
  13470. +
  13471. +#endif
  13472. diff --git a/fs/aufs/module.h b/fs/aufs/module.h
  13473. new file mode 100755
  13474. index 0000000..3769861
  13475. --- /dev/null
  13476. +++ b/fs/aufs/module.h
  13477. @@ -0,0 +1,60 @@
  13478. +/*
  13479. + * Copyright (C) 2007 Junjiro Okajima
  13480. + *
  13481. + * This program, aufs is free software; you can redistribute it and/or modify
  13482. + * it under the terms of the GNU General Public License as published by
  13483. + * the Free Software Foundation; either version 2 of the License, or
  13484. + * (at your option) any later version.
  13485. + *
  13486. + * This program is distributed in the hope that it will be useful,
  13487. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13488. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13489. + * GNU General Public License for more details.
  13490. + *
  13491. + * You should have received a copy of the GNU General Public License
  13492. + * along with this program; if not, write to the Free Software
  13493. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  13494. + */
  13495. +
  13496. +/* $Id: module.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
  13497. +
  13498. +#ifndef __AUFS_MODULE_H__
  13499. +#define __AUFS_MODULE_H__
  13500. +
  13501. +#ifdef __KERNEL__
  13502. +
  13503. +#include <linux/slab.h>
  13504. +
  13505. +/* ---------------------------------------------------------------------- */
  13506. +
  13507. +/* module parameters */
  13508. +extern short aufs_nwkq;
  13509. +extern int sysaufs_brs;
  13510. +
  13511. +/* ---------------------------------------------------------------------- */
  13512. +
  13513. +extern char au_esc_chars[];
  13514. +extern int au_dir_roflags;
  13515. +
  13516. +/* kmem cache */
  13517. +enum {AuCache_DINFO, AuCache_ICNTNR, AuCache_FINFO, AuCache_VDIR,
  13518. + AuCache_DEHSTR, AuCache_HINOTIFY, AuCache_Last};
  13519. +extern struct kmem_cache *aufs_cachep[];
  13520. +
  13521. +#define CacheFuncs(name, index) \
  13522. +static inline void *cache_alloc_##name(void) \
  13523. +{return kmem_cache_alloc(aufs_cachep[index], GFP_KERNEL);} \
  13524. +static inline void cache_free_##name(void *p) \
  13525. +{kmem_cache_free(aufs_cachep[index], p);}
  13526. +
  13527. +CacheFuncs(dinfo, AuCache_DINFO);
  13528. +CacheFuncs(icntnr, AuCache_ICNTNR);
  13529. +CacheFuncs(finfo, AuCache_FINFO);
  13530. +CacheFuncs(vdir, AuCache_VDIR);
  13531. +CacheFuncs(dehstr, AuCache_DEHSTR);
  13532. +CacheFuncs(hinotify, AuCache_HINOTIFY);
  13533. +
  13534. +#undef CacheFuncs
  13535. +
  13536. +#endif /* __KERNEL__ */
  13537. +#endif /* __AUFS_MODULE_H__ */
  13538. diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c
  13539. new file mode 100755
  13540. index 0000000..c1a9445
  13541. --- /dev/null
  13542. +++ b/fs/aufs/opts.c
  13543. @@ -0,0 +1,1043 @@
  13544. +/*
  13545. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  13546. + *
  13547. + * This program, aufs is free software; you can redistribute it and/or modify
  13548. + * it under the terms of the GNU General Public License as published by
  13549. + * the Free Software Foundation; either version 2 of the License, or
  13550. + * (at your option) any later version.
  13551. + *
  13552. + * This program is distributed in the hope that it will be useful,
  13553. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13554. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13555. + * GNU General Public License for more details.
  13556. + *
  13557. + * You should have received a copy of the GNU General Public License
  13558. + * along with this program; if not, write to the Free Software
  13559. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  13560. + */
  13561. +
  13562. +/* $Id: opts.c,v 1.34 2007/05/14 03:40:27 sfjro Exp $ */
  13563. +
  13564. +#include <asm/types.h> // a distribution requires
  13565. +#include <linux/parser.h>
  13566. +#include "aufs.h"
  13567. +
  13568. +enum {
  13569. + Opt_br,
  13570. + Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
  13571. + Opt_idel, Opt_imod,
  13572. + Opt_dirwh, Opt_rdcache, Opt_deblk, Opt_nhash,
  13573. + Opt_xino, Opt_zxino, Opt_noxino,
  13574. + Opt_plink, Opt_noplink, Opt_list_plink, Opt_clean_plink,
  13575. + Opt_udba,
  13576. + Opt_diropq_a, Opt_diropq_w,
  13577. + Opt_warn_perm, Opt_nowarn_perm,
  13578. + Opt_findrw_dir, Opt_findrw_br,
  13579. + Opt_coo,
  13580. + Opt_dlgt, Opt_nodlgt,
  13581. + Opt_tail, Opt_ignore, Opt_err
  13582. +};
  13583. +
  13584. +static match_table_t options = {
  13585. + {Opt_br, "br=%s"},
  13586. + {Opt_br, "br:%s"},
  13587. +
  13588. + {Opt_add, "add=%d:%s"},
  13589. + {Opt_add, "add:%d:%s"},
  13590. + {Opt_add, "ins=%d:%s"},
  13591. + {Opt_add, "ins:%d:%s"},
  13592. + {Opt_append, "append=%s"},
  13593. + {Opt_append, "append:%s"},
  13594. + {Opt_prepend, "prepend=%s"},
  13595. + {Opt_prepend, "prepend:%s"},
  13596. +
  13597. + {Opt_del, "del=%s"},
  13598. + {Opt_del, "del:%s"},
  13599. + //{Opt_idel, "idel:%d"},
  13600. + {Opt_mod, "mod=%s"},
  13601. + {Opt_mod, "mod:%s"},
  13602. + //{Opt_imod, "imod:%d:%s"},
  13603. +
  13604. + {Opt_dirwh, "dirwh=%d"},
  13605. + {Opt_dirwh, "dirwh:%d"},
  13606. +
  13607. + {Opt_xino, "xino=%s"},
  13608. + {Opt_xino, "xino:%s"},
  13609. + {Opt_noxino, "noxino"},
  13610. + //{Opt_zxino, "zxino=%s"},
  13611. +
  13612. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
  13613. + {Opt_plink, "plink"},
  13614. + {Opt_noplink, "noplink"},
  13615. +#ifdef CONFIG_AUFS_DEBUG
  13616. + {Opt_list_plink, "list_plink"},
  13617. +#endif
  13618. + {Opt_clean_plink, "clean_plink"},
  13619. +#endif
  13620. +
  13621. + {Opt_udba, "udba=%s"},
  13622. +
  13623. + {Opt_diropq_a, "diropq=always"},
  13624. + {Opt_diropq_a, "diropq=a"},
  13625. + {Opt_diropq_w, "diropq=whiteouted"},
  13626. + {Opt_diropq_w, "diropq=w"},
  13627. +
  13628. + {Opt_warn_perm, "warn_perm"},
  13629. + {Opt_nowarn_perm, "nowarn_perm"},
  13630. +
  13631. +#ifdef CONFIG_AUFS_DLGT
  13632. + {Opt_dlgt, "dlgt"},
  13633. + {Opt_nodlgt, "nodlgt"},
  13634. +#endif
  13635. +
  13636. + {Opt_rdcache, "rdcache=%d"},
  13637. + {Opt_rdcache, "rdcache:%d"},
  13638. +#if 0
  13639. + {Opt_findrw_dir, "findrw=dir"},
  13640. + {Opt_findrw_br, "findrw=br"},
  13641. +
  13642. + {Opt_coo, "coo=%s"},
  13643. +
  13644. + {Opt_deblk, "deblk=%d"},
  13645. + {Opt_deblk, "deblk:%d"},
  13646. + {Opt_nhash, "nhash=%d"},
  13647. + {Opt_nhash, "nhash:%d"},
  13648. +#endif
  13649. +
  13650. + {Opt_br, "dirs=%s"},
  13651. + {Opt_ignore, "debug=%d"},
  13652. + {Opt_ignore, "delete=whiteout"},
  13653. + {Opt_ignore, "delete=all"},
  13654. + {Opt_ignore, "imap=%s"},
  13655. +
  13656. + {Opt_err, NULL}
  13657. +};
  13658. +
  13659. +/* ---------------------------------------------------------------------- */
  13660. +
  13661. +#define RW "rw"
  13662. +#define RO "ro"
  13663. +#define WH "wh"
  13664. +#define RR "rr"
  13665. +#define NoLinkWH "nolwh"
  13666. +
  13667. +static match_table_t brperms = {
  13668. + {AuBr_RR, RR},
  13669. + {AuBr_RO, RO},
  13670. + {AuBr_RW, RW},
  13671. +
  13672. + {AuBr_RRWH, RR "+" WH},
  13673. + {AuBr_ROWH, RO "+" WH},
  13674. + {AuBr_RWNoLinkWH, RW "+" NoLinkWH},
  13675. +
  13676. + {AuBr_ROWH, "nfsro"},
  13677. + {AuBr_RO, NULL}
  13678. +};
  13679. +
  13680. +static int br_perm_val(char *perm)
  13681. +{
  13682. + int val;
  13683. + substring_t args[MAX_OPT_ARGS];
  13684. +
  13685. + DEBUG_ON(!perm || !*perm);
  13686. + LKTRTrace("perm %s\n", perm);
  13687. + val = match_token(perm, brperms, args);
  13688. + TraceErr(val);
  13689. + return val;
  13690. +}
  13691. +
  13692. +int br_perm_str(char *p, unsigned int len, int brperm)
  13693. +{
  13694. + struct match_token *bp = brperms;
  13695. +
  13696. + LKTRTrace("len %d, 0x%x\n", len, brperm);
  13697. +
  13698. + while (bp->pattern) {
  13699. + if (bp->token == brperm) {
  13700. + if (strlen(bp->pattern) < len) {
  13701. + strcpy(p, bp->pattern);
  13702. + return 0;
  13703. + } else
  13704. + return -E2BIG;
  13705. + }
  13706. + bp++;
  13707. + }
  13708. +
  13709. + return -EIO;
  13710. +}
  13711. +
  13712. +/* ---------------------------------------------------------------------- */
  13713. +
  13714. +static match_table_t udbalevel = {
  13715. + {AuFlag_UDBA_REVAL, "reval"},
  13716. +#ifdef CONFIG_AUFS_HINOTIFY
  13717. + {AuFlag_UDBA_INOTIFY, "inotify"},
  13718. +#endif
  13719. + {AuFlag_UDBA_NONE, "none"},
  13720. + {-1, NULL}
  13721. +};
  13722. +
  13723. +static int udba_val(char *str)
  13724. +{
  13725. + substring_t args[MAX_OPT_ARGS];
  13726. + return match_token(str, udbalevel, args);
  13727. +}
  13728. +
  13729. +au_parser_pattern_t udba_str(int udba)
  13730. +{
  13731. + struct match_token *p = udbalevel;
  13732. + while (p->pattern) {
  13733. + if (p->token == udba)
  13734. + return p->pattern;
  13735. + p++;
  13736. + }
  13737. + BUG();
  13738. + return "??";
  13739. +}
  13740. +
  13741. +void udba_set(struct super_block *sb, unsigned int flg)
  13742. +{
  13743. + au_flag_clr(sb, AuMask_UDBA);
  13744. + au_flag_set(sb, flg);
  13745. +}
  13746. +
  13747. +/* ---------------------------------------------------------------------- */
  13748. +
  13749. +static match_table_t coolevel = {
  13750. + {AuFlag_COO_LEAF, "leaf"},
  13751. + {AuFlag_COO_ALL, "all"},
  13752. + {AuFlag_COO_NONE, "none"},
  13753. + {-1, NULL}
  13754. +};
  13755. +
  13756. +#if 0
  13757. +static int coo_val(char *str)
  13758. +{
  13759. + substring_t args[MAX_OPT_ARGS];
  13760. + return match_token(str, coolevel, args);
  13761. +}
  13762. +#endif
  13763. +
  13764. +au_parser_pattern_t coo_str(int coo)
  13765. +{
  13766. + struct match_token *p = coolevel;
  13767. + while (p->pattern) {
  13768. + if (p->token == coo)
  13769. + return p->pattern;
  13770. + p++;
  13771. + }
  13772. + BUG();
  13773. + return "??";
  13774. +}
  13775. +static void coo_set(struct super_block *sb, unsigned int flg)
  13776. +{
  13777. + au_flag_clr(sb, AuMask_COO);
  13778. + au_flag_set(sb, flg);
  13779. +}
  13780. +
  13781. +/* ---------------------------------------------------------------------- */
  13782. +
  13783. +static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
  13784. +
  13785. +#ifdef CONFIG_AUFS_DEBUG
  13786. +static void dump_opts(struct opts *opts)
  13787. +{
  13788. + /* reduce stack space */
  13789. + union {
  13790. + struct opt_add *add;
  13791. + struct opt_del *del;
  13792. + struct opt_mod *mod;
  13793. + struct opt_xino *xino;
  13794. + } u;
  13795. + struct opt *opt;
  13796. +
  13797. + TraceEnter();
  13798. +
  13799. + opt = opts->opt;
  13800. + while (/* opt < opts_tail && */ opt->type != Opt_tail) {
  13801. + switch (opt->type) {
  13802. + case Opt_add:
  13803. + u.add = &opt->add;
  13804. + LKTRTrace("add {b%d, %s, 0x%x, %p}\n",
  13805. + u.add->bindex, u.add->path, u.add->perm,
  13806. + u.add->nd.dentry);
  13807. + break;
  13808. + case Opt_del:
  13809. + case Opt_idel:
  13810. + u.del = &opt->del;
  13811. + LKTRTrace("del {%s, %p}\n", u.del->path, u.del->h_root);
  13812. + break;
  13813. + case Opt_mod:
  13814. + case Opt_imod:
  13815. + u.mod = &opt->mod;
  13816. + LKTRTrace("mod {%s, 0x%x, %p}\n",
  13817. + u.mod->path, u.mod->perm, u.mod->h_root);
  13818. + break;
  13819. + case Opt_append:
  13820. + u.add = &opt->add;
  13821. + LKTRTrace("append {b%d, %s, 0x%x, %p}\n",
  13822. + u.add->bindex, u.add->path, u.add->perm,
  13823. + u.add->nd.dentry);
  13824. + break;
  13825. + case Opt_prepend:
  13826. + u.add = &opt->add;
  13827. + LKTRTrace("prepend {b%d, %s, 0x%x, %p}\n",
  13828. + u.add->bindex, u.add->path, u.add->perm,
  13829. + u.add->nd.dentry);
  13830. + break;
  13831. + case Opt_dirwh:
  13832. + LKTRTrace("dirwh %d\n", opt->dirwh);
  13833. + break;
  13834. + case Opt_rdcache:
  13835. + LKTRTrace("rdcache %d\n", opt->rdcache);
  13836. + break;
  13837. + case Opt_xino:
  13838. + u.xino = &opt->xino;
  13839. + LKTRTrace("xino {%s %.*s}\n",
  13840. + u.xino->path, DLNPair(u.xino->file->f_dentry));
  13841. + break;
  13842. + case Opt_noxino:
  13843. + LKTRLabel(noxino);
  13844. + break;
  13845. + case Opt_plink:
  13846. + LKTRLabel(plink);
  13847. + break;
  13848. + case Opt_noplink:
  13849. + LKTRLabel(noplink);
  13850. + break;
  13851. + case Opt_list_plink:
  13852. + LKTRLabel(list_plink);
  13853. + break;
  13854. + case Opt_clean_plink:
  13855. + LKTRLabel(clean_plink);
  13856. + break;
  13857. + case Opt_udba:
  13858. + LKTRTrace("udba %d, %s\n",
  13859. + opt->udba, udba_str(opt->udba));
  13860. + break;
  13861. + case Opt_diropq_a:
  13862. + LKTRLabel(diropq_a);
  13863. + break;
  13864. + case Opt_diropq_w:
  13865. + LKTRLabel(diropq_w);
  13866. + break;
  13867. + case Opt_warn_perm:
  13868. + LKTRLabel(warn_perm);
  13869. + break;
  13870. + case Opt_nowarn_perm:
  13871. + LKTRLabel(nowarn_perm);
  13872. + break;
  13873. + case Opt_dlgt:
  13874. + LKTRLabel(dlgt);
  13875. + break;
  13876. + case Opt_nodlgt:
  13877. + LKTRLabel(nodlgt);
  13878. + break;
  13879. + case Opt_coo:
  13880. + LKTRTrace("coo %d, %s\n", opt->coo, coo_str(opt->coo));
  13881. + break;
  13882. + default:
  13883. + BUG();
  13884. + }
  13885. + opt++;
  13886. + }
  13887. +}
  13888. +#else
  13889. +#define dump_opts(opts) /* */
  13890. +#endif
  13891. +
  13892. +void au_free_opts(struct opts *opts)
  13893. +{
  13894. + struct opt *opt;
  13895. +
  13896. + TraceEnter();
  13897. +
  13898. + opt = opts->opt;
  13899. + while (opt->type != Opt_tail) {
  13900. + switch (opt->type) {
  13901. + case Opt_add:
  13902. + case Opt_append:
  13903. + case Opt_prepend:
  13904. + path_release(&opt->add.nd);
  13905. + break;
  13906. + case Opt_del:
  13907. + case Opt_idel:
  13908. + dput(opt->del.h_root);
  13909. + break;
  13910. + case Opt_mod:
  13911. + case Opt_imod:
  13912. + dput(opt->mod.h_root);
  13913. + break;
  13914. + case Opt_xino:
  13915. + fput(opt->xino.file);
  13916. + break;
  13917. + }
  13918. + opt++;
  13919. + }
  13920. +}
  13921. +
  13922. +static int opt_add(struct opt *opt, char *opt_str, struct super_block *sb,
  13923. + aufs_bindex_t bindex)
  13924. +{
  13925. + int err;
  13926. + struct opt_add *add = &opt->add;
  13927. + char *p;
  13928. +
  13929. + LKTRTrace("%s, b%d\n", opt_str, bindex);
  13930. +
  13931. + add->bindex = bindex;
  13932. + add->perm = AuBr_RO;
  13933. + if (!bindex && !(sb->s_flags & MS_RDONLY))
  13934. + add->perm = AuBr_RW;
  13935. +#ifdef CONFIG_AUFS_COMPAT
  13936. + add->perm = AuBr_RW;
  13937. +#endif
  13938. + add->path = opt_str;
  13939. + p = strchr(opt_str, '=');
  13940. + if (unlikely(p)) {
  13941. + *p++ = 0;
  13942. + if (*p)
  13943. + add->perm = br_perm_val(p);
  13944. + }
  13945. +
  13946. + // LSM may detect it
  13947. + // do not superio.
  13948. + err = path_lookup(add->path, lkup_dirflags, &add->nd);
  13949. + //err = -1;
  13950. + if (!err) {
  13951. + opt->type = Opt_add;
  13952. + goto out;
  13953. + }
  13954. + Err("lookup failed %s (%d)\n", add->path, err);
  13955. + err = -EINVAL;
  13956. +
  13957. + out:
  13958. + TraceErr(err);
  13959. + return err;
  13960. +}
  13961. +
  13962. +/* called without aufs lock */
  13963. +int au_parse_opts(struct super_block *sb, char *str, struct opts *opts)
  13964. +{
  13965. + int err, n;
  13966. + struct dentry *root;
  13967. + struct opt *opt, *opt_tail;
  13968. + char *opt_str;
  13969. + substring_t args[MAX_OPT_ARGS];
  13970. + aufs_bindex_t bindex;
  13971. + struct nameidata nd;
  13972. + /* reduce stack space */
  13973. + union {
  13974. + struct opt_del *del;
  13975. + struct opt_mod *mod;
  13976. + struct opt_xino *xino;
  13977. + } u;
  13978. + struct file *file;
  13979. +
  13980. + LKTRTrace("%s, nopts %d\n", str, opts->max_opt);
  13981. +
  13982. + root = sb->s_root;
  13983. + err = 0;
  13984. + bindex = 0;
  13985. + opt = opts->opt;
  13986. + opt_tail = opt + opts->max_opt - 1;
  13987. + opt->type = Opt_tail;
  13988. + while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
  13989. + int token, skipped;
  13990. + char *p;
  13991. + err = -EINVAL;
  13992. + token = match_token(opt_str, options, args);
  13993. + LKTRTrace("%s, token %d, args[0]{%p, %p}\n",
  13994. + opt_str, token, args[0].from, args[0].to);
  13995. +
  13996. + skipped = 0;
  13997. + switch (token) {
  13998. + case Opt_br:
  13999. + err = 0;
  14000. + while (!err && (opt_str = strsep(&args[0].from, ":"))
  14001. + && *opt_str) {
  14002. + err = opt_add(opt, opt_str, sb, bindex++);
  14003. + //if (LktrCond) err = -1;
  14004. + if (unlikely(!err && ++opt > opt_tail)) {
  14005. + err = -E2BIG;
  14006. + break;
  14007. + }
  14008. + opt->type = Opt_tail;
  14009. + skipped = 1;
  14010. + }
  14011. + break;
  14012. + case Opt_add:
  14013. + if (unlikely(match_int(&args[0], &n))) {
  14014. + Err("bad integer in %s\n", opt_str);
  14015. + break;
  14016. + }
  14017. + bindex = n;
  14018. + err = opt_add(opt, args[1].from, sb, bindex);
  14019. + break;
  14020. + case Opt_append:
  14021. + case Opt_prepend:
  14022. + err = opt_add(opt, args[0].from, sb, /*dummy bindex*/1);
  14023. + if (!err)
  14024. + opt->type = token;
  14025. + break;
  14026. + case Opt_del:
  14027. + u.del = &opt->del;
  14028. + u.del->path = args[0].from;
  14029. + LKTRTrace("del path %s\n", u.del->path);
  14030. + // LSM may detect it
  14031. + // do not superio.
  14032. + err = path_lookup(u.del->path, lkup_dirflags, &nd);
  14033. + if (unlikely(err)) {
  14034. + Err("lookup failed %s (%d)\n", u.del->path, err);
  14035. + break;
  14036. + }
  14037. + u.del->h_root = dget(nd.dentry);
  14038. + path_release(&nd);
  14039. + opt->type = token;
  14040. + break;
  14041. +#if 0
  14042. + case Opt_idel:
  14043. + u.del = &opt->del;
  14044. + u.del->path = "(indexed)";
  14045. + if (unlikely(match_int(&args[0], &n))) {
  14046. + Err("bad integer in %s\n", opt_str);
  14047. + break;
  14048. + }
  14049. + bindex = n;
  14050. + aufs_read_lock(root, !AUFS_I_RLOCK);
  14051. + if (bindex < 0 || sbend(sb) < bindex) {
  14052. + Err("out of bounds, %d\n", bindex);
  14053. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  14054. + break;
  14055. + }
  14056. + err = 0;
  14057. + u.del->h_root = dget(au_h_dptr_i(root, bindex));
  14058. + opt->type = token;
  14059. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  14060. + break;
  14061. +#endif
  14062. +
  14063. + case Opt_mod:
  14064. + u.mod = &opt->mod;
  14065. + u.mod->path = args[0].from;
  14066. + p = strchr(u.mod->path, '=');
  14067. + if (unlikely(!p)) {
  14068. + Err("no permssion %s\n", opt_str);
  14069. + break;
  14070. + }
  14071. + *p++ = 0;
  14072. + u.mod->perm = br_perm_val(p);
  14073. + LKTRTrace("mod path %s, perm 0x%x, %s\n",
  14074. + u.mod->path, u.mod->perm, p);
  14075. + // LSM may detect it
  14076. + // do not superio.
  14077. + err = path_lookup(u.mod->path, lkup_dirflags, &nd);
  14078. + if (unlikely(err)) {
  14079. + Err("lookup failed %s (%d)\n", u.mod->path, err);
  14080. + break;
  14081. + }
  14082. + u.mod->h_root = dget(nd.dentry);
  14083. + path_release(&nd);
  14084. + opt->type = token;
  14085. + break;
  14086. +#if 0
  14087. + case Opt_imod:
  14088. + u.mod = &opt->mod;
  14089. + u.mod->path = "(indexed)";
  14090. + if (unlikely(match_int(&args[0], &n))) {
  14091. + Err("bad integer in %s\n", opt_str);
  14092. + break;
  14093. + }
  14094. + bindex = n;
  14095. + aufs_read_lock(root, !AUFS_I_RLOCK);
  14096. + if (bindex < 0 || sbend(sb) < bindex) {
  14097. + Err("out of bounds, %d\n", bindex);
  14098. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  14099. + break;
  14100. + }
  14101. + u.mod->perm = br_perm_val(args[1].from);
  14102. + LKTRTrace("mod path %s, perm 0x%x, %s\n",
  14103. + u.mod->path, u.mod->perm, args[1].from);
  14104. + err = 0;
  14105. + u.mod->h_root = dget(au_h_dptr_i(root, bindex));
  14106. + opt->type = token;
  14107. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  14108. + break;
  14109. +#endif
  14110. + case Opt_xino:
  14111. + u.xino = &opt->xino;
  14112. + file = xino_create(sb, args[0].from, /*silent*/0,
  14113. + /*parent*/NULL);
  14114. + err = PTR_ERR(file);
  14115. + if (IS_ERR(file))
  14116. + break;
  14117. + err = -EINVAL;
  14118. + if (unlikely(file->f_dentry->d_sb == sb)) {
  14119. + fput(file);
  14120. + Err("%s must be outside\n", args[0].from);
  14121. + break;
  14122. + }
  14123. + err = 0;
  14124. + u.xino->file = file;
  14125. + u.xino->path = args[0].from;
  14126. + opt->type = token;
  14127. + break;
  14128. +
  14129. + case Opt_dirwh:
  14130. + if (unlikely(match_int(&args[0], &opt->dirwh)))
  14131. + break;
  14132. + err = 0;
  14133. + opt->type = token;
  14134. + break;
  14135. +
  14136. + case Opt_rdcache:
  14137. + if (unlikely(match_int(&args[0], &opt->rdcache)))
  14138. + break;
  14139. + err = 0;
  14140. + opt->type = token;
  14141. + break;
  14142. +
  14143. + case Opt_noxino:
  14144. + case Opt_plink:
  14145. + case Opt_noplink:
  14146. + case Opt_list_plink:
  14147. + case Opt_clean_plink:
  14148. + case Opt_diropq_a:
  14149. + case Opt_diropq_w:
  14150. + case Opt_warn_perm:
  14151. + case Opt_nowarn_perm:
  14152. + case Opt_dlgt:
  14153. + case Opt_nodlgt:
  14154. + err = 0;
  14155. + opt->type = token;
  14156. + break;
  14157. +
  14158. + case Opt_udba:
  14159. + opt->udba = udba_val(args[0].from);
  14160. + if (opt->udba >= 0) {
  14161. + err = 0;
  14162. + opt->type = token;
  14163. + }
  14164. + break;
  14165. +
  14166. +#if 0
  14167. + case Opt_coo:
  14168. + opt->coo = coo_val(args[0].from);
  14169. + if (opt->coo >= 0) {
  14170. + err = 0;
  14171. + opt->type = token;
  14172. + }
  14173. + break;
  14174. +#endif
  14175. +
  14176. + case Opt_ignore:
  14177. +#ifndef CONFIG_AUFS_COMPAT
  14178. + Warn("ignored %s\n", opt_str);
  14179. +#endif
  14180. + skipped = 1;
  14181. + err = 0;
  14182. + break;
  14183. + case Opt_err:
  14184. + Err("unknown option %s\n", opt_str);
  14185. + break;
  14186. + }
  14187. +
  14188. + if (!err && !skipped) {
  14189. + if (unlikely(++opt > opt_tail)) {
  14190. + err = -E2BIG;
  14191. + opt--;
  14192. + opt->type = Opt_tail;
  14193. + break;
  14194. + }
  14195. + opt->type = Opt_tail;
  14196. + }
  14197. + }
  14198. +
  14199. + dump_opts(opts);
  14200. + if (unlikely(err))
  14201. + au_free_opts(opts);
  14202. + TraceErr(err);
  14203. + return err;
  14204. +}
  14205. +
  14206. +/*
  14207. + * returns,
  14208. + * plus: processed without an error
  14209. + * zero: unprocessed
  14210. + */
  14211. +static int au_do_opt_simple(struct super_block *sb, struct opt *opt,
  14212. + int remount, unsigned int *given)
  14213. +{
  14214. + int err;
  14215. + struct aufs_sbinfo *sbinfo = stosi(sb);
  14216. +
  14217. + TraceEnter();
  14218. +
  14219. + err = 1; /* handled */
  14220. + switch (opt->type) {
  14221. + case Opt_udba:
  14222. + udba_set(sb, opt->udba);
  14223. + *given |= opt->udba;
  14224. + break;
  14225. +
  14226. + case Opt_plink:
  14227. + au_flag_set(sb, AuFlag_PLINK);
  14228. + *given |= AuFlag_PLINK;
  14229. + break;
  14230. + case Opt_noplink:
  14231. + if (au_flag_test(sb, AuFlag_PLINK))
  14232. + au_put_plink(sb);
  14233. + au_flag_clr(sb, AuFlag_PLINK);
  14234. + *given |= AuFlag_PLINK;
  14235. + break;
  14236. + case Opt_list_plink:
  14237. + if (au_flag_test(sb, AuFlag_PLINK))
  14238. + au_list_plink(sb);
  14239. + break;
  14240. + case Opt_clean_plink:
  14241. + if (au_flag_test(sb, AuFlag_PLINK))
  14242. + au_put_plink(sb);
  14243. + break;
  14244. +
  14245. + case Opt_diropq_a:
  14246. + au_flag_set(sb, AuFlag_ALWAYS_DIROPQ);
  14247. + *given |= AuFlag_ALWAYS_DIROPQ;
  14248. + break;
  14249. + case Opt_diropq_w:
  14250. + au_flag_clr(sb, AuFlag_ALWAYS_DIROPQ);
  14251. + *given |= AuFlag_ALWAYS_DIROPQ;
  14252. + break;
  14253. +
  14254. + case Opt_dlgt:
  14255. + au_flag_set(sb, AuFlag_DLGT);
  14256. + *given |= AuFlag_DLGT;
  14257. + break;
  14258. + case Opt_nodlgt:
  14259. + au_flag_clr(sb, AuFlag_DLGT);
  14260. + *given |= AuFlag_DLGT;
  14261. + break;
  14262. +
  14263. + case Opt_warn_perm:
  14264. + au_flag_set(sb, AuFlag_WARN_PERM);
  14265. + *given |= AuFlag_WARN_PERM;
  14266. + break;
  14267. + case Opt_nowarn_perm:
  14268. + au_flag_clr(sb, AuFlag_WARN_PERM);
  14269. + *given |= AuFlag_WARN_PERM;
  14270. + break;
  14271. +
  14272. + case Opt_coo:
  14273. + coo_set(sb, opt->coo);
  14274. + *given |= opt->coo;
  14275. + break;
  14276. +
  14277. + case Opt_dirwh:
  14278. + sbinfo->si_dirwh = opt->dirwh;
  14279. + break;
  14280. +
  14281. + case Opt_rdcache:
  14282. + sbinfo->si_rdcache = opt->rdcache * HZ;
  14283. + break;
  14284. +
  14285. + default:
  14286. + err = 0;
  14287. + break;
  14288. + }
  14289. +
  14290. + TraceErr(err);
  14291. + return err;
  14292. +}
  14293. +
  14294. +/*
  14295. + * returns tri-state.
  14296. + * plus: processed without an error
  14297. + * zero: unprocessed
  14298. + * minus: error
  14299. + */
  14300. +static int au_do_opt_br(struct super_block *sb, struct opt *opt, int remount,
  14301. + int *do_refresh)
  14302. +{
  14303. + int err;
  14304. +
  14305. + TraceEnter();
  14306. +
  14307. + err = 0;
  14308. + switch (opt->type) {
  14309. + case Opt_append:
  14310. + opt->add.bindex = sbend(sb) + 1;
  14311. + goto add;
  14312. + case Opt_prepend:
  14313. + opt->add.bindex = 0;
  14314. + add:
  14315. + case Opt_add:
  14316. + err = br_add(sb, &opt->add, remount);
  14317. + if (!err)
  14318. + *do_refresh = err = 1;
  14319. + break;
  14320. +
  14321. + case Opt_del:
  14322. + case Opt_idel:
  14323. + err = br_del(sb, &opt->del, remount);
  14324. + if (!err)
  14325. + *do_refresh = err = 1;
  14326. + break;
  14327. +
  14328. + case Opt_mod:
  14329. + case Opt_imod:
  14330. + err = br_mod(sb, &opt->mod, remount, do_refresh);
  14331. + if (!err)
  14332. + err = 1;
  14333. + break;
  14334. + }
  14335. +
  14336. + TraceErr(err);
  14337. + return err;
  14338. +}
  14339. +
  14340. +static int au_do_opt_xino(struct super_block *sb, struct opt *opt, int remount,
  14341. + struct opt_xino **opt_xino)
  14342. +{
  14343. + int err;
  14344. +
  14345. + TraceEnter();
  14346. +
  14347. + err = 0;
  14348. + switch (opt->type) {
  14349. + case Opt_xino:
  14350. + err = xino_set(sb, &opt->xino, remount);
  14351. + if (!err)
  14352. + *opt_xino = &opt->xino;
  14353. + break;
  14354. + case Opt_noxino:
  14355. + err = xino_clr(sb);
  14356. + break;
  14357. + }
  14358. +
  14359. + TraceErr(err);
  14360. + return err;
  14361. +}
  14362. +
  14363. +static int verify_opts(struct super_block *sb, int remount)
  14364. +{
  14365. + int err;
  14366. + aufs_bindex_t bindex, bend;
  14367. + struct aufs_branch *br;
  14368. + struct dentry *root;
  14369. + struct inode *dir;
  14370. + unsigned int do_plink;
  14371. +
  14372. + TraceEnter();
  14373. +
  14374. + if (unlikely(!(sb->s_flags & MS_RDONLY)
  14375. + && !br_writable(sbr_perm(sb, 0))))
  14376. + Warn("first branch should be rw\n");
  14377. +
  14378. + err = 0;
  14379. + root = sb->s_root;
  14380. + dir = sb->s_root->d_inode;
  14381. + do_plink = au_flag_test(sb, AuFlag_PLINK);
  14382. + bend = sbend(sb);
  14383. + for (bindex = 0; !err && bindex <= bend; bindex++) {
  14384. + struct inode *h_dir;
  14385. + int skip;
  14386. +
  14387. + skip = 0;
  14388. + h_dir = au_h_iptr_i(dir, bindex);
  14389. + br = stobr(sb, bindex);
  14390. + br_wh_read_lock(br);
  14391. + switch (br->br_perm) {
  14392. + case AuBr_RR:
  14393. + case AuBr_RO:
  14394. + case AuBr_RRWH:
  14395. + case AuBr_ROWH:
  14396. + skip = (!br->br_wh && !br->br_plink);
  14397. + break;
  14398. +
  14399. + case AuBr_RWNoLinkWH:
  14400. + skip = !br->br_wh;
  14401. + if (skip) {
  14402. + if (do_plink)
  14403. + skip = !!br->br_plink;
  14404. + else
  14405. + skip = !br->br_plink;
  14406. + }
  14407. + break;
  14408. +
  14409. + case AuBr_RW:
  14410. + skip = !!br->br_wh;
  14411. + if (skip) {
  14412. + if (do_plink)
  14413. + skip = !!br->br_plink;
  14414. + else
  14415. + skip = !br->br_plink;
  14416. + }
  14417. + break;
  14418. +
  14419. + default:
  14420. + BUG();
  14421. + }
  14422. + br_wh_read_unlock(br);
  14423. +
  14424. + if (skip)
  14425. + continue;
  14426. +
  14427. + hdir_lock(h_dir, dir, bindex);
  14428. + br_wh_write_lock(br);
  14429. + err = init_wh(au_h_dptr_i(root, bindex), br,
  14430. + au_nfsmnt(sb, bindex), sb);
  14431. + br_wh_write_unlock(br);
  14432. + hdir_unlock(h_dir, dir, bindex);
  14433. + }
  14434. +
  14435. + TraceErr(err);
  14436. + return err;
  14437. +}
  14438. +
  14439. +int au_do_opts_mount(struct super_block *sb, struct opts *opts)
  14440. +{
  14441. + int err, do_refresh;
  14442. + struct inode *dir;
  14443. + struct opt *opt;
  14444. + unsigned int flags, given;
  14445. + struct opt_xino *opt_xino;
  14446. + aufs_bindex_t bend, bindex;
  14447. +
  14448. + TraceEnter();
  14449. + SiMustWriteLock(sb);
  14450. + DiMustWriteLock(sb->s_root);
  14451. + dir = sb->s_root->d_inode;
  14452. + IiMustWriteLock(dir);
  14453. +
  14454. + err = 0;
  14455. + given = 0;
  14456. + opt_xino = NULL;
  14457. + opt = opts->opt;
  14458. + while (err >= 0 && opt->type != Opt_tail)
  14459. + err = au_do_opt_simple(sb, opt++, /*remount*/0, &given);
  14460. + if (err > 0)
  14461. + err = 0;
  14462. + else if (unlikely(err < 0))
  14463. + goto out;
  14464. +
  14465. + /* disable them temporary */
  14466. + flags = au_flag_test(sb, AuFlag_XINO | AuMask_UDBA | AuFlag_DLGT);
  14467. + au_flag_clr(sb, AuFlag_XINO | AuFlag_DLGT);
  14468. + udba_set(sb, AuFlag_UDBA_REVAL);
  14469. +
  14470. + do_refresh = 0;
  14471. + opt = opts->opt;
  14472. + while (err >= 0 && opt->type != Opt_tail)
  14473. + err = au_do_opt_br(sb, opt++, /*remount*/0, &do_refresh);
  14474. + if (err > 0)
  14475. + err = 0;
  14476. + else if (unlikely(err < 0))
  14477. + goto out;
  14478. +
  14479. + bend = sbend(sb);
  14480. + if (unlikely(bend < 0)) {
  14481. + err = -EINVAL;
  14482. + Err("no branches\n");
  14483. + goto out;
  14484. + }
  14485. +
  14486. + if (flags & AuFlag_XINO)
  14487. + au_flag_set(sb, AuFlag_XINO);
  14488. + opt = opts->opt;
  14489. + while (!err && opt->type != Opt_tail)
  14490. + err = au_do_opt_xino(sb, opt++, /*remount*/0, &opt_xino);
  14491. + if (unlikely(err))
  14492. + goto out;
  14493. +
  14494. + //todo: test this error case.
  14495. + err = verify_opts(sb, /*remount*/0);
  14496. + DEBUG_ON(err);
  14497. + if (unlikely(err))
  14498. + goto out;
  14499. +
  14500. + /* enable xino */
  14501. + if (au_flag_test(sb, AuFlag_XINO) && !opt_xino) {
  14502. + struct file *xino_file = xino_def(sb);
  14503. + err = PTR_ERR(xino_file);
  14504. + if (IS_ERR(xino_file))
  14505. + goto out;
  14506. +
  14507. + err = 0;
  14508. + for (bindex = 0; !err && bindex <= bend; bindex++)
  14509. + err = xino_init(sb, bindex, xino_file,
  14510. + /*do_test*/bindex);
  14511. + fput(xino_file);
  14512. + if (unlikely(err))
  14513. + goto out;
  14514. + }
  14515. +
  14516. + /* restore hinotify */
  14517. + udba_set(sb, flags & AuMask_UDBA);
  14518. + if (flags & AuFlag_UDBA_INOTIFY)
  14519. + au_reset_hinotify(dir, au_hi_flags(dir, 1) & ~AUFS_HI_XINO);
  14520. +
  14521. + /* restore dlgt */
  14522. + if (flags & AuFlag_DLGT)
  14523. + au_flag_set(sb, AuFlag_DLGT);
  14524. +
  14525. + out:
  14526. + TraceErr(err);
  14527. + return err;
  14528. +}
  14529. +
  14530. +int au_do_opts_remount(struct super_block *sb, struct opts *opts,
  14531. + int *do_refresh, unsigned int *given)
  14532. +{
  14533. + int err, rerr;
  14534. + struct inode *dir;
  14535. + struct opt_xino *opt_xino;
  14536. + struct opt *opt;
  14537. + unsigned int dlgt;
  14538. +
  14539. + TraceEnter();
  14540. + SiMustWriteLock(sb);
  14541. + DiMustWriteLock(sb->s_root);
  14542. + dir = sb->s_root->d_inode;
  14543. + IiMustWriteLock(dir);
  14544. + //DEBUG_ON(au_flag_test(sb, AuFlag_UDBA_INOTIFY));
  14545. +
  14546. + err = 0;
  14547. + *do_refresh = 0;
  14548. + *given = 0;
  14549. + dlgt = au_flag_test(sb, AuFlag_DLGT);
  14550. + opt_xino = NULL;
  14551. + opt = opts->opt;
  14552. + while (err >= 0 && opt->type != Opt_tail) {
  14553. + err = au_do_opt_simple(sb, opt, /*remount*/1, given);
  14554. +
  14555. + /* disable it temporary */
  14556. + dlgt = au_flag_test(sb, AuFlag_DLGT);
  14557. + au_flag_clr(sb, AuFlag_DLGT);
  14558. +
  14559. + if (!err)
  14560. + err = au_do_opt_br(sb, opt, /*remount*/1, do_refresh);
  14561. + if (!err)
  14562. + err = au_do_opt_xino(sb, opt, /*remount*/1, &opt_xino);
  14563. +
  14564. + /* restore it */
  14565. + au_flag_set(sb, dlgt);
  14566. + opt++;
  14567. + }
  14568. + if (err > 0)
  14569. + err = 0;
  14570. + TraceErr(err);
  14571. +
  14572. + /* go on if err */
  14573. +
  14574. + //todo: test this error case.
  14575. + au_flag_clr(sb, AuFlag_DLGT);
  14576. + rerr = verify_opts(sb, /*remount*/1);
  14577. + au_flag_set(sb, dlgt);
  14578. +
  14579. + /* they are handled by the caller */
  14580. + if (!*do_refresh)
  14581. + *do_refresh = !!((*given & AuMask_UDBA)
  14582. + || au_flag_test(sb, AuFlag_XINO));
  14583. +
  14584. + TraceErr(err);
  14585. + return err;
  14586. +}
  14587. diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h
  14588. new file mode 100755
  14589. index 0000000..16c1a6a
  14590. --- /dev/null
  14591. +++ b/fs/aufs/opts.h
  14592. @@ -0,0 +1,96 @@
  14593. +/*
  14594. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  14595. + *
  14596. + * This program, aufs is free software; you can redistribute it and/or modify
  14597. + * it under the terms of the GNU General Public License as published by
  14598. + * the Free Software Foundation; either version 2 of the License, or
  14599. + * (at your option) any later version.
  14600. + *
  14601. + * This program is distributed in the hope that it will be useful,
  14602. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14603. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14604. + * GNU General Public License for more details.
  14605. + *
  14606. + * You should have received a copy of the GNU General Public License
  14607. + * along with this program; if not, write to the Free Software
  14608. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  14609. + */
  14610. +
  14611. +/* $Id: opts.h,v 1.13 2007/05/14 06:27:18 sfjro Exp $ */
  14612. +
  14613. +#ifndef __AUFS_OPTS_H__
  14614. +#define __AUFS_OPTS_H__
  14615. +
  14616. +#ifdef __KERNEL__
  14617. +
  14618. +#include <linux/fs.h>
  14619. +#include <linux/namei.h>
  14620. +#include <linux/version.h>
  14621. +#include <linux/aufs_type.h>
  14622. +
  14623. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
  14624. +typedef const char* au_parser_pattern_t;
  14625. +#else
  14626. +typedef char* au_parser_pattern_t;
  14627. +#endif
  14628. +
  14629. +/* ---------------------------------------------------------------------- */
  14630. +
  14631. +struct opt_add {
  14632. + aufs_bindex_t bindex;
  14633. + char *path;
  14634. + int perm;
  14635. + struct nameidata nd;
  14636. +};
  14637. +
  14638. +struct opt_del {
  14639. + char *path;
  14640. + struct dentry *h_root;
  14641. +};
  14642. +
  14643. +struct opt_mod {
  14644. + char *path;
  14645. + int perm;
  14646. + struct dentry *h_root;
  14647. +};
  14648. +
  14649. +struct opt_xino {
  14650. + char *path;
  14651. + struct file *file;
  14652. +};
  14653. +
  14654. +struct opt {
  14655. + int type;
  14656. + union {
  14657. + struct opt_xino xino;
  14658. + struct opt_add add;
  14659. + struct opt_del del;
  14660. + struct opt_mod mod;
  14661. + int dirwh;
  14662. + int rdcache;
  14663. + int deblk;
  14664. + int nhash;
  14665. + int udba;
  14666. + int coo;
  14667. + };
  14668. +};
  14669. +
  14670. +struct opts {
  14671. + struct opt *opt;
  14672. + int max_opt;
  14673. +};
  14674. +
  14675. +/* ---------------------------------------------------------------------- */
  14676. +
  14677. +int br_perm_str(char *p, unsigned int len, int brperm);
  14678. +au_parser_pattern_t udba_str(int udba);
  14679. +void udba_set(struct super_block *sb, unsigned int flg);
  14680. +//au_parser_pattern_t coo_str(int coo);
  14681. +void au_free_opts(struct opts *opts);
  14682. +int au_parse_opts(struct super_block *sb, char *str, struct opts *opts);
  14683. +int au_do_opts_mount(struct super_block *sb, struct opts *opts);
  14684. +int au_do_opts_remount(struct super_block *sb, struct opts *opts,
  14685. + int *do_refresh, unsigned int *given);
  14686. +
  14687. +#endif /* __KERNEL__ */
  14688. +#endif /* __AUFS_OPTS_H__ */
  14689. diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c
  14690. new file mode 100755
  14691. index 0000000..0e520af
  14692. --- /dev/null
  14693. +++ b/fs/aufs/plink.c
  14694. @@ -0,0 +1,331 @@
  14695. +/*
  14696. + * Copyright (C) 2007 Junjiro Okajima
  14697. + *
  14698. + * This program, aufs is free software; you can redistribute it and/or modify
  14699. + * it under the terms of the GNU General Public License as published by
  14700. + * the Free Software Foundation; either version 2 of the License, or
  14701. + * (at your option) any later version.
  14702. + *
  14703. + * This program is distributed in the hope that it will be useful,
  14704. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14705. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14706. + * GNU General Public License for more details.
  14707. + *
  14708. + * You should have received a copy of the GNU General Public License
  14709. + * along with this program; if not, write to the Free Software
  14710. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  14711. + */
  14712. +
  14713. +/* $Id: plink.c,v 1.4 2007/05/14 03:39:10 sfjro Exp $ */
  14714. +
  14715. +#include "aufs.h"
  14716. +
  14717. +struct pseudo_link {
  14718. + struct list_head list;
  14719. + struct inode *inode;
  14720. +};
  14721. +
  14722. +#ifdef CONFIG_AUFS_DEBUG
  14723. +void au_list_plink(struct super_block *sb)
  14724. +{
  14725. + struct aufs_sbinfo *sbinfo;
  14726. + struct list_head *plink_list;
  14727. + struct pseudo_link *plink;
  14728. +
  14729. + TraceEnter();
  14730. + SiMustAnyLock(sb);
  14731. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14732. +
  14733. + sbinfo = stosi(sb);
  14734. + plink_list = &sbinfo->si_plink;
  14735. + spin_lock(&sbinfo->si_plink_lock);
  14736. + list_for_each_entry(plink, plink_list, list)
  14737. + Dbg("%lu\n", plink->inode->i_ino);
  14738. + spin_unlock(&sbinfo->si_plink_lock);
  14739. +}
  14740. +#endif
  14741. +
  14742. +int au_is_plinked(struct super_block *sb, struct inode *inode)
  14743. +{
  14744. + int found;
  14745. + struct aufs_sbinfo *sbinfo;
  14746. + struct list_head *plink_list;
  14747. + struct pseudo_link *plink;
  14748. +
  14749. + LKTRTrace("i%lu\n", inode->i_ino);
  14750. + SiMustAnyLock(sb);
  14751. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14752. +
  14753. + found = 0;
  14754. + sbinfo = stosi(sb);
  14755. + plink_list = &sbinfo->si_plink;
  14756. + spin_lock(&sbinfo->si_plink_lock);
  14757. + list_for_each_entry(plink, plink_list, list)
  14758. + if (plink->inode == inode) {
  14759. + found = 1;
  14760. + break;
  14761. + }
  14762. + spin_unlock(&sbinfo->si_plink_lock);
  14763. + return found;
  14764. +}
  14765. +
  14766. +// 20 is max digits length of ulong 64
  14767. +#define PLINK_NAME_LEN ((20 + 1) * 2)
  14768. +
  14769. +static int plink_name(char *name, int len, struct inode *inode,
  14770. + aufs_bindex_t bindex)
  14771. +{
  14772. + int rlen;
  14773. + struct inode *h_inode;
  14774. +
  14775. + LKTRTrace("i%lu, b%d\n", inode->i_ino, bindex);
  14776. + DEBUG_ON(len != PLINK_NAME_LEN);
  14777. + h_inode = au_h_iptr_i(inode, bindex);
  14778. + DEBUG_ON(!h_inode);
  14779. + rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
  14780. + DEBUG_ON(rlen >= len);
  14781. + return rlen;
  14782. +}
  14783. +
  14784. +struct dentry *lkup_plink(struct super_block *sb, aufs_bindex_t bindex,
  14785. + struct inode *inode)
  14786. +{
  14787. + struct dentry *h_dentry, *h_parent;
  14788. + struct aufs_branch *br;
  14789. + struct inode *h_dir;
  14790. + char tgtname[PLINK_NAME_LEN];
  14791. + int len;
  14792. + struct lkup_args lkup;
  14793. +
  14794. + LKTRTrace("b%d, i%lu\n", bindex, inode->i_ino);
  14795. + br = stobr(sb, bindex);
  14796. + h_parent = br->br_plink;
  14797. + DEBUG_ON(!h_parent);
  14798. + h_dir = h_parent->d_inode;
  14799. + DEBUG_ON(!h_dir);
  14800. +
  14801. + len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
  14802. +
  14803. + // always superio.
  14804. + lkup.nfsmnt = au_do_nfsmnt(br->br_mnt);
  14805. + lkup.dlgt = need_dlgt(sb);
  14806. + hi_lock_whplink(h_dir);
  14807. + h_dentry = sio_lkup_one(tgtname, h_parent, len, &lkup);
  14808. + i_unlock(h_dir);
  14809. + return h_dentry;
  14810. +}
  14811. +
  14812. +static int do_whplink(char *tgt, int len, struct dentry *h_parent,
  14813. + struct dentry *h_dentry, struct vfsmount *nfsmnt,
  14814. + struct super_block *sb)
  14815. +{
  14816. + int err;
  14817. + struct dentry *h_tgt;
  14818. + struct inode *h_dir;
  14819. + struct lkup_args lkup = {
  14820. + .nfsmnt = nfsmnt,
  14821. + .dlgt = need_dlgt(sb)
  14822. + };
  14823. +
  14824. + h_tgt = lkup_one(tgt, h_parent, len, &lkup);
  14825. + err = PTR_ERR(h_tgt);
  14826. + if (IS_ERR(h_tgt))
  14827. + goto out;
  14828. +
  14829. + err = 0;
  14830. + h_dir = h_parent->d_inode;
  14831. + if (unlikely(h_tgt->d_inode && h_tgt->d_inode != h_dentry->d_inode))
  14832. + err = vfsub_unlink(h_dir, h_tgt, lkup.dlgt);
  14833. + if (!err && !h_tgt->d_inode) {
  14834. + err = vfsub_link(h_dentry, h_dir, h_tgt, lkup.dlgt);
  14835. + //inode->i_nlink++;
  14836. + }
  14837. + dput(h_tgt);
  14838. +
  14839. + out:
  14840. + TraceErr(err);
  14841. + return err;
  14842. +}
  14843. +
  14844. +struct do_whplink_args {
  14845. + int *errp;
  14846. + char *tgt;
  14847. + int len;
  14848. + struct dentry *h_parent;
  14849. + struct dentry *h_dentry;
  14850. + struct vfsmount *nfsmnt;
  14851. + struct super_block *sb;
  14852. +};
  14853. +
  14854. +static void call_do_whplink(void *args)
  14855. +{
  14856. + struct do_whplink_args *a = args;
  14857. + *a->errp = do_whplink(a->tgt, a->len, a->h_parent, a->h_dentry,
  14858. + a->nfsmnt, a->sb);
  14859. +}
  14860. +
  14861. +static int whplink(struct dentry *h_dentry, struct inode *inode,
  14862. + aufs_bindex_t bindex, struct super_block *sb)
  14863. +{
  14864. + int err, len;
  14865. + struct aufs_branch *br;
  14866. + struct dentry *h_parent;
  14867. + struct inode *h_dir;
  14868. + char tgtname[PLINK_NAME_LEN];
  14869. +
  14870. + LKTRTrace("%.*s\n", DLNPair(h_dentry));
  14871. + br = stobr(inode->i_sb, bindex);
  14872. + h_parent = br->br_plink;
  14873. + DEBUG_ON(!h_parent);
  14874. + h_dir = h_parent->d_inode;
  14875. + DEBUG_ON(!h_dir);
  14876. +
  14877. + len = plink_name(tgtname, sizeof(tgtname), inode, bindex);
  14878. +
  14879. + // always superio.
  14880. + hi_lock_whplink(h_dir);
  14881. + if (!is_au_wkq(current)) {
  14882. + struct do_whplink_args args = {
  14883. + .errp = &err,
  14884. + .tgt = tgtname,
  14885. + .len = len,
  14886. + .h_parent = h_parent,
  14887. + .h_dentry = h_dentry,
  14888. + .nfsmnt = au_do_nfsmnt(br->br_mnt),
  14889. + .sb = sb
  14890. + };
  14891. + au_wkq_wait(call_do_whplink, &args, /*dlgt*/0);
  14892. + } else
  14893. + err = do_whplink(tgtname, len, h_parent, h_dentry,
  14894. + au_do_nfsmnt(br->br_mnt), sb);
  14895. + i_unlock(h_dir);
  14896. +
  14897. + TraceErr(err);
  14898. + return err;
  14899. +}
  14900. +
  14901. +void append_plink(struct super_block *sb, struct inode *inode,
  14902. + struct dentry *h_dentry, aufs_bindex_t bindex)
  14903. +{
  14904. + struct aufs_sbinfo *sbinfo;
  14905. + struct list_head *plink_list;
  14906. + struct pseudo_link *plink;
  14907. + int found, err, cnt;
  14908. +
  14909. + LKTRTrace("i%lu\n", inode->i_ino);
  14910. + SiMustAnyLock(sb);
  14911. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14912. +
  14913. + cnt = 0;
  14914. + found = 0;
  14915. + sbinfo = stosi(sb);
  14916. + plink_list = &sbinfo->si_plink;
  14917. + spin_lock(&sbinfo->si_plink_lock);
  14918. + list_for_each_entry(plink, plink_list, list) {
  14919. + cnt++;
  14920. + if (plink->inode == inode) {
  14921. + found = 1;
  14922. + break;
  14923. + }
  14924. + }
  14925. +
  14926. + err = 0;
  14927. + if (!found) {
  14928. + struct pseudo_link *plink;
  14929. +
  14930. + plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
  14931. + if (plink) {
  14932. + plink->inode = igrab(inode);
  14933. + list_add(&plink->list, plink_list);
  14934. + cnt++;
  14935. + } else
  14936. + err = -ENOMEM;
  14937. + }
  14938. + spin_unlock(&sbinfo->si_plink_lock);
  14939. +
  14940. + if (!err)
  14941. + err = whplink(h_dentry, inode, bindex, sb);
  14942. +
  14943. + if (unlikely(cnt > 100))
  14944. + Warn1("unexpectedly many pseudo links, %d\n", cnt);
  14945. + if (unlikely(err))
  14946. + Warn("err %d, damaged pseudo link. ignored.\n", err);
  14947. +}
  14948. +
  14949. +static void do_put_plink(struct pseudo_link *plink, int do_del)
  14950. +{
  14951. + TraceEnter();
  14952. +
  14953. + iput(plink->inode);
  14954. + if (do_del)
  14955. + list_del(&plink->list);
  14956. + kfree(plink);
  14957. +}
  14958. +
  14959. +void au_put_plink(struct super_block *sb)
  14960. +{
  14961. + struct aufs_sbinfo *sbinfo;
  14962. + struct list_head *plink_list;
  14963. + struct pseudo_link *plink, *tmp;
  14964. +
  14965. + TraceEnter();
  14966. + SiMustWriteLock(sb);
  14967. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14968. +
  14969. + sbinfo = stosi(sb);
  14970. + plink_list = &sbinfo->si_plink;
  14971. + //spin_lock(&sbinfo->si_plink_lock);
  14972. + list_for_each_entry_safe(plink, tmp, plink_list, list)
  14973. + do_put_plink(plink, 0);
  14974. + INIT_LIST_HEAD(plink_list);
  14975. + //spin_unlock(&sbinfo->si_plink_lock);
  14976. +}
  14977. +
  14978. +void half_refresh_plink(struct super_block *sb, aufs_bindex_t br_id)
  14979. +{
  14980. + struct aufs_sbinfo *sbinfo;
  14981. + struct list_head *plink_list;
  14982. + struct pseudo_link *plink, *tmp;
  14983. + struct inode *inode;
  14984. + aufs_bindex_t bstart, bend, bindex;
  14985. + int do_put;
  14986. +
  14987. + TraceEnter();
  14988. + SiMustWriteLock(sb);
  14989. + DEBUG_ON(!au_flag_test(sb, AuFlag_PLINK));
  14990. +
  14991. + sbinfo = stosi(sb);
  14992. + plink_list = &sbinfo->si_plink;
  14993. + //spin_lock(&sbinfo->si_plink_lock);
  14994. + list_for_each_entry_safe(plink, tmp, plink_list, list) {
  14995. + do_put = 0;
  14996. + inode = igrab(plink->inode);
  14997. + ii_write_lock_child(inode);
  14998. + bstart = ibstart(inode);
  14999. + bend = ibend(inode);
  15000. + if (bstart >= 0) {
  15001. + for (bindex = bstart; bindex <= bend; bindex++) {
  15002. + if (!au_h_iptr_i(inode, bindex)
  15003. + || itoid_index(inode, bindex) != br_id)
  15004. + continue;
  15005. + set_h_iptr(inode, bindex, NULL, 0);
  15006. + do_put = 1;
  15007. + break;
  15008. + }
  15009. + } else
  15010. + do_put_plink(plink, 1);
  15011. +
  15012. + if (do_put) {
  15013. + for (bindex = bstart; bindex <= bend; bindex++)
  15014. + if (au_h_iptr_i(inode, bindex)) {
  15015. + do_put = 0;
  15016. + break;
  15017. + }
  15018. + if (do_put)
  15019. + do_put_plink(plink, 1);
  15020. + }
  15021. + ii_write_unlock(inode);
  15022. + iput(inode);
  15023. + }
  15024. + //spin_unlock(&sbinfo->si_plink_lock);
  15025. +}
  15026. diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c
  15027. new file mode 100755
  15028. index 0000000..55cb64c
  15029. --- /dev/null
  15030. +++ b/fs/aufs/sbinfo.c
  15031. @@ -0,0 +1,173 @@
  15032. +/*
  15033. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  15034. + *
  15035. + * This program, aufs is free software; you can redistribute it and/or modify
  15036. + * it under the terms of the GNU General Public License as published by
  15037. + * the Free Software Foundation; either version 2 of the License, or
  15038. + * (at your option) any later version.
  15039. + *
  15040. + * This program is distributed in the hope that it will be useful,
  15041. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15042. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15043. + * GNU General Public License for more details.
  15044. + *
  15045. + * You should have received a copy of the GNU General Public License
  15046. + * along with this program; if not, write to the Free Software
  15047. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15048. + */
  15049. +
  15050. +/* $Id: sbinfo.c,v 1.30 2007/05/14 03:39:31 sfjro Exp $ */
  15051. +
  15052. +#include "aufs.h"
  15053. +
  15054. +struct aufs_sbinfo *stosi(struct super_block *sb)
  15055. +{
  15056. + struct aufs_sbinfo *sbinfo;
  15057. + sbinfo = sb->s_fs_info;
  15058. + //DEBUG_ON(sbinfo->si_bend < 0);
  15059. + return sbinfo;
  15060. +}
  15061. +
  15062. +aufs_bindex_t sbend(struct super_block *sb)
  15063. +{
  15064. + SiMustAnyLock(sb);
  15065. + return stosi(sb)->si_bend;
  15066. +}
  15067. +
  15068. +struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex)
  15069. +{
  15070. + SiMustAnyLock(sb);
  15071. + DEBUG_ON(bindex < 0 || sbend(sb) < bindex
  15072. + || !stosi(sb)->si_branch[0 + bindex]);
  15073. + return stosi(sb)->si_branch[0 + bindex];
  15074. +}
  15075. +
  15076. +int au_sigen(struct super_block *sb)
  15077. +{
  15078. + SiMustAnyLock(sb);
  15079. + return stosi(sb)->si_generation;
  15080. +}
  15081. +
  15082. +int au_sigen_inc(struct super_block *sb)
  15083. +{
  15084. + int gen;
  15085. +
  15086. + SiMustWriteLock(sb);
  15087. + gen = ++stosi(sb)->si_generation;
  15088. + au_update_digen(sb->s_root);
  15089. + au_update_iigen(sb->s_root->d_inode);
  15090. + sb->s_root->d_inode->i_version++;
  15091. + return gen;
  15092. +}
  15093. +
  15094. +int find_bindex(struct super_block *sb, struct aufs_branch *br)
  15095. +{
  15096. + aufs_bindex_t bindex, bend;
  15097. +
  15098. + bend = sbend(sb);
  15099. + for (bindex = 0; bindex <= bend; bindex++)
  15100. + if (stobr(sb, bindex) == br)
  15101. + return bindex;
  15102. + return -1;
  15103. +}
  15104. +
  15105. +/* ---------------------------------------------------------------------- */
  15106. +
  15107. +/* dentry and super_block lock. call at entry point */
  15108. +void aufs_read_lock(struct dentry *dentry, int flags)
  15109. +{
  15110. + si_read_lock(dentry->d_sb);
  15111. + if (flags & AUFS_D_WLOCK)
  15112. + di_write_lock_child(dentry);
  15113. + else
  15114. + di_read_lock_child(dentry, flags);
  15115. +}
  15116. +
  15117. +void aufs_read_unlock(struct dentry *dentry, int flags)
  15118. +{
  15119. + if (flags & AUFS_D_WLOCK)
  15120. + di_write_unlock(dentry);
  15121. + else
  15122. + di_read_unlock(dentry, flags);
  15123. + si_read_unlock(dentry->d_sb);
  15124. +}
  15125. +
  15126. +void aufs_write_lock(struct dentry *dentry)
  15127. +{
  15128. + //au_wkq_wait_nwtask();
  15129. + si_write_lock(dentry->d_sb);
  15130. + di_write_lock_child(dentry);
  15131. +}
  15132. +
  15133. +void aufs_write_unlock(struct dentry *dentry)
  15134. +{
  15135. + di_write_unlock(dentry);
  15136. + si_write_unlock(dentry->d_sb);
  15137. + //au_wkq_wait_nwtask();
  15138. +}
  15139. +
  15140. +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir)
  15141. +{
  15142. + DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
  15143. + si_read_lock(d1->d_sb);
  15144. + di_write_lock2_child(d1, d2, isdir);
  15145. +}
  15146. +
  15147. +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
  15148. +{
  15149. + DEBUG_ON(d1 == d2 || d1->d_sb != d2->d_sb);
  15150. + di_write_unlock2(d1, d2);
  15151. + si_read_unlock(d1->d_sb);
  15152. +}
  15153. +
  15154. +/* ---------------------------------------------------------------------- */
  15155. +
  15156. +aufs_bindex_t new_br_id(struct super_block *sb)
  15157. +{
  15158. + aufs_bindex_t br_id;
  15159. +
  15160. + TraceEnter();
  15161. + SiMustWriteLock(sb);
  15162. +
  15163. + while (1) {
  15164. + br_id = ++stosi(sb)->si_last_br_id;
  15165. + if (br_id && find_brindex(sb, br_id) < 0)
  15166. + return br_id;
  15167. + }
  15168. +}
  15169. +
  15170. +/* ---------------------------------------------------------------------- */
  15171. +
  15172. +#ifdef CONFIG_AUFS_SYSAUFS
  15173. +static int make_xino(struct seq_file *seq, struct sysaufs_args *args,
  15174. + int *do_size)
  15175. +{
  15176. + int err;
  15177. + struct super_block *sb = args->sb;
  15178. + aufs_bindex_t bindex, bend;
  15179. + struct file *xf;
  15180. + struct inode *xi;
  15181. +
  15182. + TraceEnter();
  15183. + DEBUG_ON(args->index != SysaufsSb_XINO);
  15184. + SiMustReadLock(sb);
  15185. +
  15186. + *do_size = 0;
  15187. + err = seq_printf(seq, "%d %lu\n", sizeof(struct xino),
  15188. + atomic_long_read(&stosi(sb)->si_xino));
  15189. + bend = sbend(sb);
  15190. + for (bindex = 0; !err && bindex <= bend; bindex++) {
  15191. + xf = stobr(sb, bindex)->br_xino;
  15192. + xi = xf->f_dentry->d_inode;
  15193. + err = seq_printf(seq, "%d: %d, %Lux%d %Ld\n",
  15194. + bindex, file_count(xf),
  15195. + (u64)xi->i_blocks, 1 << xi->i_blkbits,
  15196. + i_size_read(xi));
  15197. + }
  15198. + return err;
  15199. +}
  15200. +
  15201. +sysaufs_op au_si_ops[] = {
  15202. + [SysaufsSb_XINO] = make_xino
  15203. +};
  15204. +#endif
  15205. diff --git a/fs/aufs/super.c b/fs/aufs/super.c
  15206. new file mode 100755
  15207. index 0000000..c1123f8
  15208. --- /dev/null
  15209. +++ b/fs/aufs/super.c
  15210. @@ -0,0 +1,716 @@
  15211. +/*
  15212. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  15213. + *
  15214. + * This program, aufs is free software; you can redistribute it and/or modify
  15215. + * it under the terms of the GNU General Public License as published by
  15216. + * the Free Software Foundation; either version 2 of the License, or
  15217. + * (at your option) any later version.
  15218. + *
  15219. + * This program is distributed in the hope that it will be useful,
  15220. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15221. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15222. + * GNU General Public License for more details.
  15223. + *
  15224. + * You should have received a copy of the GNU General Public License
  15225. + * along with this program; if not, write to the Free Software
  15226. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15227. + */
  15228. +
  15229. +/* $Id: super.c,v 1.50 2007/05/14 03:39:42 sfjro Exp $ */
  15230. +
  15231. +#include <linux/module.h>
  15232. +#include <linux/seq_file.h>
  15233. +#include <linux/statfs.h>
  15234. +#include "aufs.h"
  15235. +
  15236. +/*
  15237. + * super_operations
  15238. + */
  15239. +static struct inode *aufs_alloc_inode(struct super_block *sb)
  15240. +{
  15241. + struct aufs_icntnr *c;
  15242. +
  15243. + TraceEnter();
  15244. +
  15245. + c = cache_alloc_icntnr();
  15246. + //if (LktrCond) {cache_free_icntnr(c); c = NULL;}
  15247. + if (c) {
  15248. + inode_init_once(&c->vfs_inode);
  15249. + c->vfs_inode.i_version = 1; //sigen(sb);
  15250. + c->iinfo.ii_hinode = NULL;
  15251. + return &c->vfs_inode;
  15252. + }
  15253. + return NULL;
  15254. +}
  15255. +
  15256. +static void aufs_destroy_inode(struct inode *inode)
  15257. +{
  15258. + LKTRTrace("i%lu\n", inode->i_ino);
  15259. + au_iinfo_fin(inode);
  15260. + cache_free_icntnr(container_of(inode, struct aufs_icntnr, vfs_inode));
  15261. +}
  15262. +
  15263. +//todo: how about merge with alloc_inode()?
  15264. +static void aufs_read_inode(struct inode *inode)
  15265. +{
  15266. + int err;
  15267. +
  15268. + LKTRTrace("i%lu\n", inode->i_ino);
  15269. +
  15270. + err = au_iinfo_init(inode);
  15271. + //if (LktrCond) err = -1;
  15272. + if (!err) {
  15273. + inode->i_version++;
  15274. + inode->i_op = &aufs_iop;
  15275. + inode->i_fop = &aufs_file_fop;
  15276. + inode->i_mapping->a_ops = &aufs_aop;
  15277. + return; /* success */
  15278. + }
  15279. +
  15280. + LKTRTrace("intializing inode info failed(%d)\n", err);
  15281. + make_bad_inode(inode);
  15282. +}
  15283. +
  15284. +int au_show_brs(struct seq_file *seq, struct super_block *sb)
  15285. +{
  15286. + int err;
  15287. + aufs_bindex_t bindex, bend;
  15288. + char a[16];
  15289. + struct dentry *root;
  15290. +
  15291. + TraceEnter();
  15292. + SiMustAnyLock(sb);
  15293. + root = sb->s_root;
  15294. + DiMustAnyLock(root);
  15295. +
  15296. + err = 0;
  15297. + bend = sbend(sb);
  15298. + for (bindex = 0; !err && bindex <= bend; bindex++) {
  15299. + err = br_perm_str(a, sizeof(a), sbr_perm(sb, bindex));
  15300. + if (!err)
  15301. + err = seq_path(seq, sbr_mnt(sb, bindex),
  15302. + au_h_dptr_i(root, bindex), au_esc_chars);
  15303. + if (err > 0)
  15304. + err = seq_printf(seq, "=%s", a);
  15305. + if (!err && bindex != bend)
  15306. + err = seq_putc(seq, ':');
  15307. + }
  15308. +
  15309. + TraceErr(err);
  15310. + return err;
  15311. +}
  15312. +
  15313. +static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
  15314. +{
  15315. + int err, n;
  15316. + struct super_block *sb;
  15317. + struct aufs_sbinfo *sbinfo;
  15318. + struct dentry *root;
  15319. + struct file *xino;
  15320. +
  15321. + TraceEnter();
  15322. +
  15323. + sb = mnt->mnt_sb;
  15324. + root = sb->s_root;
  15325. + aufs_read_lock(root, !AUFS_I_RLOCK);
  15326. + if (au_flag_test(sb, AuFlag_XINO)) {
  15327. + err = seq_puts(m, ",xino=");
  15328. + if (unlikely(err))
  15329. + goto out;
  15330. + xino = stobr(sb, 0)->br_xino;
  15331. + err = seq_path(m, xino->f_vfsmnt, xino->f_dentry, au_esc_chars);
  15332. + if (unlikely(err <= 0))
  15333. + goto out;
  15334. + err = 0;
  15335. +
  15336. +#define Deleted "\\040(deleted)"
  15337. + m->count -= sizeof(Deleted) - 1;
  15338. + DEBUG_ON(memcmp(m->buf + m->count, Deleted,
  15339. + sizeof(Deleted) - 1));
  15340. +#undef Deleted
  15341. + } else
  15342. + err = seq_puts(m, ",noxino");
  15343. +
  15344. + n = au_flag_test(sb, AuFlag_PLINK);
  15345. + if (unlikely(!err && (AuDefFlags & AuFlag_PLINK) != n))
  15346. + err = seq_printf(m, ",%splink", n ? "" : "no");
  15347. + n = au_flag_test_udba(sb);
  15348. + if (unlikely(!err && (AuDefFlags & AuMask_UDBA) != n))
  15349. + err = seq_printf(m, ",udba=%s", udba_str(n));
  15350. + n = au_flag_test(sb, AuFlag_ALWAYS_DIROPQ);
  15351. + if (unlikely(!err && (AuDefFlags & AuFlag_ALWAYS_DIROPQ) != n))
  15352. + err = seq_printf(m, ",diropq=%c", n ? 'a' : 'w');
  15353. + n = au_flag_test(sb, AuFlag_DLGT);
  15354. + if (unlikely(!err && (AuDefFlags & AuFlag_DLGT) != n))
  15355. + err = seq_printf(m, ",%sdlgt", n ? "" : "no");
  15356. + n = au_flag_test(sb, AuFlag_WARN_PERM);
  15357. + if (unlikely(!err && (AuDefFlags & AuFlag_WARN_PERM) != n))
  15358. + err = seq_printf(m, ",%swarn_perm", n ? "" : "no");
  15359. +
  15360. + sbinfo = stosi(sb);
  15361. + n = sbinfo->si_dirwh;
  15362. + if (unlikely(!err && n != AUFS_DIRWH_DEF))
  15363. + err = seq_printf(m, ",dirwh=%d", n);
  15364. + n = sbinfo->si_rdcache / HZ;
  15365. + if (unlikely(!err && n != AUFS_RDCACHE_DEF))
  15366. + err = seq_printf(m, ",rdcache=%d", n);
  15367. +#if 0
  15368. + n = au_flag_test_coo(sb);
  15369. + if (unlikely(!err && (AuDefFlags & AuMask_COO) != n))
  15370. + err = seq_printf(m, ",coo=%s", coo_str(n));
  15371. +#endif
  15372. +
  15373. + if (!err && !sysaufs_brs) {
  15374. +#ifdef CONFIG_AUFS_COMPAT
  15375. + err = seq_puts(m, ",dirs=");
  15376. +#else
  15377. + err = seq_puts(m, ",br:");
  15378. +#endif
  15379. + if (!err)
  15380. + err = au_show_brs(m, sb);
  15381. + }
  15382. +
  15383. + out:
  15384. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  15385. + TraceErr(err);
  15386. + if (err)
  15387. + err = -E2BIG;
  15388. + TraceErr(err);
  15389. + return err;
  15390. +}
  15391. +
  15392. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  15393. +#define StatfsLock(d) aufs_read_lock((d)->d_sb->s_root, 0)
  15394. +#define StatfsUnlock(d) aufs_read_unlock((d)->d_sb->s_root, 0)
  15395. +#define StatfsArg(d) au_h_dptr((d)->d_sb->s_root)
  15396. +#define StatfsHInode(d) (StatfsArg(d)->d_inode)
  15397. +#define StatfsSb(d) ((d)->d_sb)
  15398. +static int aufs_statfs(struct dentry *arg, struct kstatfs *buf)
  15399. +#else
  15400. +#define StatfsLock(s) si_read_lock(s)
  15401. +#define StatfsUnlock(s) si_read_unlock(s)
  15402. +#define StatfsArg(s) sbr_sb(s, 0)
  15403. +#define StatfsHInode(s) (StatfsArg(s)->s_root->d_inode)
  15404. +#define StatfsSb(s) (s)
  15405. +static int aufs_statfs(struct super_block *arg, struct kstatfs *buf)
  15406. +#endif
  15407. +{
  15408. + int err;
  15409. +
  15410. + TraceEnter();
  15411. +
  15412. + StatfsLock(arg);
  15413. + err = vfsub_statfs(StatfsArg(arg), buf, need_dlgt(StatfsSb(arg)));
  15414. + //if (LktrCond) err = -1;
  15415. + StatfsUnlock(arg);
  15416. + if (!err) {
  15417. + //buf->f_type = AUFS_SUPER_MAGIC;
  15418. + buf->f_type = 0;
  15419. + buf->f_namelen -= AUFS_WH_PFX_LEN;
  15420. + memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
  15421. + }
  15422. + //buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
  15423. +
  15424. + TraceErr(err);
  15425. + return err;
  15426. +}
  15427. +
  15428. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) || defined(UbuntuEdgy17Umount18)
  15429. +#define UmountBeginSb(mnt) (mnt)->mnt_sb
  15430. +static void aufs_umount_begin(struct vfsmount *arg, int flags)
  15431. +#else
  15432. +#define UmountBeginSb(sb) sb
  15433. +static void aufs_umount_begin(struct super_block *arg)
  15434. +#endif
  15435. +{
  15436. + struct super_block *sb = UmountBeginSb(arg);
  15437. +
  15438. + if (unlikely(!stosi(sb)))
  15439. + return;
  15440. +
  15441. + //au_wkq_wait_nwtask();
  15442. + si_write_lock(sb);
  15443. + if (au_flag_test(sb, AuFlag_PLINK)) {
  15444. + au_put_plink(sb);
  15445. + //kobj_umount(stosi(sb));
  15446. + }
  15447. +#if 0
  15448. + if (unlikely(au_flag_test(sb, AuFlag_UDBA_INOTIFY)))
  15449. + shrink_dcache_sb(sb);
  15450. +#endif
  15451. + si_write_unlock(sb);
  15452. +}
  15453. +
  15454. +static void free_sbinfo(struct aufs_sbinfo *sbinfo)
  15455. +{
  15456. + TraceEnter();
  15457. + DEBUG_ON(!sbinfo
  15458. + || !list_empty(&sbinfo->si_plink));
  15459. +
  15460. + free_branches(sbinfo);
  15461. + kfree(sbinfo->si_branch);
  15462. + kfree(sbinfo);
  15463. +}
  15464. +
  15465. +/* final actions when unmounting a file system */
  15466. +static void aufs_put_super(struct super_block *sb)
  15467. +{
  15468. + struct aufs_sbinfo *sbinfo;
  15469. +
  15470. + TraceEnter();
  15471. +
  15472. + sbinfo = stosi(sb);
  15473. + if (unlikely(!sbinfo))
  15474. + return;
  15475. +
  15476. + sysaufs_del(sbinfo);
  15477. +
  15478. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && !defined(UbuntuEdgy17Umount18)
  15479. + // umount_begin() may not be called.
  15480. + aufs_umount_begin(sb);
  15481. +#endif
  15482. + free_sbinfo(sbinfo);
  15483. +}
  15484. +
  15485. +/* ---------------------------------------------------------------------- */
  15486. +
  15487. +/*
  15488. + * refresh directories at remount time.
  15489. + */
  15490. +static int do_refresh_dir(struct dentry *dentry, unsigned int flags)
  15491. +{
  15492. + int err;
  15493. + struct dentry *parent;
  15494. + struct inode *inode;
  15495. +
  15496. + LKTRTrace("%.*s\n", DLNPair(dentry));
  15497. + inode = dentry->d_inode;
  15498. + DEBUG_ON(!inode || !S_ISDIR(inode->i_mode));
  15499. +
  15500. + di_write_lock_child(dentry);
  15501. + parent = dget_parent(dentry);
  15502. + di_read_lock_parent(parent, AUFS_I_RLOCK);
  15503. + err = au_refresh_hdentry(dentry, S_IFDIR);
  15504. + if (err >= 0) {
  15505. + err = au_refresh_hinode(inode, dentry);
  15506. + if (!err)
  15507. + au_reset_hinotify(inode, flags);
  15508. + }
  15509. + if (unlikely(err))
  15510. + Err("unrecoverable error %d\n", err);
  15511. + di_read_unlock(parent, AUFS_I_RLOCK);
  15512. + dput(parent);
  15513. + di_write_unlock(dentry);
  15514. +
  15515. + TraceErr(err);
  15516. + return err;
  15517. +}
  15518. +
  15519. +static int test_dir(struct dentry *dentry, void *arg)
  15520. +{
  15521. + return S_ISDIR(dentry->d_inode->i_mode);
  15522. +}
  15523. +
  15524. +static int refresh_dir(struct dentry *root, int sgen)
  15525. +{
  15526. + int err, i, j, ndentry;
  15527. + const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
  15528. + struct au_dcsub_pages dpages;
  15529. + struct au_dpage *dpage;
  15530. + struct dentry **dentries;
  15531. +
  15532. + LKTRTrace("sgen %d\n", sgen);
  15533. + SiMustWriteLock(root->d_sb);
  15534. + DEBUG_ON(au_digen(root) != sgen);
  15535. + DiMustWriteLock(root);
  15536. +
  15537. + err = au_dpages_init(&dpages, GFP_KERNEL);
  15538. + if (unlikely(err))
  15539. + goto out;
  15540. + err = au_dcsub_pages(&dpages, root, test_dir, NULL);
  15541. + if (unlikely(err))
  15542. + goto out_dpages;
  15543. +
  15544. + DiMustNoWaiters(root);
  15545. + IiMustNoWaiters(root->d_inode);
  15546. + di_write_unlock(root);
  15547. + for (i = 0; !err && i < dpages.ndpage; i++) {
  15548. + dpage = dpages.dpages + i;
  15549. + dentries = dpage->dentries;
  15550. + ndentry = dpage->ndentry;
  15551. + for (j = 0; !err && j < ndentry; j++) {
  15552. + struct dentry *d;
  15553. + d = dentries[j];
  15554. + DEBUG_ON(!S_ISDIR(d->d_inode->i_mode)
  15555. + || IS_ROOT(d)
  15556. + || au_digen(d->d_parent) != sgen);
  15557. + if (au_digen(d) != sgen)
  15558. + err = do_refresh_dir(d, flags);
  15559. + }
  15560. + }
  15561. + di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
  15562. +
  15563. + out_dpages:
  15564. + au_dpages_free(&dpages);
  15565. + out:
  15566. + TraceErr(err);
  15567. + return err;
  15568. +}
  15569. +
  15570. +/* stop extra interpretation of errno in mount(8), and strange error messages */
  15571. +static int cvt_err(int err)
  15572. +{
  15573. + TraceErr(err);
  15574. +
  15575. + switch (err) {
  15576. + case -ENOENT:
  15577. + case -ENOTDIR:
  15578. + case -EEXIST:
  15579. + case -EIO:
  15580. + err = -EINVAL;
  15581. + }
  15582. + return err;
  15583. +}
  15584. +
  15585. +/* protected by s_umount */
  15586. +static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
  15587. +{
  15588. + int err, do_refresh;
  15589. + struct dentry *root;
  15590. + struct inode *inode;
  15591. + struct opts opts;
  15592. + unsigned int given, dlgt;
  15593. +
  15594. + //au_debug_on();
  15595. + LKTRTrace("flags 0x%x, data %s, len %d\n",
  15596. + *flags, data ? data : "NULL", data ? strlen(data) : 0);
  15597. +
  15598. + err = 0;
  15599. + if (unlikely(!data || !*data))
  15600. + goto out; /* success */
  15601. +
  15602. + err = -ENOMEM;
  15603. + memset(&opts, 0, sizeof(opts));
  15604. + opts.opt = (void*)__get_free_page(GFP_KERNEL);
  15605. + //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
  15606. + if (unlikely(!opts.opt))
  15607. + goto out;
  15608. + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
  15609. +
  15610. + /* parse it before aufs lock */
  15611. + err = au_parse_opts(sb, data, &opts);
  15612. + //if (LktrCond) {au_free_opts(&opts); err = -1;}
  15613. + if (unlikely(err))
  15614. + goto out_opts;
  15615. +
  15616. + root = sb->s_root;
  15617. + inode = root->d_inode;
  15618. + i_lock(inode);
  15619. + aufs_write_lock(root);
  15620. +
  15621. + //DbgSleep(3);
  15622. +
  15623. + /* au_do_opts() may return an error */
  15624. + do_refresh = 0;
  15625. + given = 0;
  15626. + err = au_do_opts_remount(sb, &opts, &do_refresh, &given);
  15627. + //if (LktrCond) err = -1;
  15628. + au_free_opts(&opts);
  15629. +
  15630. + if (do_refresh) {
  15631. + int rerr;
  15632. + struct aufs_sbinfo *sbinfo;
  15633. +
  15634. + dlgt = au_flag_test(sb, AuFlag_DLGT);
  15635. + au_flag_clr(sb, AuFlag_DLGT);
  15636. + au_sigen_inc(sb);
  15637. + au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
  15638. + sbinfo = stosi(sb);
  15639. + sbinfo->si_failed_refresh_dirs = 0;
  15640. + rerr = refresh_dir(root, au_sigen(sb));
  15641. + if (unlikely(rerr)) {
  15642. + sbinfo->si_failed_refresh_dirs = 1;
  15643. + Warn("Refreshing directories failed, ignores (%d)\n",
  15644. + rerr);
  15645. + }
  15646. + au_cpup_attr_all(inode);
  15647. + au_flag_set(sb, dlgt);
  15648. + }
  15649. +
  15650. + aufs_write_unlock(root);
  15651. + i_unlock(inode);
  15652. + /* braces are added to stop a warning */
  15653. + if (do_refresh) {
  15654. + sysaufs_notify_remount();
  15655. + }
  15656. +
  15657. + out_opts:
  15658. + free_page((unsigned long)opts.opt);
  15659. + out:
  15660. + err = cvt_err(err);
  15661. + TraceErr(err);
  15662. + //au_debug_off();
  15663. + return err;
  15664. +}
  15665. +
  15666. +static struct super_operations aufs_sop = {
  15667. + .alloc_inode = aufs_alloc_inode,
  15668. + .destroy_inode = aufs_destroy_inode,
  15669. + .read_inode = aufs_read_inode,
  15670. + //.dirty_inode = aufs_dirty_inode,
  15671. + //.write_inode = aufs_write_inode,
  15672. + //void (*put_inode) (struct inode *);
  15673. + .drop_inode = generic_delete_inode,
  15674. + //.delete_inode = aufs_delete_inode,
  15675. + //.clear_inode = aufs_clear_inode,
  15676. +
  15677. + .show_options = aufs_show_options,
  15678. + .statfs = aufs_statfs,
  15679. +
  15680. + .put_super = aufs_put_super,
  15681. + //void (*write_super) (struct super_block *);
  15682. + //int (*sync_fs)(struct super_block *sb, int wait);
  15683. + //void (*write_super_lockfs) (struct super_block *);
  15684. + //void (*unlockfs) (struct super_block *);
  15685. + .remount_fs = aufs_remount_fs,
  15686. + // depends upon umount flags. also use put_super() (< 2.6.18)
  15687. + .umount_begin = aufs_umount_begin
  15688. +};
  15689. +
  15690. +/* ---------------------------------------------------------------------- */
  15691. +
  15692. +/*
  15693. + * at first mount time.
  15694. + */
  15695. +
  15696. +static int alloc_sbinfo(struct super_block *sb)
  15697. +{
  15698. + struct aufs_sbinfo *sbinfo;
  15699. +
  15700. + TraceEnter();
  15701. +
  15702. + sbinfo = kmalloc(sizeof(*sbinfo), GFP_KERNEL);
  15703. + //if (LktrCond) {kfree(sbinfo); sbinfo = NULL;}
  15704. + if (unlikely(!sbinfo))
  15705. + goto out;
  15706. + sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_KERNEL);
  15707. + //if (LktrCond) {kfree(sbinfo->si_branch); sbinfo->si_branch = NULL;}
  15708. + if (unlikely(!sbinfo->si_branch)) {
  15709. + kfree(sbinfo);
  15710. + goto out;
  15711. + }
  15712. + rw_init_wlock(&sbinfo->si_rwsem);
  15713. + sbinfo->si_bend = -1;
  15714. + atomic_long_set(&sbinfo->si_xino, AUFS_FIRST_INO);
  15715. + spin_lock_init(&sbinfo->si_plink_lock);
  15716. + INIT_LIST_HEAD(&sbinfo->si_plink);
  15717. + init_lvma(sbinfo);
  15718. + sbinfo->si_generation = 0;
  15719. + sbinfo->si_last_br_id = 0;
  15720. + sbinfo->si_failed_refresh_dirs = 0;
  15721. + sbinfo->si_flags = 0;
  15722. + sbinfo->si_dirwh = AUFS_DIRWH_DEF;
  15723. + sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
  15724. + //atomic_set(&sbinfo->si_hinotify, 0);
  15725. + //init_waitqueue_head(&sbinfo->si_hinotify_wq);
  15726. +
  15727. + sb->s_fs_info = sbinfo;
  15728. + au_flag_set(sb, AuDefFlags);
  15729. +#ifdef ForceInotify
  15730. + udba_set(sb, AuFlag_UDBA_INOTIFY);
  15731. +#endif
  15732. +#ifdef ForceDlgt
  15733. + au_flag_set(sb, AuFlag_DLGT);
  15734. +#endif
  15735. +#ifdef ForceNoPlink
  15736. + au_flag_clr(sb, AuFlag_PLINK);
  15737. +#endif
  15738. + return 0; /* success */
  15739. +
  15740. + out:
  15741. + TraceErr(-ENOMEM);
  15742. + return -ENOMEM;
  15743. +}
  15744. +
  15745. +static int alloc_root(struct super_block *sb)
  15746. +{
  15747. + int err;
  15748. + struct inode *inode;
  15749. + struct dentry *root;
  15750. +
  15751. + TraceEnter();
  15752. +
  15753. + err = -ENOMEM;
  15754. + inode = iget(sb, AUFS_ROOT_INO);
  15755. + //if (LktrCond) {iput(inode); inode = NULL;}
  15756. + if (unlikely(!inode))
  15757. + goto out;
  15758. + err = PTR_ERR(inode);
  15759. + if (IS_ERR(inode))
  15760. + goto out;
  15761. + err = -ENOMEM;
  15762. + if (unlikely(is_bad_inode(inode)))
  15763. + goto out_iput;
  15764. +
  15765. + root = d_alloc_root(inode);
  15766. + //if (LktrCond) {igrab(inode); dput(root); root = NULL;}
  15767. + if (unlikely(!root))
  15768. + goto out_iput;
  15769. + err = PTR_ERR(root);
  15770. + if (IS_ERR(root))
  15771. + goto out_iput;
  15772. +
  15773. + err = au_alloc_dinfo(root);
  15774. + //if (LktrCond){rw_write_unlock(&dtodi(root)->di_rwsem);err=-1;}
  15775. + if (!err) {
  15776. + sb->s_root = root;
  15777. + return 0; /* success */
  15778. + }
  15779. + dput(root);
  15780. + goto out; /* do not iput */
  15781. +
  15782. + out_iput:
  15783. + iput(inode);
  15784. + out:
  15785. + TraceErr(err);
  15786. + return err;
  15787. +
  15788. +}
  15789. +
  15790. +static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
  15791. +{
  15792. + int err;
  15793. + struct dentry *root;
  15794. + struct inode *inode;
  15795. + struct opts opts;
  15796. + char *arg = raw_data;
  15797. +
  15798. + //au_debug_on();
  15799. + if (unlikely(!arg || !*arg)) {
  15800. + err = -EINVAL;
  15801. + Err("no arg\n");
  15802. + goto out;
  15803. + }
  15804. + LKTRTrace("%s, silent %d\n", arg, silent);
  15805. +
  15806. + err = -ENOMEM;
  15807. + memset(&opts, 0, sizeof(opts));
  15808. + opts.opt = (void*)__get_free_page(GFP_KERNEL);
  15809. + //if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
  15810. + if (unlikely(!opts.opt))
  15811. + goto out;
  15812. + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
  15813. +
  15814. + err = alloc_sbinfo(sb);
  15815. + //if (LktrCond) {si_write_unlock(sb);free_sbinfo(stosi(sb));err=-1;}
  15816. + if (unlikely(err))
  15817. + goto out_opts;
  15818. + SiMustWriteLock(sb);
  15819. + /* all timestamps always follow the ones on the branch */
  15820. + sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
  15821. + sb->s_op = &aufs_sop;
  15822. + au_init_export_op(sb);
  15823. + //err = kobj_mount(stosi(sb));
  15824. + //if (err)
  15825. + //goto out_info;
  15826. +
  15827. + err = alloc_root(sb);
  15828. + //if (LktrCond) {rw_write_unlock(&dtodi(sb->s_root)->di_rwsem);
  15829. + //dput(sb->s_root);sb->s_root=NULL;err=-1;}
  15830. + if (unlikely(err)) {
  15831. + DEBUG_ON(sb->s_root);
  15832. + si_write_unlock(sb);
  15833. + goto out_info;
  15834. + }
  15835. + root = sb->s_root;
  15836. + DiMustWriteLock(root);
  15837. + inode = root->d_inode;
  15838. + inode->i_nlink = 2;
  15839. +
  15840. + /*
  15841. + * actually we can parse options regardless aufs lock here.
  15842. + * but at remount time, parsing must be done before aufs lock.
  15843. + * so we follow the same rule.
  15844. + */
  15845. + ii_write_lock_parent(inode);
  15846. + aufs_write_unlock(root);
  15847. + err = au_parse_opts(sb, arg, &opts);
  15848. + //if (LktrCond) {au_free_opts(&opts); err = -1;}
  15849. + if (unlikely(err))
  15850. + goto out_root;
  15851. +
  15852. + /* lock vfs_inode first, then aufs. */
  15853. + i_lock(inode);
  15854. + inode->i_op = &aufs_dir_iop;
  15855. + inode->i_fop = &aufs_dir_fop;
  15856. + aufs_write_lock(root);
  15857. +
  15858. + sb->s_maxbytes = 0;
  15859. + err = au_do_opts_mount(sb, &opts);
  15860. + //if (LktrCond) err = -1;
  15861. + au_free_opts(&opts);
  15862. + if (unlikely(err))
  15863. + goto out_unlock;
  15864. + DEBUG_ON(!sb->s_maxbytes);
  15865. +
  15866. + //DbgDentry(root);
  15867. + aufs_write_unlock(root);
  15868. + i_unlock(inode);
  15869. + //DbgSb(sb);
  15870. + goto out_opts; /* success */
  15871. +
  15872. + out_unlock:
  15873. + aufs_write_unlock(root);
  15874. + i_unlock(inode);
  15875. + out_root:
  15876. + dput(root);
  15877. + sb->s_root = NULL;
  15878. + out_info:
  15879. + free_sbinfo(stosi(sb));
  15880. + sb->s_fs_info = NULL;
  15881. + out_opts:
  15882. + free_page((unsigned long)opts.opt);
  15883. + out:
  15884. + TraceErr(err);
  15885. + err = cvt_err(err);
  15886. + TraceErr(err);
  15887. + //au_debug_off();
  15888. + return err;
  15889. +}
  15890. +
  15891. +/* ---------------------------------------------------------------------- */
  15892. +
  15893. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  15894. +static int aufs_get_sb(struct file_system_type *fs_type, int flags,
  15895. + const char *dev_name, void *raw_data,
  15896. + struct vfsmount *mnt)
  15897. +{
  15898. + int err;
  15899. +
  15900. + /* all timestamps always follow the ones on the branch */
  15901. + //mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME;
  15902. + err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
  15903. + if (!err) {
  15904. + struct aufs_sbinfo *sbinfo = stosi(mnt->mnt_sb);
  15905. + sbinfo->si_mnt = mnt;
  15906. + sysaufs_add(sbinfo);
  15907. + }
  15908. + return err;
  15909. +}
  15910. +#else
  15911. +static struct super_block *aufs_get_sb(struct file_system_type *fs_type,
  15912. + int flags, const char *dev_name,
  15913. + void *raw_data)
  15914. +{
  15915. + return get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super);
  15916. +}
  15917. +#endif
  15918. +
  15919. +struct file_system_type aufs_fs_type = {
  15920. + .name = AUFS_FSTYPE,
  15921. + .fs_flags = FS_REVAL_DOT, // for UDBA and NFS branch
  15922. + .get_sb = aufs_get_sb,
  15923. + .kill_sb = generic_shutdown_super,
  15924. + //no need to __module_get() and module_put().
  15925. + .owner = THIS_MODULE,
  15926. +};
  15927. diff --git a/fs/aufs/super.h b/fs/aufs/super.h
  15928. new file mode 100755
  15929. index 0000000..56ddee1
  15930. --- /dev/null
  15931. +++ b/fs/aufs/super.h
  15932. @@ -0,0 +1,339 @@
  15933. +/*
  15934. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  15935. + *
  15936. + * This program, aufs is free software; you can redistribute it and/or modify
  15937. + * it under the terms of the GNU General Public License as published by
  15938. + * the Free Software Foundation; either version 2 of the License, or
  15939. + * (at your option) any later version.
  15940. + *
  15941. + * This program is distributed in the hope that it will be useful,
  15942. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15943. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15944. + * GNU General Public License for more details.
  15945. + *
  15946. + * You should have received a copy of the GNU General Public License
  15947. + * along with this program; if not, write to the Free Software
  15948. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15949. + */
  15950. +
  15951. +/* $Id: super.h,v 1.44 2007/05/14 03:39:54 sfjro Exp $ */
  15952. +
  15953. +#ifndef __AUFS_SUPER_H__
  15954. +#define __AUFS_SUPER_H__
  15955. +
  15956. +#ifdef __KERNEL__
  15957. +
  15958. +#include <linux/fs.h>
  15959. +#include <linux/version.h>
  15960. +#include <linux/aufs_type.h>
  15961. +#include "misc.h"
  15962. +#include "sysaufs.h"
  15963. +
  15964. +#ifdef CONFIG_AUFS_SYSAUFS
  15965. +/* entries under sysfs per mount-point */
  15966. +enum {SysaufsSb_XINO, /* SysaufsSb_PLINK, */ SysaufsSb_Last};
  15967. +struct sysaufs_sbinfo {
  15968. + au_subsys_t subsys;
  15969. + struct sysaufs_entry array[SysaufsSb_Last];
  15970. +};
  15971. +extern sysaufs_op au_si_ops[];
  15972. +#else
  15973. +struct sysaufs_sbinfo {};
  15974. +#endif
  15975. +
  15976. +struct aufs_sbinfo {
  15977. + struct aufs_rwsem si_rwsem;
  15978. +
  15979. + /* branch management */
  15980. + /* wrap around attack by superuser? No. */
  15981. + int si_generation;
  15982. +
  15983. + /*
  15984. + * set true when refresh_dirs() at remount time failed.
  15985. + * then try refreshing dirs at access time again.
  15986. + * if it is false, refreshing dirs at access time is unnecesary
  15987. + */
  15988. + unsigned int si_failed_refresh_dirs:1;
  15989. +
  15990. + aufs_bindex_t si_bend;
  15991. + aufs_bindex_t si_last_br_id;
  15992. + struct aufs_branch **si_branch;
  15993. +
  15994. + /* mount flags */
  15995. + unsigned int si_flags;
  15996. +
  15997. + /* external inode number table */
  15998. + atomic_long_t si_xino; // time bomb
  15999. + //struct file *si_xino_bmap;
  16000. +
  16001. + /* readdir cache time, max, in HZ */
  16002. + unsigned long si_rdcache;
  16003. +
  16004. + /*
  16005. + * If the number of whiteouts are larger than si_dirwh, leave all of
  16006. + * them after rename_whtmp to reduce the cost of rmdir(2).
  16007. + * future fsck.aufs or kernel thread will remove them later.
  16008. + * Otherwise, remove all whiteouts and the dir in rmdir(2).
  16009. + */
  16010. + unsigned int si_dirwh;
  16011. +
  16012. + /* pseudo_link list */ // dirty
  16013. + spinlock_t si_plink_lock;
  16014. + struct list_head si_plink;
  16015. +
  16016. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  16017. + /* super_blocks list is not exported */
  16018. + struct list_head si_list;
  16019. + struct vfsmount *si_mnt; /* no get/put */
  16020. +#endif
  16021. +
  16022. + /* sysfs */
  16023. + struct sysaufs_sbinfo si_sysaufs;
  16024. +
  16025. +#ifdef CONFIG_AUFS_HINOTIFY
  16026. + /* hinotify */
  16027. + //atomic_t si_hinotify;
  16028. + //wait_queue_head_t si_hinotify_wq;
  16029. +#endif
  16030. +
  16031. +#ifdef CONFIG_AUFS_ROBR
  16032. + /* locked vma list for mmap() */ // very dirty
  16033. + spinlock_t si_lvma_lock;
  16034. + struct list_head si_lvma;
  16035. +#endif
  16036. +};
  16037. +
  16038. +/* an entry in a xino file */
  16039. +struct xino {
  16040. + ino_t ino;
  16041. + //__u32 h_gen;
  16042. +} __attribute__ ((packed));
  16043. +
  16044. +//#define AuXino_INVALID_HGEN (-1)
  16045. +
  16046. +/* ---------------------------------------------------------------------- */
  16047. +
  16048. +/* Mount flags */
  16049. +#define AuFlag_XINO 1
  16050. +#define AuFlag_ZXINO (1 << 1)
  16051. +#define AuFlag_PLINK (1 << 2)
  16052. +#define AuFlag_UDBA_NONE (1 << 3)
  16053. +#define AuFlag_UDBA_REVAL (1 << 4)
  16054. +#define AuFlag_UDBA_INOTIFY (1 << 5)
  16055. +#define AuFlag_WARN_PERM (1 << 6)
  16056. +#define AuFlag_COO_NONE (1 << 7)
  16057. +#define AuFlag_COO_LEAF (1 << 8)
  16058. +#define AuFlag_COO_ALL (1 << 9)
  16059. +#define AuFlag_ALWAYS_DIROPQ (1 << 10)
  16060. +#define AuFlag_DLGT (1 << 11)
  16061. +
  16062. +#define AuMask_UDBA (AuFlag_UDBA_NONE | AuFlag_UDBA_REVAL \
  16063. + | AuFlag_UDBA_INOTIFY)
  16064. +#define AuMask_COO (AuFlag_COO_NONE | AuFlag_COO_LEAF \
  16065. + | AuFlag_COO_ALL)
  16066. +
  16067. +#ifdef CONFIG_AUFS_COMPAT
  16068. +#define AuDefFlag_DIROPQ AuFlag_ALWAYS_DIROPQ
  16069. +#else
  16070. +#define AuDefFlag_DIROPQ 0
  16071. +#endif
  16072. +
  16073. +#define AuDefFlags_COMM (AuFlag_XINO | AuFlag_UDBA_REVAL | AuFlag_WARN_PERM \
  16074. + | AuFlag_COO_NONE | AuDefFlag_DIROPQ)
  16075. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
  16076. +#define AuDefFlags (AuDefFlags_COMM | AuFlag_PLINK)
  16077. +#else
  16078. +#define AuDefFlags AuDefFlags_COMM
  16079. +#endif
  16080. +
  16081. +/* ---------------------------------------------------------------------- */
  16082. +
  16083. +/* flags for aufs_read_lock()/di_read_lock() */
  16084. +#define AUFS_D_WLOCK 1
  16085. +#define AUFS_I_RLOCK 2
  16086. +#define AUFS_I_WLOCK 4
  16087. +
  16088. +/* ---------------------------------------------------------------------- */
  16089. +
  16090. +/* super.c */
  16091. +int au_show_brs(struct seq_file *seq, struct super_block *sb);
  16092. +
  16093. +/* xino.c */
  16094. +struct file *xino_create(struct super_block *sb, char *fname, int silent,
  16095. + struct dentry *parent);
  16096. +ino_t xino_new_ino(struct super_block *sb);
  16097. +int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino);
  16098. +int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  16099. + struct xino *xino);
  16100. +int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  16101. + struct xino *xino);
  16102. +int xino_init(struct super_block *sb, aufs_bindex_t bindex,
  16103. + struct file *base_file, int do_test);
  16104. +struct opt_xino;
  16105. +int xino_set(struct super_block *sb, struct opt_xino *xino, int remount);
  16106. +int xino_clr(struct super_block *sb);
  16107. +struct file *xino_def(struct super_block *sb);
  16108. +
  16109. +/* sbinfo.c */
  16110. +struct aufs_sbinfo *stosi(struct super_block *sb);
  16111. +aufs_bindex_t sbend(struct super_block *sb);
  16112. +struct aufs_branch *stobr(struct super_block *sb, aufs_bindex_t bindex);
  16113. +int au_sigen(struct super_block *sb);
  16114. +int au_sigen_inc(struct super_block *sb);
  16115. +int find_bindex(struct super_block *sb, struct aufs_branch *br);
  16116. +
  16117. +void aufs_read_lock(struct dentry *dentry, int flags);
  16118. +void aufs_read_unlock(struct dentry *dentry, int flags);
  16119. +void aufs_write_lock(struct dentry *dentry);
  16120. +void aufs_write_unlock(struct dentry *dentry);
  16121. +void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int isdir);
  16122. +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
  16123. +
  16124. +aufs_bindex_t new_br_id(struct super_block *sb);
  16125. +
  16126. +/* ---------------------------------------------------------------------- */
  16127. +
  16128. +static inline const char *au_sbtype(struct super_block *sb)
  16129. +{
  16130. + return sb->s_type->name;
  16131. +}
  16132. +
  16133. +static inline int au_is_aufs(struct super_block *sb)
  16134. +{
  16135. + return !strcmp(au_sbtype(sb), AUFS_FSTYPE);
  16136. +}
  16137. +
  16138. +static inline int au_is_nfs(struct super_block *sb)
  16139. +{
  16140. +#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
  16141. + return !strcmp(au_sbtype(sb), "nfs");
  16142. +#else
  16143. + return 0;
  16144. +#endif
  16145. +}
  16146. +
  16147. +static inline int au_is_remote(struct super_block *sb)
  16148. +{
  16149. + return au_is_nfs(sb);
  16150. +}
  16151. +
  16152. +#ifdef CONFIG_AUFS_EXPORT
  16153. +static inline void au_init_export_op(struct super_block *sb)
  16154. +{
  16155. + extern struct export_operations aufs_export_op;
  16156. + sb->s_export_op = &aufs_export_op;
  16157. +}
  16158. +
  16159. +static inline int au_is_nfsd(struct task_struct *tsk)
  16160. +{
  16161. + return (!tsk->mm && !strcmp(tsk->comm, "nfsd"));
  16162. +}
  16163. +
  16164. +static inline void au_nfsd_lockdep_off(void)
  16165. +{
  16166. + /* braces are added to stop a warning */
  16167. + if (au_is_nfsd(current)) {
  16168. + lockdep_off();
  16169. + }
  16170. +}
  16171. +
  16172. +static inline void au_nfsd_lockdep_on(void)
  16173. +{
  16174. + /* braces are added to stop a warning */
  16175. + if (au_is_nfsd(current)) {
  16176. + lockdep_on();
  16177. + }
  16178. +}
  16179. +#else
  16180. +static inline int au_is_nfsd(struct task_struct *tsk)
  16181. +{
  16182. + return 0;
  16183. +}
  16184. +static inline void au_init_export_op(struct super_block *sb)
  16185. +{
  16186. + /* nothing */
  16187. +}
  16188. +#define au_nfsd_lockdep_off() /* */
  16189. +#define au_nfsd_lockdep_on() /* */
  16190. +#endif /* CONFIG_AUFS_EXPORT */
  16191. +
  16192. +static inline void init_lvma(struct aufs_sbinfo *sbinfo)
  16193. +{
  16194. +#ifdef CONFIG_AUFS_ROBR
  16195. + spin_lock_init(&sbinfo->si_lvma_lock);
  16196. + INIT_LIST_HEAD(&sbinfo->si_lvma);
  16197. +#else
  16198. + /* nothing */
  16199. +#endif
  16200. +}
  16201. +
  16202. +/* limited support before 2.6.18 */
  16203. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
  16204. +static inline void au_mntget(struct super_block *sb)
  16205. +{
  16206. + mntget(stosi(sb)->si_mnt);
  16207. +}
  16208. +
  16209. +static inline void au_mntput(struct super_block *sb)
  16210. +{
  16211. + mntput(stosi(sb)->si_mnt);
  16212. +}
  16213. +#else
  16214. +static inline void au_mntget(struct super_block *sb)
  16215. +{
  16216. + /* empty */
  16217. +}
  16218. +
  16219. +static inline void au_mntput(struct super_block *sb)
  16220. +{
  16221. + /* empty */
  16222. +}
  16223. +#endif
  16224. +
  16225. +/* ---------------------------------------------------------------------- */
  16226. +
  16227. +static inline void au_flag_set(struct super_block *sb, unsigned int flag)
  16228. +{
  16229. + //SiMustWriteLock(sb);
  16230. + stosi(sb)->si_flags |= flag;
  16231. +}
  16232. +
  16233. +static inline void au_flag_clr(struct super_block *sb, unsigned int flag)
  16234. +{
  16235. + //SiMustWriteLock(sb);
  16236. + stosi(sb)->si_flags &= ~flag;
  16237. +}
  16238. +
  16239. +static inline
  16240. +unsigned int au_flag_test(struct super_block *sb, unsigned int flag)
  16241. +{
  16242. + //SiMustAnyLock(sb);
  16243. + return stosi(sb)->si_flags & flag;
  16244. +}
  16245. +
  16246. +static inline unsigned int au_flag_test_udba(struct super_block *sb)
  16247. +{
  16248. + return au_flag_test(sb, AuMask_UDBA);
  16249. +}
  16250. +
  16251. +static inline unsigned int au_flag_test_coo(struct super_block *sb)
  16252. +{
  16253. + return au_flag_test(sb, AuMask_COO);
  16254. +}
  16255. +
  16256. +/* ---------------------------------------------------------------------- */
  16257. +
  16258. +/* lock superblock. mainly for entry point functions */
  16259. +/*
  16260. + * si_read_lock, si_write_lock,
  16261. + * si_read_unlock, si_write_unlock, si_downgrade_lock
  16262. + */
  16263. +SimpleRwsemFuncs(si, struct super_block *sb, stosi(sb)->si_rwsem);
  16264. +
  16265. +/* to debug easier, do not make them inlined functions */
  16266. +#define SiMustReadLock(sb) RwMustReadLock(&stosi(sb)->si_rwsem)
  16267. +#define SiMustWriteLock(sb) RwMustWriteLock(&stosi(sb)->si_rwsem)
  16268. +#define SiMustAnyLock(sb) RwMustAnyLock(&stosi(sb)->si_rwsem)
  16269. +
  16270. +#endif /* __KERNEL__ */
  16271. +#endif /* __AUFS_SUPER_H__ */
  16272. diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
  16273. new file mode 100755
  16274. index 0000000..d686862
  16275. --- /dev/null
  16276. +++ b/fs/aufs/sysaufs.c
  16277. @@ -0,0 +1,620 @@
  16278. +/*
  16279. + * Copyright (C) 2007 Junjiro Okajima
  16280. + *
  16281. + * This program, aufs is free software; you can redistribute it and/or modify
  16282. + * it under the terms of the GNU General Public License as published by
  16283. + * the Free Software Foundation; either version 2 of the License, or
  16284. + * (at your option) any later version.
  16285. + *
  16286. + * This program is distributed in the hope that it will be useful,
  16287. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16288. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16289. + * GNU General Public License for more details.
  16290. + *
  16291. + * You should have received a copy of the GNU General Public License
  16292. + * along with this program; if not, write to the Free Software
  16293. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16294. + */
  16295. +
  16296. +/* $Id: sysaufs.c,v 1.6 2007/05/14 03:40:10 sfjro Exp $ */
  16297. +
  16298. +#include <linux/module.h>
  16299. +#include <linux/seq_file.h>
  16300. +#include <linux/sysfs.h>
  16301. +#include "aufs.h"
  16302. +
  16303. +/* ---------------------------------------------------------------------- */
  16304. +
  16305. +/* super_blocks list is not exported */
  16306. +static DEFINE_MUTEX(aufs_sbilist_mtx);
  16307. +static LIST_HEAD(aufs_sbilist);
  16308. +
  16309. +/* ---------------------------------------------------------------------- */
  16310. +
  16311. +typedef ssize_t (*rwfunc_t)(struct kobject *kobj, char *buf, loff_t offset,
  16312. + size_t sz, struct sysaufs_args *args);
  16313. +static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
  16314. + size_t sz, struct sysaufs_args *args);
  16315. +static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf, loff_t
  16316. + offset, size_t sz, struct sysaufs_args *args);
  16317. +
  16318. +#define GFunc(name, _index, func) \
  16319. +static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
  16320. +{ \
  16321. + struct sysaufs_args args = { \
  16322. + .index = (_index), \
  16323. + .mtx = &aufs_sbilist_mtx, \
  16324. + .sb = NULL \
  16325. + }; \
  16326. + return func(kobj, buf, offset, sz, &args); \
  16327. +}
  16328. +
  16329. +#define GFuncs(name, _index) \
  16330. + GFunc(read_##name, _index, sysaufs_read); \
  16331. + GFunc(write_##name, _index, sysaufs_free_write);
  16332. +
  16333. +static struct super_block *find_sb_locked(struct kobject *kobj)
  16334. +{
  16335. + struct super_block *sb;
  16336. + struct aufs_sbinfo *sbinfo;
  16337. +
  16338. + TraceEnter();
  16339. + MtxMustLock(&aufs_sbilist_mtx);
  16340. +
  16341. + sb = NULL;
  16342. + list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
  16343. + if (&au_subsys_to_kset(sbinfo->si_sysaufs.subsys).kobj != kobj)
  16344. + continue;
  16345. + sb = sbinfo->si_mnt->mnt_sb;
  16346. + si_read_lock(sb);
  16347. + break;
  16348. + }
  16349. + return sb;
  16350. +}
  16351. +
  16352. +static ssize_t sb_func(struct kobject *kobj, char *buf, loff_t offset,
  16353. + size_t sz, struct sysaufs_args *args, rwfunc_t func)
  16354. +{
  16355. + ssize_t err;
  16356. +
  16357. + err = -ENOENT;
  16358. + mutex_lock(&aufs_sbilist_mtx);
  16359. + args->sb = find_sb_locked(kobj);
  16360. + if (args->sb) {
  16361. + err = func(kobj, buf, offset, sz, args);
  16362. + si_read_unlock(args->sb);
  16363. + }
  16364. + mutex_unlock(&aufs_sbilist_mtx);
  16365. + return err;
  16366. +}
  16367. +
  16368. +#define SbFunc(name, _index, func) \
  16369. +static ssize_t name(struct kobject *kobj, char *buf, loff_t offset, size_t sz) \
  16370. +{ \
  16371. + struct sysaufs_args args = { \
  16372. + .index = (_index), \
  16373. + .mtx = NULL \
  16374. + }; \
  16375. + return sb_func(kobj, buf, offset, sz, &args, func); \
  16376. +}
  16377. +
  16378. +#define SbFuncs(name, index) \
  16379. + SbFunc(read_##name, index, sysaufs_read); \
  16380. + SbFunc(write_##name, index, sysaufs_free_write)
  16381. +
  16382. +static decl_subsys(aufs, NULL, NULL);
  16383. +enum {Brs, Stat, Config, _Last};
  16384. +static struct sysaufs_entry g_array[_Last];
  16385. +GFuncs(brs, Brs);
  16386. +GFuncs(stat, Stat);
  16387. +GFuncs(config, Config);
  16388. +
  16389. +SbFuncs(xino, SysaufsSb_XINO);
  16390. +
  16391. +#define SetEntry(e, _name, init_size, _ops) \
  16392. + do { \
  16393. + (e)->attr.attr.name = #_name; \
  16394. + (e)->attr.attr.owner = THIS_MODULE; \
  16395. + (e)->attr.attr.mode = S_IRUGO | S_IWUSR; \
  16396. + (e)->attr.read = read_##_name; \
  16397. + (e)->attr.write = write_##_name; \
  16398. + (e)->allocated = init_size; \
  16399. + (e)->err = -1; \
  16400. + (e)->ops = _ops; \
  16401. + } while (0)
  16402. +
  16403. +#define Priv(e) (e)->attr.private
  16404. +#define Allocated(e) (e)->allocated
  16405. +#define Len(e) (e)->attr.size
  16406. +#define Name(e) attr_name((e)->attr)
  16407. +
  16408. +/* ---------------------------------------------------------------------- */
  16409. +
  16410. +static void free_entry(struct sysaufs_entry *e)
  16411. +{
  16412. + MtxMustLock(&aufs_sbilist_mtx);
  16413. + DEBUG_ON(!Priv(e));
  16414. +
  16415. + if (Allocated(e) > 0)
  16416. + kfree(Priv(e));
  16417. + else
  16418. + free_pages((unsigned long)Priv(e), -Allocated(e));
  16419. + Priv(e) = NULL;
  16420. + Len(e) = 0;
  16421. +}
  16422. +
  16423. +static void free_entries(void)
  16424. +{
  16425. + static int a[] = {Brs, -1};
  16426. + int *p = a;
  16427. +
  16428. + MtxMustLock(&aufs_sbilist_mtx);
  16429. +
  16430. + while (*p >= 0) {
  16431. + if (Priv(g_array + *p))
  16432. + free_entry(g_array + *p);
  16433. + p++;
  16434. + }
  16435. +}
  16436. +
  16437. +static int alloc_entry(struct sysaufs_entry *e)
  16438. +{
  16439. + MtxMustLock(&aufs_sbilist_mtx);
  16440. + DEBUG_ON(Priv(e));
  16441. + //Dbg("%d\n", Allocated(e));
  16442. +
  16443. + if (Allocated(e) > 0)
  16444. + Priv(e) = kmalloc(Allocated(e), GFP_KERNEL);
  16445. + else
  16446. + Priv(e) = (void*)__get_free_pages(GFP_KERNEL, -Allocated(e));
  16447. + if (Priv(e))
  16448. + return 0;
  16449. + return -ENOMEM;
  16450. +}
  16451. +
  16452. +/* ---------------------------------------------------------------------- */
  16453. +
  16454. +static void unreg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
  16455. + au_subsys_t *parent)
  16456. +{
  16457. + int i;
  16458. +
  16459. + TraceEnter();
  16460. +
  16461. + for (i = 0; i < n; i++, a++)
  16462. + if (!a->err) {
  16463. + sysfs_remove_bin_file
  16464. + (&au_subsys_to_kset(*subsys).kobj, &a->attr);
  16465. + if (Priv(a))
  16466. + free_entry(a);
  16467. + }
  16468. +
  16469. + subsystem_unregister(subsys);
  16470. + subsys_put(parent);
  16471. +}
  16472. +
  16473. +static int reg(au_subsys_t *subsys, struct sysaufs_entry *a, int n,
  16474. + au_subsys_t *parent)
  16475. +{
  16476. + int err, i;
  16477. +
  16478. + TraceEnter();
  16479. +
  16480. + subsys_get(parent);
  16481. + kobj_set_kset_s(&au_subsys_to_kset(*subsys), *parent);
  16482. + err = subsystem_register(subsys);
  16483. + if (unlikely(err))
  16484. + goto out;
  16485. +
  16486. + for (i = 0; !err && i < n; i++)
  16487. + err = a[i].err = sysfs_create_bin_file
  16488. + (&au_subsys_to_kset(*subsys).kobj, &a[i].attr);
  16489. + if (unlikely(err))
  16490. + unreg(subsys, a, n, parent);
  16491. +
  16492. + out:
  16493. + TraceErr(err);
  16494. + return err;
  16495. +}
  16496. +
  16497. +/* ---------------------------------------------------------------------- */
  16498. +
  16499. +#define SbSetEntry(index, name, init_size) \
  16500. + SetEntry(sa->array + index, name, init_size, au_si_ops);
  16501. +
  16502. +void sysaufs_add(struct aufs_sbinfo *sbinfo)
  16503. +{
  16504. + int err;
  16505. + struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
  16506. +
  16507. + TraceEnter();
  16508. +
  16509. + mutex_lock(&aufs_sbilist_mtx);
  16510. + list_add_tail(&sbinfo->si_list, &aufs_sbilist);
  16511. + free_entries();
  16512. +
  16513. + memset(sa, 0, sizeof(*sa));
  16514. + SbSetEntry(SysaufsSb_XINO, xino, 128);
  16515. + err = kobject_set_name(&au_subsys_to_kset(sa->subsys).kobj, "%p",
  16516. + sbinfo->si_mnt->mnt_sb);
  16517. + if (!err)
  16518. + err = reg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array),
  16519. + &aufs_subsys);
  16520. + if (unlikely(err))
  16521. + Warn("failed adding sysfs (%d)\n", err);
  16522. +
  16523. + mutex_unlock(&aufs_sbilist_mtx);
  16524. +}
  16525. +
  16526. +void sysaufs_del(struct aufs_sbinfo *sbinfo)
  16527. +{
  16528. + struct sysaufs_sbinfo *sa = &sbinfo->si_sysaufs;
  16529. +
  16530. + TraceEnter();
  16531. +
  16532. + mutex_lock(&aufs_sbilist_mtx);
  16533. + unreg(&sa->subsys, sa->array, ARRAY_SIZE(sa->array), &aufs_subsys);
  16534. + list_del(&sbinfo->si_list);
  16535. + free_entries();
  16536. + mutex_unlock(&aufs_sbilist_mtx);
  16537. +}
  16538. +
  16539. +void sysaufs_notify_remount(void)
  16540. +{
  16541. + mutex_lock(&aufs_sbilist_mtx);
  16542. + free_entries();
  16543. + mutex_unlock(&aufs_sbilist_mtx);
  16544. +}
  16545. +
  16546. +/* ---------------------------------------------------------------------- */
  16547. +
  16548. +static int make_brs(struct seq_file *seq, struct sysaufs_args *args,
  16549. + int *do_size)
  16550. +{
  16551. + int err;
  16552. + struct aufs_sbinfo *sbinfo;
  16553. +
  16554. + TraceEnter();
  16555. + MtxMustLock(&aufs_sbilist_mtx);
  16556. + DEBUG_ON(args->index != Brs);
  16557. +
  16558. + err = 0;
  16559. + list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
  16560. + struct super_block *sb;
  16561. + struct dentry *root;
  16562. + struct vfsmount *mnt;
  16563. +
  16564. + sb = sbinfo->si_mnt->mnt_sb;
  16565. + root = sb->s_root;
  16566. + aufs_read_lock(root, !AUFS_I_RLOCK);
  16567. + mnt = sbinfo->si_mnt;
  16568. + err = seq_escape
  16569. + (seq, mnt->mnt_devname ? mnt->mnt_devname : "none",
  16570. + au_esc_chars);
  16571. + if (!err)
  16572. + err = seq_putc(seq, ' ');
  16573. + if (!err)
  16574. + err = seq_path(seq, mnt, root, au_esc_chars);
  16575. + if (err > 0)
  16576. + err = seq_printf(seq, " %p br:", sb);
  16577. + if (!err)
  16578. + err = au_show_brs(seq, sb);
  16579. + aufs_read_unlock(root, !AUFS_I_RLOCK);
  16580. + if (!err)
  16581. + err = seq_putc(seq, '\n');
  16582. + else
  16583. + break;
  16584. + }
  16585. +
  16586. + TraceErr(err);
  16587. + return err;
  16588. +}
  16589. +
  16590. +static int make_config(struct seq_file *seq, struct sysaufs_args *args,
  16591. + int *do_size)
  16592. +{
  16593. + int err;
  16594. +
  16595. + TraceEnter();
  16596. + DEBUG_ON(args->index != Config);
  16597. +
  16598. +#ifdef CONFIG_AUFS
  16599. + err = seq_puts(seq, "CONFIG_AUFS=y\n");
  16600. +#else
  16601. + err = seq_puts(seq, "CONFIG_AUFS=m\n");
  16602. +#endif
  16603. +
  16604. +#define puts(m, v) \
  16605. + if (!err) err = seq_puts(seq, "CONFIG_AUFS_" #m "=" #v "\n")
  16606. +#define puts_bool(m) puts(m, y)
  16607. +#define puts_mod(m) puts(m, m)
  16608. +
  16609. +#ifdef CONFIG_AUFS_FAKE_DM
  16610. + puts_bool(FAKE_DM);
  16611. +#endif
  16612. +#ifdef CONFIG_AUFS_BRANCH_MAX_127
  16613. + puts_bool(BRANCH_MAX_127);
  16614. +#elif defined(CONFIG_AUFS_BRANCH_MAX_511)
  16615. + puts_bool(BRANCH_MAX_511);
  16616. +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
  16617. + puts_bool(BRANCH_MAX_1023);
  16618. +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
  16619. + puts_bool(BRANCH_MAX_32767);
  16620. +#endif
  16621. + puts_bool(SYSAUFS);
  16622. +#ifdef CONFIG_AUFS_HINOTIFY
  16623. + puts_bool(HINOTIFY);
  16624. +#endif
  16625. +#ifdef CONFIG_AUFS_EXPORT
  16626. + puts_bool(EXPORT);
  16627. +#endif
  16628. +#ifdef CONFIG_AUFS_ROBR
  16629. + puts_bool(ROBR);
  16630. +#endif
  16631. +#ifdef CONFIG_AUFS_DLGT
  16632. + puts_bool(DLGT);
  16633. +#endif
  16634. +#ifdef CONFIG_AUFS_LHASH_PATCH
  16635. + puts_bool(LHASH_PATCH);
  16636. +#endif
  16637. +#ifdef CONFIG_AUFS_KSIZE_PATCH
  16638. + puts_bool(KSIZE_PATCH);
  16639. +#endif
  16640. +#ifdef CONFIG_AUFS_DEBUG
  16641. + puts_bool(DEBUG);
  16642. +#endif
  16643. +#ifdef CONFIG_AUFS_COMPAT
  16644. + puts_bool(COMPAT);
  16645. +#endif
  16646. +
  16647. +#undef puts_bool
  16648. +#undef puts
  16649. +
  16650. + TraceErr(err);
  16651. + return err;
  16652. +}
  16653. +
  16654. +static int make_stat(struct seq_file *seq, struct sysaufs_args *args,
  16655. + int *do_size)
  16656. +{
  16657. + int err, i;
  16658. +
  16659. + TraceEnter();
  16660. + DEBUG_ON(args->index != Stat);
  16661. +
  16662. + *do_size = 0;
  16663. + err = seq_puts(seq, "wkq max_busy:");
  16664. + for (i = 0; !err && i < aufs_nwkq; i++)
  16665. + err = seq_printf(seq, " %u", au_wkq[i].max_busy);
  16666. + if (!err)
  16667. + err = seq_printf(seq, ", %u(generic)\n",
  16668. + au_wkq[aufs_nwkq].max_busy);
  16669. + TraceErr(err);
  16670. + return err;
  16671. +}
  16672. +
  16673. +/* ---------------------------------------------------------------------- */
  16674. +
  16675. +static int make(struct sysaufs_entry *e, struct sysaufs_args *args,
  16676. + int *do_size)
  16677. +
  16678. +{
  16679. + int err;
  16680. + struct seq_file *seq;
  16681. +
  16682. + TraceEnter();
  16683. + DEBUG_ON(Priv(e));
  16684. + MtxMustLock(&aufs_sbilist_mtx);
  16685. +
  16686. + err = -ENOMEM;
  16687. + seq = kzalloc(sizeof(*seq), GFP_KERNEL);
  16688. + if (unlikely(!seq))
  16689. + goto out;
  16690. +
  16691. + Len(e) = 0;
  16692. + while (1) {
  16693. + err = alloc_entry(e);
  16694. + if (unlikely(err))
  16695. + break;
  16696. +
  16697. + //mutex_init(&seq.lock);
  16698. + seq->buf = Priv(e);
  16699. + seq->count = 0;
  16700. + seq->size = Allocated(e);
  16701. + if (unlikely(Allocated(e) <= 0))
  16702. + seq->size = PAGE_SIZE << -Allocated(e);
  16703. +
  16704. + err = e->ops[args->index](seq, args, do_size);
  16705. + if (!err) {
  16706. + Len(e) = seq->count;
  16707. + break; /* success */
  16708. + }
  16709. +
  16710. + free_entry(e);
  16711. + if (Allocated(e) > 0) {
  16712. + Allocated(e) <<= 1;
  16713. + if (unlikely(Allocated(e) >= (int)PAGE_SIZE))
  16714. + Allocated(e) = 0;
  16715. + } else
  16716. + Allocated(e)--;
  16717. + //Dbg("%d\n", Allocated(e));
  16718. + }
  16719. + kfree(seq);
  16720. +
  16721. + out:
  16722. + TraceErr(err);
  16723. + return err;
  16724. +}
  16725. +
  16726. +/* why does sysfs pass my parent kobject? */
  16727. +static struct dentry *find_me(struct dentry *parent, struct sysaufs_entry *e)
  16728. +{
  16729. +#if 1
  16730. + struct dentry *dentry;
  16731. + const char *name = Name(e);
  16732. + const unsigned int len = strlen(name);
  16733. +
  16734. + //Dbg("%.*s\n", DLNPair(parent));
  16735. + spin_lock(&dcache_lock);
  16736. + list_for_each_entry(dentry, &parent->d_subdirs, D_CHILD) {
  16737. + //Dbg("%.*s\n", DLNPair(dentry));
  16738. + if (len == dentry->d_name.len
  16739. + && !strcmp(dentry->d_name.name, name)) {
  16740. + spin_unlock(&dcache_lock);
  16741. + return dentry;
  16742. + }
  16743. + }
  16744. + spin_unlock(&dcache_lock);
  16745. +#endif
  16746. + return NULL;
  16747. +}
  16748. +
  16749. +static ssize_t sysaufs_read(struct kobject *kobj, char *buf, loff_t offset,
  16750. + size_t sz, struct sysaufs_args *args)
  16751. +{
  16752. + ssize_t err;
  16753. + loff_t len;
  16754. + struct dentry *d;
  16755. + struct sysaufs_entry *e;
  16756. + int do_size;
  16757. +
  16758. + LKTRTrace("{%d, %p}, offset %Ld, sz %lu\n",
  16759. + args->index, args->sb, offset, (unsigned long)sz);
  16760. +
  16761. + if (unlikely(!sz))
  16762. + return 0;
  16763. +
  16764. + err = 0;
  16765. + d = NULL;
  16766. + e = g_array + args->index;
  16767. + if (args->sb)
  16768. + e = stosi(args->sb)->si_sysaufs.array + args->index;
  16769. +
  16770. + do_size = 1;
  16771. + if (args->mtx)
  16772. + mutex_lock(args->mtx);
  16773. + if (unlikely(!Priv(e))) {
  16774. + err = make(e, args, &do_size);
  16775. + DEBUG_ON(Len(e) > INT_MAX);
  16776. + if (do_size) {
  16777. + d = find_me(kobj->dentry, e);
  16778. + if (d)
  16779. + i_size_write(d->d_inode, Len(e));
  16780. + }
  16781. + }
  16782. +
  16783. + if (!err) {
  16784. + err = len = Len(e) - offset;
  16785. + LKTRTrace("%Ld\n", len);
  16786. + if (len > 0) {
  16787. + if (len > sz)
  16788. + err = sz;
  16789. + memcpy(buf, Priv(e) + offset, err);
  16790. + }
  16791. +
  16792. + if (!do_size)
  16793. + free_entry(e);
  16794. + }
  16795. + if (args->mtx)
  16796. + mutex_unlock(args->mtx);
  16797. +
  16798. + TraceErr(err);
  16799. + return err;
  16800. +}
  16801. +
  16802. +static ssize_t sysaufs_free_write(struct kobject *kobj, char *buf,
  16803. + loff_t offset, size_t sz,
  16804. + struct sysaufs_args *args)
  16805. +{
  16806. + struct dentry *d;
  16807. + int allocated, len;
  16808. + struct sysaufs_entry *e;
  16809. +
  16810. + LKTRTrace("{%d, %p}\n", args->index, args->sb);
  16811. +
  16812. + e = g_array + args->index;
  16813. + if (args->sb)
  16814. + e = stosi(args->sb)->si_sysaufs.array + args->index;
  16815. +
  16816. + if (args->mtx)
  16817. + mutex_lock(args->mtx);
  16818. + if (Priv(e)) {
  16819. + allocated = Allocated(e);
  16820. + if (unlikely(allocated <= 0))
  16821. + allocated = PAGE_SIZE << -allocated;
  16822. + allocated >>= 1;
  16823. + len = Len(e);
  16824. +
  16825. + free_entry(e);
  16826. + if (unlikely(len <= allocated)) {
  16827. + if (Allocated(e) >= 0)
  16828. + Allocated(e) = allocated;
  16829. + else
  16830. + Allocated(e)++;
  16831. + }
  16832. +
  16833. + d = find_me(kobj->dentry, e);
  16834. + if (d && i_size_read(d->d_inode))
  16835. + i_size_write(d->d_inode, 0);
  16836. + }
  16837. + if (args->mtx)
  16838. + mutex_unlock(args->mtx);
  16839. +
  16840. + return sz;
  16841. +}
  16842. +
  16843. +static sysaufs_op g_ops[] = {
  16844. + [Brs] = make_brs,
  16845. + [Stat] = make_stat,
  16846. + [Config] = make_config
  16847. +};
  16848. +
  16849. +/* ---------------------------------------------------------------------- */
  16850. +
  16851. +#define GSetEntry(index, name, init_size) \
  16852. + SetEntry(g_array + index, name, init_size, g_ops)
  16853. +
  16854. +int __init sysaufs_init(void)
  16855. +{
  16856. + int err;
  16857. +
  16858. + GSetEntry(Brs, brs, 128);
  16859. + GSetEntry(Stat, stat, 32);
  16860. + GSetEntry(Config, config, 256);
  16861. + err = reg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
  16862. + TraceErr(err);
  16863. + return err;
  16864. +}
  16865. +
  16866. +void __exit sysaufs_fin(void)
  16867. +{
  16868. + mutex_lock(&aufs_sbilist_mtx);
  16869. + unreg(&aufs_subsys, g_array, ARRAY_SIZE(g_array), &fs_subsys);
  16870. + mutex_unlock(&aufs_sbilist_mtx);
  16871. +}
  16872. +
  16873. +/* ---------------------------------------------------------------------- */
  16874. +
  16875. +#ifdef DbgDlgt
  16876. +int is_branch(struct super_block *h_sb)
  16877. +{
  16878. + int found = 0;
  16879. + struct aufs_sbinfo *sbinfo;
  16880. +
  16881. + //Dbg("here\n");
  16882. + mutex_lock(&aufs_sbilist_mtx);
  16883. + list_for_each_entry(sbinfo, &aufs_sbilist, si_list) {
  16884. + aufs_bindex_t bindex, bend;
  16885. + struct super_block *sb;
  16886. +
  16887. + sb = sbinfo->si_mnt->mnt_sb;
  16888. + si_read_lock(sb);
  16889. + bend = sbend(sb);
  16890. + for (bindex = 0; !found && bindex <= bend; bindex++)
  16891. + found = (h_sb == sbr_sb(sb, bindex));
  16892. + si_read_unlock(sb);
  16893. + }
  16894. + mutex_unlock(&aufs_sbilist_mtx);
  16895. + return found;
  16896. +}
  16897. +#endif
  16898. diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
  16899. new file mode 100755
  16900. index 0000000..cf0247f
  16901. --- /dev/null
  16902. +++ b/fs/aufs/sysaufs.h
  16903. @@ -0,0 +1,83 @@
  16904. +/*
  16905. + * Copyright (C) 2007 Junjiro Okajima
  16906. + *
  16907. + * This program, aufs is free software; you can redistribute it and/or modify
  16908. + * it under the terms of the GNU General Public License as published by
  16909. + * the Free Software Foundation; either version 2 of the License, or
  16910. + * (at your option) any later version.
  16911. + *
  16912. + * This program is distributed in the hope that it will be useful,
  16913. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16914. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16915. + * GNU General Public License for more details.
  16916. + *
  16917. + * You should have received a copy of the GNU General Public License
  16918. + * along with this program; if not, write to the Free Software
  16919. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16920. + */
  16921. +
  16922. +/* $Id: sysaufs.h,v 1.3 2007/05/14 06:27:18 sfjro Exp $ */
  16923. +
  16924. +#ifndef __SYSAUFS_H__
  16925. +#define __SYSAUFS_H__
  16926. +
  16927. +#ifdef __KERNEL__
  16928. +
  16929. +#include <linux/seq_file.h>
  16930. +#include <linux/sysfs.h>
  16931. +#include <linux/version.h>
  16932. +
  16933. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
  16934. +typedef struct kset au_subsys_t;
  16935. +#define au_subsys_to_kset(subsys) (subsys)
  16936. +#else
  16937. +typedef struct subsystem au_subsys_t;
  16938. +#define au_subsys_to_kset(subsys) ((subsys).kset)
  16939. +#endif
  16940. +
  16941. +/* ---------------------------------------------------------------------- */
  16942. +
  16943. +/* arguments for an entry under sysfs */
  16944. +struct sysaufs_args {
  16945. + int index;
  16946. + struct mutex *mtx;
  16947. + struct super_block *sb;
  16948. +};
  16949. +
  16950. +typedef int (*sysaufs_op)(struct seq_file *seq, struct sysaufs_args *args,
  16951. + int *do_size);
  16952. +
  16953. +/* an entry under sysfs */
  16954. +struct sysaufs_entry {
  16955. + struct bin_attribute attr;
  16956. + int allocated; /* zero minus means pages */
  16957. + int err;
  16958. + sysaufs_op *ops;
  16959. +};
  16960. +
  16961. +/* ---------------------------------------------------------------------- */
  16962. +
  16963. +struct aufs_sbinfo;
  16964. +#ifdef CONFIG_AUFS_SYSAUFS
  16965. +void sysaufs_add(struct aufs_sbinfo *sbinfo);
  16966. +void sysaufs_del(struct aufs_sbinfo *sbinfo);
  16967. +int __init sysaufs_init(void);
  16968. +void sysaufs_fin(void);
  16969. +void sysaufs_notify_remount(void);
  16970. +#else
  16971. +static inline void sysaufs_add(struct aufs_sbinfo *sbinfo)
  16972. +{
  16973. + /* nothing */
  16974. +}
  16975. +
  16976. +static inline void sysaufs_del(struct aufs_sbinfo *sbinfo)
  16977. +{
  16978. + /* nothing */
  16979. +}
  16980. +#define sysaufs_init() 0
  16981. +#define sysaufs_fin() /* */
  16982. +#define sysaufs_notify_remount() /* */
  16983. +#endif /* CONFIG_AUFS_SYSAUFS */
  16984. +
  16985. +#endif /* __KERNEL__ */
  16986. +#endif /* __SYSAUFS_H__ */
  16987. diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c
  16988. new file mode 100755
  16989. index 0000000..8e99b7d
  16990. --- /dev/null
  16991. +++ b/fs/aufs/vdir.c
  16992. @@ -0,0 +1,802 @@
  16993. +/*
  16994. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  16995. + *
  16996. + * This program, aufs is free software; you can redistribute it and/or modify
  16997. + * it under the terms of the GNU General Public License as published by
  16998. + * the Free Software Foundation; either version 2 of the License, or
  16999. + * (at your option) any later version.
  17000. + *
  17001. + * This program is distributed in the hope that it will be useful,
  17002. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17003. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17004. + * GNU General Public License for more details.
  17005. + *
  17006. + * You should have received a copy of the GNU General Public License
  17007. + * along with this program; if not, write to the Free Software
  17008. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17009. + */
  17010. +
  17011. +/* $Id: vdir.c,v 1.22 2007/05/14 03:38:52 sfjro Exp $ */
  17012. +
  17013. +#include "aufs.h"
  17014. +
  17015. +static int calc_size(int namelen)
  17016. +{
  17017. + int sz;
  17018. +
  17019. + sz = sizeof(struct aufs_de) + namelen;
  17020. + if (sizeof(ino_t) == sizeof(long)) {
  17021. + const int mask = sizeof(ino_t) - 1;
  17022. + if (sz & mask) {
  17023. + sz += sizeof(ino_t);
  17024. + sz &= ~mask;
  17025. + }
  17026. + } else {
  17027. +#if 0 // remove
  17028. + BUG();
  17029. + // this block will be discarded by optimizer.
  17030. + int m;
  17031. + m = sz % sizeof(ino_t);
  17032. + if (m)
  17033. + sz += sizeof(ino_t) - m;
  17034. +#endif
  17035. + }
  17036. +
  17037. + DEBUG_ON(sz % sizeof(ino_t));
  17038. + return sz;
  17039. +}
  17040. +
  17041. +static int set_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
  17042. +{
  17043. + if (calc_size(0) <= deblk_end->p - p->p) {
  17044. + p->de->de_str.len = 0;
  17045. + //smp_mb();
  17046. + return 0;
  17047. + }
  17048. + return -1; // error
  17049. +}
  17050. +
  17051. +/* returns true or false */
  17052. +static int is_deblk_end(union aufs_deblk_p *p, union aufs_deblk_p *deblk_end)
  17053. +{
  17054. + if (calc_size(0) <= deblk_end->p - p->p)
  17055. + return !p->de->de_str.len;
  17056. + return 1;
  17057. +}
  17058. +
  17059. +static aufs_deblk_t *last_deblk(struct aufs_vdir *vdir)
  17060. +{
  17061. + return vdir->vd_deblk[vdir->vd_nblk - 1];
  17062. +}
  17063. +
  17064. +void nhash_init(struct aufs_nhash *nhash)
  17065. +{
  17066. + int i;
  17067. + for (i = 0; i < AUFS_NHASH_SIZE; i++)
  17068. + INIT_HLIST_HEAD(nhash->heads + i);
  17069. +}
  17070. +
  17071. +struct aufs_nhash *nhash_new(gfp_t gfp)
  17072. +{
  17073. + struct aufs_nhash *nhash;
  17074. +
  17075. + nhash = kmalloc(sizeof(*nhash), gfp);
  17076. + if (nhash) {
  17077. + nhash_init(nhash);
  17078. + return nhash;
  17079. + }
  17080. + return ERR_PTR(-ENOMEM);
  17081. +}
  17082. +
  17083. +void nhash_del(struct aufs_nhash *nhash)
  17084. +{
  17085. + nhash_fin(nhash);
  17086. + kfree(nhash);
  17087. +}
  17088. +
  17089. +void nhash_move(struct aufs_nhash *dst, struct aufs_nhash *src)
  17090. +{
  17091. + int i;
  17092. +
  17093. + TraceEnter();
  17094. +
  17095. + //DbgWhlist(src);
  17096. + *dst = *src;
  17097. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17098. + struct hlist_head *h;
  17099. + h = dst->heads + i;
  17100. + if (h->first)
  17101. + h->first->pprev = &h->first;
  17102. + INIT_HLIST_HEAD(src->heads + i);
  17103. + }
  17104. + //DbgWhlist(src);
  17105. + //DbgWhlist(dst);
  17106. + //smp_mb();
  17107. +}
  17108. +
  17109. +/* ---------------------------------------------------------------------- */
  17110. +
  17111. +void nhash_fin(struct aufs_nhash *whlist)
  17112. +{
  17113. + int i;
  17114. + struct hlist_head *head;
  17115. + struct aufs_wh *tpos;
  17116. + struct hlist_node *pos, *n;
  17117. +
  17118. + TraceEnter();
  17119. +
  17120. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17121. + head = whlist->heads + i;
  17122. + hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
  17123. + //hlist_del(pos);
  17124. + kfree(tpos);
  17125. + }
  17126. + }
  17127. +}
  17128. +
  17129. +int is_longer_wh(struct aufs_nhash *whlist, aufs_bindex_t btgt, int limit)
  17130. +{
  17131. + int n, i;
  17132. + struct hlist_head *head;
  17133. + struct aufs_wh *tpos;
  17134. + struct hlist_node *pos;
  17135. +
  17136. + LKTRTrace("limit %d\n", limit);
  17137. + //return 1;
  17138. +
  17139. + n = 0;
  17140. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17141. + head = whlist->heads + i;
  17142. + hlist_for_each_entry(tpos, pos, head, wh_hash)
  17143. + if (tpos->wh_bindex == btgt && ++n > limit)
  17144. + return 1;
  17145. + }
  17146. + return 0;
  17147. +}
  17148. +
  17149. +/* returns found(true) or not */
  17150. +int test_known_wh(struct aufs_nhash *whlist, char *name, int namelen)
  17151. +{
  17152. + struct hlist_head *head;
  17153. + struct aufs_wh *tpos;
  17154. + struct hlist_node *pos;
  17155. + struct aufs_destr *str;
  17156. +
  17157. + LKTRTrace("%.*s\n", namelen, name);
  17158. +
  17159. + head = whlist->heads + au_name_hash(name, namelen);
  17160. + hlist_for_each_entry(tpos, pos, head, wh_hash) {
  17161. + str = &tpos->wh_str;
  17162. + LKTRTrace("%.*s\n", str->len, str->name);
  17163. + if (str->len == namelen && !memcmp(str->name, name, namelen))
  17164. + return 1;
  17165. + }
  17166. + return 0;
  17167. +}
  17168. +
  17169. +int append_wh(struct aufs_nhash *whlist, char *name, int namelen,
  17170. + aufs_bindex_t bindex)
  17171. +{
  17172. + int err;
  17173. + struct aufs_destr *str;
  17174. + struct aufs_wh *wh;
  17175. +
  17176. + LKTRTrace("%.*s\n", namelen, name);
  17177. +
  17178. + err = -ENOMEM;
  17179. + wh = kmalloc(sizeof(*wh) + namelen, GFP_KERNEL);
  17180. + if (unlikely(!wh))
  17181. + goto out;
  17182. + err = 0;
  17183. + wh->wh_bindex = bindex;
  17184. + str = &wh->wh_str;
  17185. + str->len = namelen;
  17186. + memcpy(str->name, name, namelen);
  17187. + hlist_add_head(&wh->wh_hash,
  17188. + whlist->heads + au_name_hash(name, namelen));
  17189. + //smp_mb();
  17190. +
  17191. + out:
  17192. + TraceErr(err);
  17193. + return err;
  17194. +}
  17195. +
  17196. +/* ---------------------------------------------------------------------- */
  17197. +
  17198. +void free_vdir(struct aufs_vdir *vdir)
  17199. +{
  17200. + aufs_deblk_t **deblk;
  17201. +
  17202. + TraceEnter();
  17203. +
  17204. + deblk = vdir->vd_deblk;
  17205. + while (vdir->vd_nblk--) {
  17206. + kfree(*deblk);
  17207. + deblk++;
  17208. + }
  17209. + kfree(vdir->vd_deblk);
  17210. + cache_free_vdir(vdir);
  17211. +}
  17212. +
  17213. +static int append_deblk(struct aufs_vdir *vdir)
  17214. +{
  17215. + int err, sz, i;
  17216. + aufs_deblk_t **o;
  17217. + union aufs_deblk_p p, deblk_end;
  17218. +
  17219. + TraceEnter();
  17220. +
  17221. + err = -ENOMEM;
  17222. + sz = sizeof(*o) * vdir->vd_nblk;
  17223. + o = au_kzrealloc(vdir->vd_deblk, sz, sz + sizeof(*o), GFP_KERNEL);
  17224. + if (unlikely(!o))
  17225. + goto out;
  17226. + vdir->vd_deblk = o;
  17227. + p.deblk = kmalloc(sizeof(*p.deblk), GFP_KERNEL);
  17228. + if (p.deblk) {
  17229. + i = vdir->vd_nblk++;
  17230. + vdir->vd_deblk[i] = p.deblk;
  17231. + vdir->vd_last.i = i;
  17232. + vdir->vd_last.p.p = p.p;
  17233. + deblk_end.deblk = p.deblk + 1;
  17234. + err = set_deblk_end(&p, &deblk_end);
  17235. + DEBUG_ON(err);
  17236. + }
  17237. +
  17238. + out:
  17239. + TraceErr(err);
  17240. + return err;
  17241. +}
  17242. +
  17243. +static struct aufs_vdir *alloc_vdir(void)
  17244. +{
  17245. + struct aufs_vdir *vdir;
  17246. + int err;
  17247. +
  17248. + TraceEnter();
  17249. +
  17250. + err = -ENOMEM;
  17251. + vdir = cache_alloc_vdir();
  17252. + if (unlikely(!vdir))
  17253. + goto out;
  17254. + vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_KERNEL);
  17255. + if (unlikely(!vdir->vd_deblk))
  17256. + goto out_free;
  17257. +
  17258. + vdir->vd_nblk = 0;
  17259. + vdir->vd_version = 0;
  17260. + vdir->vd_jiffy = 0;
  17261. + err = append_deblk(vdir);
  17262. + if (!err)
  17263. + return vdir; /* success */
  17264. +
  17265. + kfree(vdir->vd_deblk);
  17266. +
  17267. + out_free:
  17268. + cache_free_vdir(vdir);
  17269. + out:
  17270. + vdir = ERR_PTR(err);
  17271. + TraceErrPtr(vdir);
  17272. + return vdir;
  17273. +}
  17274. +
  17275. +static int reinit_vdir(struct aufs_vdir *vdir)
  17276. +{
  17277. + int err;
  17278. + union aufs_deblk_p p, deblk_end;
  17279. +
  17280. + TraceEnter();
  17281. +
  17282. + while (vdir->vd_nblk > 1) {
  17283. + kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
  17284. + vdir->vd_deblk[vdir->vd_nblk - 1] = NULL;
  17285. + vdir->vd_nblk--;
  17286. + }
  17287. + p.deblk = vdir->vd_deblk[0];
  17288. + deblk_end.deblk = p.deblk + 1;
  17289. + err = set_deblk_end(&p, &deblk_end);
  17290. + DEBUG_ON(err);
  17291. + vdir->vd_version = 0;
  17292. + vdir->vd_jiffy = 0;
  17293. + vdir->vd_last.i = 0;
  17294. + vdir->vd_last.p.deblk = vdir->vd_deblk[0];
  17295. + //smp_mb();
  17296. + //DbgVdir(vdir);
  17297. + return err;
  17298. +}
  17299. +
  17300. +/* ---------------------------------------------------------------------- */
  17301. +
  17302. +static void free_dehlist(struct aufs_nhash *dehlist)
  17303. +{
  17304. + int i;
  17305. + struct hlist_head *head;
  17306. + struct aufs_dehstr *tpos;
  17307. + struct hlist_node *pos, *n;
  17308. +
  17309. + TraceEnter();
  17310. +
  17311. + for (i = 0; i < AUFS_NHASH_SIZE; i++) {
  17312. + head = dehlist->heads + i;
  17313. + hlist_for_each_entry_safe(tpos, pos, n, head, hash) {
  17314. + //hlist_del(pos);
  17315. + cache_free_dehstr(tpos);
  17316. + }
  17317. + }
  17318. +}
  17319. +
  17320. +/* returns found(true) or not */
  17321. +static int test_known(struct aufs_nhash *delist, char *name, int namelen)
  17322. +{
  17323. + struct hlist_head *head;
  17324. + struct aufs_dehstr *tpos;
  17325. + struct hlist_node *pos;
  17326. + struct aufs_destr *str;
  17327. +
  17328. + LKTRTrace("%.*s\n", namelen, name);
  17329. +
  17330. + head = delist->heads + au_name_hash(name, namelen);
  17331. + hlist_for_each_entry(tpos, pos, head, hash) {
  17332. + str = tpos->str;
  17333. + LKTRTrace("%.*s\n", str->len, str->name);
  17334. + if (str->len == namelen && !memcmp(str->name, name, namelen))
  17335. + return 1;
  17336. + }
  17337. + return 0;
  17338. +
  17339. +}
  17340. +
  17341. +static int append_de(struct aufs_vdir *vdir, char *name, int namelen, ino_t ino,
  17342. + unsigned int d_type, struct aufs_nhash *delist)
  17343. +{
  17344. + int err, sz;
  17345. + union aufs_deblk_p p, *room, deblk_end;
  17346. + struct aufs_dehstr *dehstr;
  17347. +
  17348. + LKTRTrace("%.*s %d, i%lu, dt%u\n", namelen, name, namelen, ino, d_type);
  17349. +
  17350. + p.deblk = last_deblk(vdir);
  17351. + deblk_end.deblk = p.deblk + 1;
  17352. + room = &vdir->vd_last.p;
  17353. + DEBUG_ON(room->p < p.p || deblk_end.p <= room->p
  17354. + || !is_deblk_end(room, &deblk_end));
  17355. +
  17356. + sz = calc_size(namelen);
  17357. + if (unlikely(sz > deblk_end.p - room->p)) {
  17358. + err = append_deblk(vdir);
  17359. + if (unlikely(err))
  17360. + goto out;
  17361. + p.deblk = last_deblk(vdir);
  17362. + deblk_end.deblk = p.deblk + 1;
  17363. + //smp_mb();
  17364. + DEBUG_ON(room->p != p.p);
  17365. + }
  17366. +
  17367. + err = -ENOMEM;
  17368. + dehstr = cache_alloc_dehstr();
  17369. + if (unlikely(!dehstr))
  17370. + goto out;
  17371. + dehstr->str = &room->de->de_str;
  17372. + hlist_add_head(&dehstr->hash,
  17373. + delist->heads + au_name_hash(name, namelen));
  17374. +
  17375. + room->de->de_ino = ino;
  17376. + room->de->de_type = d_type;
  17377. + room->de->de_str.len = namelen;
  17378. + memcpy(room->de->de_str.name, name, namelen);
  17379. +
  17380. + err = 0;
  17381. + room->p += sz;
  17382. + if (unlikely(set_deblk_end(room, &deblk_end)))
  17383. + err = append_deblk(vdir);
  17384. + //smp_mb();
  17385. +
  17386. + out:
  17387. + TraceErr(err);
  17388. + return err;
  17389. +}
  17390. +
  17391. +/* ---------------------------------------------------------------------- */
  17392. +
  17393. +struct fillvdir_arg {
  17394. + struct file *file;
  17395. + struct aufs_vdir *vdir;
  17396. + struct aufs_nhash *delist;
  17397. + struct aufs_nhash *whlist;
  17398. + aufs_bindex_t bindex;
  17399. + int err;
  17400. + int called;
  17401. +};
  17402. +
  17403. +static int fillvdir(void *__arg, const char *__name, int namelen, loff_t offset,
  17404. + filldir_ino_t h_ino, unsigned int d_type)
  17405. +{
  17406. + struct fillvdir_arg *arg = __arg;
  17407. + char *name = (void*)__name;
  17408. + aufs_bindex_t bindex, bend;
  17409. + struct xino xino;
  17410. + struct super_block *sb;
  17411. +
  17412. + LKTRTrace("%.*s, namelen %d, i%Lu, dt%u\n",
  17413. + namelen, name, namelen, (u64)h_ino, d_type);
  17414. +
  17415. + sb = arg->file->f_dentry->d_sb;
  17416. + bend = arg->bindex;
  17417. + arg->err = 0;
  17418. + arg->called++;
  17419. + //smp_mb();
  17420. + if (namelen <= AUFS_WH_PFX_LEN
  17421. + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
  17422. + for (bindex = 0; bindex < bend; bindex++)
  17423. + if (test_known(arg->delist + bindex, name, namelen)
  17424. + || test_known_wh(arg->whlist + bindex, name,
  17425. + namelen))
  17426. + goto out; /* already exists or whiteouted */
  17427. +
  17428. + arg->err = xino_read(sb, bend, h_ino, &xino);
  17429. + if (!arg->err && !xino.ino) {
  17430. + //struct inode *h_inode;
  17431. + xino.ino = xino_new_ino(sb);
  17432. + if (unlikely(!xino.ino))
  17433. + arg->err = -EIO;
  17434. +#if 0
  17435. + //xino.h_gen = AuXino_INVALID_HGEN;
  17436. + h_inode = ilookup(sbr_sb(sb, bend), h_ino);
  17437. + if (h_inode) {
  17438. + if (!is_bad_inode(h_inode)) {
  17439. + xino.h_gen = h_inode->i_generation;
  17440. + WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
  17441. + }
  17442. + iput(h_inode);
  17443. + }
  17444. +#endif
  17445. + arg->err = xino_write(sb, bend, h_ino, &xino);
  17446. + }
  17447. + if (!arg->err)
  17448. + arg->err = append_de(arg->vdir, name, namelen, xino.ino,
  17449. + d_type, arg->delist + bend);
  17450. + } else {
  17451. + name += AUFS_WH_PFX_LEN;
  17452. + namelen -= AUFS_WH_PFX_LEN;
  17453. + for (bindex = 0; bindex < bend; bindex++)
  17454. + if (test_known_wh(arg->whlist + bend, name, namelen))
  17455. + goto out; /* already whiteouted */
  17456. + arg->err = append_wh(arg->whlist + bend, name, namelen, bend);
  17457. + }
  17458. +
  17459. + out:
  17460. + if (!arg->err)
  17461. + arg->vdir->vd_jiffy = jiffies;
  17462. + //smp_mb();
  17463. + TraceErr(arg->err);
  17464. + return arg->err;
  17465. +}
  17466. +
  17467. +static int read_vdir(struct file *file, int may_read)
  17468. +{
  17469. + int err, do_read, dlgt;
  17470. + struct dentry *dentry;
  17471. + struct inode *inode;
  17472. + struct aufs_vdir *vdir, *allocated;
  17473. + unsigned long expire;
  17474. + struct fillvdir_arg arg;
  17475. + aufs_bindex_t bindex, bend, bstart;
  17476. + struct super_block *sb;
  17477. +
  17478. + dentry = file->f_dentry;
  17479. + LKTRTrace("%.*s, may %d\n", DLNPair(dentry), may_read);
  17480. + FiMustWriteLock(file);
  17481. + inode = dentry->d_inode;
  17482. + IMustLock(inode);
  17483. + IiMustWriteLock(inode);
  17484. + DEBUG_ON(!S_ISDIR(inode->i_mode));
  17485. +
  17486. + err = 0;
  17487. + allocated = NULL;
  17488. + do_read = 0;
  17489. + sb = inode->i_sb;
  17490. + expire = stosi(sb)->si_rdcache;
  17491. + vdir = ivdir(inode);
  17492. + if (!vdir) {
  17493. + DEBUG_ON(fvdir_cache(file));
  17494. + do_read = 1;
  17495. + vdir = alloc_vdir();
  17496. + err = PTR_ERR(vdir);
  17497. + if (IS_ERR(vdir))
  17498. + goto out;
  17499. + err = 0;
  17500. + allocated = vdir;
  17501. + } else if (may_read
  17502. + && (inode->i_version != vdir->vd_version
  17503. + || time_after(jiffies, vdir->vd_jiffy + expire))) {
  17504. + LKTRTrace("iver %lu, vdver %lu, exp %lu\n",
  17505. + inode->i_version, vdir->vd_version,
  17506. + vdir->vd_jiffy + expire);
  17507. + do_read = 1;
  17508. + err = reinit_vdir(vdir);
  17509. + if (unlikely(err))
  17510. + goto out;
  17511. + }
  17512. + //DbgVdir(vdir); goto out;
  17513. +
  17514. + if (!do_read)
  17515. + return 0; /* success */
  17516. +
  17517. + err = -ENOMEM;
  17518. + bend = fbend(file);
  17519. + arg.delist = kmalloc(sizeof(*arg.delist) * (bend + 1), GFP_KERNEL);
  17520. + if (unlikely(!arg.delist))
  17521. + goto out_vdir;
  17522. + arg.whlist = kmalloc(sizeof(*arg.whlist) * (bend + 1), GFP_KERNEL);
  17523. + if (unlikely(!arg.whlist))
  17524. + goto out_delist;
  17525. + err = 0;
  17526. + for (bindex = 0; bindex <= bend; bindex++) {
  17527. + nhash_init(arg.delist + bindex);
  17528. + nhash_init(arg.whlist + bindex);
  17529. + }
  17530. +
  17531. + dlgt = need_dlgt(sb);
  17532. + arg.file = file;
  17533. + arg.vdir = vdir;
  17534. + bstart = fbstart(file);
  17535. + for (bindex = bstart; !err && bindex <= bend; bindex++) {
  17536. + struct file *hf;
  17537. + struct inode *h_inode;
  17538. +
  17539. + hf = au_h_fptr_i(file, bindex);
  17540. + if (!hf)
  17541. + continue;
  17542. +
  17543. + h_inode = hf->f_dentry->d_inode;
  17544. + //hf->f_pos = 0;
  17545. + arg.bindex = bindex;
  17546. + do {
  17547. + arg.err = 0;
  17548. + arg.called = 0;
  17549. + //smp_mb();
  17550. + err = vfsub_readdir(hf, fillvdir, &arg, dlgt);
  17551. + if (err >= 0)
  17552. + err = arg.err;
  17553. + } while (!err && arg.called);
  17554. + }
  17555. +
  17556. + for (bindex = bstart; bindex <= bend; bindex++) {
  17557. + free_dehlist(arg.delist + bindex);
  17558. + nhash_fin(arg.whlist + bindex);
  17559. + }
  17560. + kfree(arg.whlist);
  17561. +
  17562. + out_delist:
  17563. + kfree(arg.delist);
  17564. + out_vdir:
  17565. + if (!err) {
  17566. + //file->f_pos = 0;
  17567. + vdir->vd_version = inode->i_version;
  17568. + vdir->vd_last.i = 0;
  17569. + vdir->vd_last.p.deblk = vdir->vd_deblk[0];
  17570. + if (allocated)
  17571. + set_ivdir(inode, allocated);
  17572. + } else if (allocated)
  17573. + free_vdir(allocated);
  17574. + //DbgVdir(vdir); goto out;
  17575. +
  17576. + out:
  17577. + TraceErr(err);
  17578. + return err;
  17579. +}
  17580. +
  17581. +static int copy_vdir(struct aufs_vdir *tgt, struct aufs_vdir *src)
  17582. +{
  17583. + int err, i, rerr, n;
  17584. +
  17585. + TraceEnter();
  17586. + DEBUG_ON(tgt->vd_nblk != 1);
  17587. + //DbgVdir(tgt);
  17588. +
  17589. + err = -ENOMEM;
  17590. + if (tgt->vd_nblk < src->vd_nblk) {
  17591. + aufs_deblk_t **p;
  17592. + p = au_kzrealloc(tgt->vd_deblk, sizeof(*p) * tgt->vd_nblk,
  17593. + sizeof(*p) * src->vd_nblk, GFP_KERNEL);
  17594. + if (unlikely(!p))
  17595. + goto out;
  17596. + tgt->vd_deblk = p;
  17597. + }
  17598. +
  17599. + n = tgt->vd_nblk = src->vd_nblk;
  17600. + memcpy(tgt->vd_deblk[0], src->vd_deblk[0], AUFS_DEBLK_SIZE);
  17601. + //tgt->vd_last.i = 0;
  17602. + //tgt->vd_last.p.deblk = tgt->vd_deblk[0];
  17603. + tgt->vd_version = src->vd_version;
  17604. + tgt->vd_jiffy = src->vd_jiffy;
  17605. +
  17606. + for (i = 1; i < n; i++) {
  17607. + tgt->vd_deblk[i] = kmalloc(AUFS_DEBLK_SIZE, GFP_KERNEL);
  17608. + if (tgt->vd_deblk[i])
  17609. + memcpy(tgt->vd_deblk[i], src->vd_deblk[i],
  17610. + AUFS_DEBLK_SIZE);
  17611. + else
  17612. + goto out;
  17613. + }
  17614. + //smp_mb();
  17615. + //DbgVdir(tgt);
  17616. + return 0; /* success */
  17617. +
  17618. + out:
  17619. + rerr = reinit_vdir(tgt);
  17620. + BUG_ON(rerr);
  17621. + TraceErr(err);
  17622. + return err;
  17623. +}
  17624. +
  17625. +int au_init_vdir(struct file *file)
  17626. +{
  17627. + int err;
  17628. + struct dentry *dentry;
  17629. + struct inode *inode;
  17630. + struct aufs_vdir *vdir_cache, *allocated;
  17631. +
  17632. + dentry = file->f_dentry;
  17633. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  17634. + FiMustWriteLock(file);
  17635. + inode = dentry->d_inode;
  17636. + IiMustWriteLock(inode);
  17637. + DEBUG_ON(!S_ISDIR(inode->i_mode));
  17638. +
  17639. + err = read_vdir(file, !file->f_pos);
  17640. + if (unlikely(err))
  17641. + goto out;
  17642. + //DbgVdir(ivdir(inode)); goto out;
  17643. +
  17644. + allocated = NULL;
  17645. + vdir_cache = fvdir_cache(file);
  17646. + if (!vdir_cache) {
  17647. + vdir_cache = alloc_vdir();
  17648. + err = PTR_ERR(vdir_cache);
  17649. + if (IS_ERR(vdir_cache))
  17650. + goto out;
  17651. + allocated = vdir_cache;
  17652. + } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
  17653. + err = reinit_vdir(vdir_cache);
  17654. + if (unlikely(err))
  17655. + goto out;
  17656. + } else
  17657. + return 0; /* success */
  17658. + //err = 0; DbgVdir(vdir_cache); goto out;
  17659. +
  17660. + err = copy_vdir(vdir_cache, ivdir(inode));
  17661. + if (!err) {
  17662. + file->f_version = inode->i_version;
  17663. + if (allocated)
  17664. + set_fvdir_cache(file, allocated);
  17665. + } else if (allocated)
  17666. + free_vdir(allocated);
  17667. +
  17668. + out:
  17669. + TraceErr(err);
  17670. + return err;
  17671. +}
  17672. +
  17673. +static loff_t calc_offset(struct aufs_vdir *vdir)
  17674. +{
  17675. + loff_t offset;
  17676. + union aufs_deblk_p p;
  17677. +
  17678. + p.deblk = vdir->vd_deblk[vdir->vd_last.i];
  17679. + offset = vdir->vd_last.p.p - p.p;
  17680. + offset += sizeof(*p.deblk) * vdir->vd_last.i;
  17681. + return offset;
  17682. +}
  17683. +
  17684. +/* returns true or false */
  17685. +static int seek_vdir(struct file *file)
  17686. +{
  17687. + int valid, i, n;
  17688. + struct dentry *dentry;
  17689. + struct aufs_vdir *vdir_cache;
  17690. + loff_t offset;
  17691. + union aufs_deblk_p p, deblk_end;
  17692. +
  17693. + dentry = file->f_dentry;
  17694. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  17695. + vdir_cache = fvdir_cache(file);
  17696. + DEBUG_ON(!vdir_cache);
  17697. + //DbgVdir(vdir_cache);
  17698. +
  17699. + valid = 1;
  17700. + offset = calc_offset(vdir_cache);
  17701. + LKTRTrace("offset %Ld\n", offset);
  17702. + if (file->f_pos == offset)
  17703. + goto out;
  17704. +
  17705. + vdir_cache->vd_last.i = 0;
  17706. + vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
  17707. + if (!file->f_pos)
  17708. + goto out;
  17709. +
  17710. + valid = 0;
  17711. + i = file->f_pos / AUFS_DEBLK_SIZE;
  17712. + LKTRTrace("i %d\n", i);
  17713. + if (i >= vdir_cache->vd_nblk)
  17714. + goto out;
  17715. +
  17716. + n = vdir_cache->vd_nblk;
  17717. + //DbgVdir(vdir_cache);
  17718. + for (; i < n; i++) {
  17719. + p.deblk = vdir_cache->vd_deblk[i];
  17720. + deblk_end.deblk = p.deblk + 1;
  17721. + offset = i * AUFS_DEBLK_SIZE;
  17722. + while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
  17723. + int l;
  17724. + l = calc_size(p.de->de_str.len);
  17725. + offset += l;
  17726. + p.p += l;
  17727. + }
  17728. + if (!is_deblk_end(&p, &deblk_end)) {
  17729. + valid = 1;
  17730. + vdir_cache->vd_last.i = i;
  17731. + vdir_cache->vd_last.p = p;
  17732. + break;
  17733. + }
  17734. + }
  17735. +
  17736. + out:
  17737. + //smp_mb();
  17738. + //DbgVdir(vdir_cache);
  17739. + TraceErr(!valid);
  17740. + return valid;
  17741. +}
  17742. +
  17743. +int au_fill_de(struct file *file, void *dirent, filldir_t filldir)
  17744. +{
  17745. + int err, l;
  17746. + struct dentry *dentry;
  17747. + struct aufs_vdir *vdir_cache;
  17748. + struct aufs_de *de;
  17749. + union aufs_deblk_p deblk_end;
  17750. +
  17751. + dentry = file->f_dentry;
  17752. + LKTRTrace("%.*s, pos %Ld\n", DLNPair(dentry), file->f_pos);
  17753. + vdir_cache = fvdir_cache(file);
  17754. + DEBUG_ON(!vdir_cache);
  17755. + //DbgVdir(vdir_cache);
  17756. +
  17757. + if (!seek_vdir(file))
  17758. + return 0;
  17759. +
  17760. + while (1) {
  17761. + deblk_end.deblk
  17762. + = vdir_cache->vd_deblk[vdir_cache->vd_last.i] + 1;
  17763. + while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
  17764. + de = vdir_cache->vd_last.p.de;
  17765. + LKTRTrace("%.*s, off%Ld, i%lu, dt%d\n",
  17766. + de->de_str.len, de->de_str.name,
  17767. + file->f_pos, de->de_ino, de->de_type);
  17768. + err = filldir(dirent, de->de_str.name, de->de_str.len,
  17769. + file->f_pos, de->de_ino, de->de_type);
  17770. + if (unlikely(err)) {
  17771. + TraceErr(err);
  17772. + //return err;
  17773. + //todo: ignore the error caused by udba.
  17774. + return 0;
  17775. + }
  17776. +
  17777. + l = calc_size(de->de_str.len);
  17778. + vdir_cache->vd_last.p.p += l;
  17779. + file->f_pos += l;
  17780. + }
  17781. + if (vdir_cache->vd_last.i < vdir_cache->vd_nblk - 1) {
  17782. + vdir_cache->vd_last.i++;
  17783. + vdir_cache->vd_last.p.deblk
  17784. + = vdir_cache->vd_deblk[vdir_cache->vd_last.i];
  17785. + file->f_pos = sizeof(*vdir_cache->vd_last.p.deblk)
  17786. + * vdir_cache->vd_last.i;
  17787. + continue;
  17788. + }
  17789. + break;
  17790. + }
  17791. +
  17792. + //smp_mb();
  17793. + return 0;
  17794. +}
  17795. diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
  17796. new file mode 100755
  17797. index 0000000..8571d21
  17798. --- /dev/null
  17799. +++ b/fs/aufs/vfsub.c
  17800. @@ -0,0 +1,665 @@
  17801. +/*
  17802. + * Copyright (C) 2007 Junjiro Okajima
  17803. + *
  17804. + * This program, aufs is free software; you can redistribute it and/or modify
  17805. + * it under the terms of the GNU General Public License as published by
  17806. + * the Free Software Foundation; either version 2 of the License, or
  17807. + * (at your option) any later version.
  17808. + *
  17809. + * This program is distributed in the hope that it will be useful,
  17810. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17811. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17812. + * GNU General Public License for more details.
  17813. + *
  17814. + * You should have received a copy of the GNU General Public License
  17815. + * along with this program; if not, write to the Free Software
  17816. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17817. + */
  17818. +
  17819. +/* $Id: vfsub.c,v 1.5 2007/04/23 00:55:06 sfjro Exp $ */
  17820. +// I'm going to slightly mad
  17821. +
  17822. +#include "aufs.h"
  17823. +
  17824. +/* ---------------------------------------------------------------------- */
  17825. +
  17826. +#ifdef CONFIG_AUFS_DLGT
  17827. +struct permission_args {
  17828. + int *errp;
  17829. + struct inode *inode;
  17830. + int mask;
  17831. + struct nameidata *nd;
  17832. +};
  17833. +
  17834. +static void call_permission(void *args)
  17835. +{
  17836. + struct permission_args *a = args;
  17837. + *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
  17838. +}
  17839. +
  17840. +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
  17841. + int dlgt)
  17842. +{
  17843. + if (!dlgt)
  17844. + return do_vfsub_permission(inode, mask, nd);
  17845. + else {
  17846. + int err;
  17847. + struct permission_args args = {
  17848. + .errp = &err,
  17849. + .inode = inode,
  17850. + .mask = mask,
  17851. + .nd = nd
  17852. + };
  17853. + au_wkq_wait(call_permission, &args, /*dlgt*/1);
  17854. + return err;
  17855. + }
  17856. +}
  17857. +
  17858. +/* ---------------------------------------------------------------------- */
  17859. +
  17860. +struct create_args {
  17861. + int *errp;
  17862. + struct inode *dir;
  17863. + struct dentry *dentry;
  17864. + int mode;
  17865. + struct nameidata *nd;
  17866. +};
  17867. +
  17868. +static void call_create(void *args)
  17869. +{
  17870. + struct create_args *a = args;
  17871. + *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
  17872. +}
  17873. +
  17874. +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  17875. + struct nameidata *nd, int dlgt)
  17876. +{
  17877. + if (!dlgt)
  17878. + return do_vfsub_create(dir, dentry, mode, nd);
  17879. + else {
  17880. + int err;
  17881. + struct create_args args = {
  17882. + .errp = &err,
  17883. + .dir = dir,
  17884. + .dentry = dentry,
  17885. + .mode = mode,
  17886. + .nd = nd
  17887. + };
  17888. + au_wkq_wait(call_create, &args, /*dlgt*/1);
  17889. + return err;
  17890. + }
  17891. +}
  17892. +
  17893. +struct symlink_args {
  17894. + int *errp;
  17895. + struct inode *dir;
  17896. + struct dentry *dentry;
  17897. + const char *symname;
  17898. + int mode;
  17899. +};
  17900. +
  17901. +static void call_symlink(void *args)
  17902. +{
  17903. + struct symlink_args *a = args;
  17904. + *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
  17905. +}
  17906. +
  17907. +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
  17908. + int mode, int dlgt)
  17909. +{
  17910. + if (!dlgt)
  17911. + return do_vfsub_symlink(dir, dentry, symname, mode);
  17912. + else {
  17913. + int err;
  17914. + struct symlink_args args = {
  17915. + .errp = &err,
  17916. + .dir = dir,
  17917. + .dentry = dentry,
  17918. + .symname = symname,
  17919. + .mode = mode
  17920. + };
  17921. + au_wkq_wait(call_symlink, &args, /*dlgt*/1);
  17922. + return err;
  17923. + }
  17924. +}
  17925. +
  17926. +struct mknod_args {
  17927. + int *errp;
  17928. + struct inode *dir;
  17929. + struct dentry *dentry;
  17930. + int mode;
  17931. + dev_t dev;
  17932. +};
  17933. +
  17934. +static void call_mknod(void *args)
  17935. +{
  17936. + struct mknod_args *a = args;
  17937. + *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
  17938. +}
  17939. +
  17940. +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
  17941. + int dlgt)
  17942. +{
  17943. + if (!dlgt)
  17944. + return do_vfsub_mknod(dir, dentry, mode, dev);
  17945. + else {
  17946. + int err;
  17947. + struct mknod_args args = {
  17948. + .errp = &err,
  17949. + .dir = dir,
  17950. + .dentry = dentry,
  17951. + .mode = mode,
  17952. + .dev = dev
  17953. + };
  17954. + au_wkq_wait(call_mknod, &args, /*dlgt*/1);
  17955. + return err;
  17956. + }
  17957. +}
  17958. +
  17959. +struct mkdir_args {
  17960. + int *errp;
  17961. + struct inode *dir;
  17962. + struct dentry *dentry;
  17963. + int mode;
  17964. +};
  17965. +
  17966. +static void call_mkdir(void *args)
  17967. +{
  17968. + struct mkdir_args *a = args;
  17969. + *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
  17970. +}
  17971. +
  17972. +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt)
  17973. +{
  17974. + if (!dlgt)
  17975. + return do_vfsub_mkdir(dir, dentry, mode);
  17976. + else {
  17977. + int err;
  17978. + struct mkdir_args args = {
  17979. + .errp = &err,
  17980. + .dir = dir,
  17981. + .dentry = dentry,
  17982. + .mode = mode
  17983. + };
  17984. + au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
  17985. + return err;
  17986. + }
  17987. +}
  17988. +
  17989. +/* ---------------------------------------------------------------------- */
  17990. +
  17991. +struct link_args {
  17992. + int *errp;
  17993. + struct inode *dir;
  17994. + struct dentry *src_dentry, *dentry;
  17995. +};
  17996. +
  17997. +static void call_link(void *args)
  17998. +{
  17999. + struct link_args *a = args;
  18000. + *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
  18001. +}
  18002. +
  18003. +int vfsub_link(struct dentry *src_dentry, struct inode *dir,
  18004. + struct dentry *dentry, int dlgt)
  18005. +{
  18006. + if (!dlgt)
  18007. + return do_vfsub_link(src_dentry, dir, dentry);
  18008. + else {
  18009. + int err;
  18010. + struct link_args args = {
  18011. + .errp = &err,
  18012. + .src_dentry = src_dentry,
  18013. + .dir = dir,
  18014. + .dentry = dentry
  18015. + };
  18016. + au_wkq_wait(call_link, &args, /*dlgt*/1);
  18017. + return err;
  18018. + }
  18019. +}
  18020. +
  18021. +struct rename_args {
  18022. + int *errp;
  18023. + struct inode *src_dir, *dir;
  18024. + struct dentry *src_dentry, *dentry;
  18025. +};
  18026. +
  18027. +static void call_rename(void *args)
  18028. +{
  18029. + struct rename_args *a = args;
  18030. + *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
  18031. + a->dentry);
  18032. +}
  18033. +
  18034. +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  18035. + struct inode *dir, struct dentry *dentry, int dlgt)
  18036. +{
  18037. + if (!dlgt)
  18038. + return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
  18039. + else {
  18040. + int err;
  18041. + struct rename_args args = {
  18042. + .errp = &err,
  18043. + .src_dir = src_dir,
  18044. + .src_dentry = src_dentry,
  18045. + .dir = dir,
  18046. + .dentry = dentry
  18047. + };
  18048. + au_wkq_wait(call_rename, &args, /*dlgt*/1);
  18049. + return err;
  18050. + }
  18051. +}
  18052. +
  18053. +struct rmdir_args {
  18054. + int *errp;
  18055. + struct inode *dir;
  18056. + struct dentry *dentry;
  18057. +};
  18058. +
  18059. +static void call_rmdir(void *args)
  18060. +{
  18061. + struct rmdir_args *a = args;
  18062. + *a->errp = do_vfsub_rmdir(a->dir, a->dentry);
  18063. +}
  18064. +
  18065. +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
  18066. +{
  18067. + if (!dlgt)
  18068. + return do_vfsub_rmdir(dir, dentry);
  18069. + else {
  18070. + int err;
  18071. + struct rmdir_args args = {
  18072. + .errp = &err,
  18073. + .dir = dir,
  18074. + .dentry = dentry
  18075. + };
  18076. + au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
  18077. + return err;
  18078. + }
  18079. +}
  18080. +
  18081. +/* ---------------------------------------------------------------------- */
  18082. +
  18083. +struct read_args {
  18084. + ssize_t *errp;
  18085. + struct file *file;
  18086. + union {
  18087. + void *kbuf;
  18088. + char __user *ubuf;
  18089. + };
  18090. + size_t count;
  18091. + loff_t *ppos;
  18092. +};
  18093. +
  18094. +static void call_read_k(void *args)
  18095. +{
  18096. + struct read_args *a = args;
  18097. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  18098. + DLNPair(a->file->f_dentry), (unsigned long)a->count,
  18099. + *a->ppos);
  18100. + *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
  18101. +}
  18102. +
  18103. +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18104. + loff_t *ppos, int dlgt)
  18105. +{
  18106. + if (!dlgt)
  18107. + return do_vfsub_read_u(file, ubuf, count, ppos);
  18108. + else {
  18109. + ssize_t err, read;
  18110. + struct read_args args = {
  18111. + .errp = &err,
  18112. + .file = file,
  18113. + .count = count,
  18114. + .ppos = ppos
  18115. + };
  18116. +
  18117. + if (unlikely(!count))
  18118. + return 0;
  18119. +
  18120. + /*
  18121. + * workaround an application bug.
  18122. + * generally, read(2) or write(2) may return the value shorter
  18123. + * than requested. But many applications don't support it,
  18124. + * for example bash.
  18125. + */
  18126. + err = -ENOMEM;
  18127. + if (args.count > PAGE_SIZE)
  18128. + args.count = PAGE_SIZE;
  18129. + args.kbuf = kmalloc(args.count, GFP_KERNEL);
  18130. + if (unlikely(!args.kbuf))
  18131. + goto out;
  18132. +
  18133. + read = 0;
  18134. + do {
  18135. + au_wkq_wait(call_read_k, &args, /*dlgt*/1);
  18136. + if (unlikely(err > 0
  18137. + && copy_to_user(ubuf, args.kbuf, err))) {
  18138. + err = -EFAULT;
  18139. + goto out_free;
  18140. + } else if (!err)
  18141. + break;
  18142. + else if (unlikely(err < 0))
  18143. + goto out_free;
  18144. + count -= err;
  18145. + /* do not read too much because of file i/o pointer */
  18146. + if (unlikely(count < args.count))
  18147. + args.count = count;
  18148. + ubuf += err;
  18149. + read += err;
  18150. + } while (count);
  18151. + smp_mb();
  18152. + err = read;
  18153. +
  18154. + out_free:
  18155. + kfree(args.kbuf);
  18156. + out:
  18157. + return err;
  18158. + }
  18159. +}
  18160. +
  18161. +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18162. + int dlgt)
  18163. +{
  18164. + if (!dlgt)
  18165. + return do_vfsub_read_k(file, kbuf, count, ppos);
  18166. + else {
  18167. + ssize_t err;
  18168. + struct read_args args = {
  18169. + .errp = &err,
  18170. + .file = file,
  18171. + .count = count,
  18172. + .ppos = ppos
  18173. + };
  18174. + args.kbuf = kbuf;
  18175. + au_wkq_wait(call_read_k, &args, /*dlgt*/1);
  18176. + return err;
  18177. + }
  18178. +}
  18179. +
  18180. +struct write_args {
  18181. + ssize_t *errp;
  18182. + struct file *file;
  18183. + union {
  18184. + void *kbuf;
  18185. + const char __user *ubuf;
  18186. + };
  18187. + void *buf;
  18188. + size_t count;
  18189. + loff_t *ppos;
  18190. +};
  18191. +
  18192. +static void call_write_k(void *args)
  18193. +{
  18194. + struct write_args *a = args;
  18195. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  18196. + DLNPair(a->file->f_dentry), (unsigned long)a->count,
  18197. + *a->ppos);
  18198. + *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
  18199. +}
  18200. +
  18201. +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
  18202. + loff_t *ppos, int dlgt)
  18203. +{
  18204. + if (!dlgt)
  18205. + return do_vfsub_write_u(file, ubuf, count, ppos);
  18206. + else {
  18207. + ssize_t err, written;
  18208. + struct write_args args = {
  18209. + .errp = &err,
  18210. + .file = file,
  18211. + .count = count,
  18212. + .ppos = ppos
  18213. + };
  18214. +
  18215. + if (unlikely(!count))
  18216. + return 0;
  18217. +
  18218. + /*
  18219. + * workaround an application bug.
  18220. + * generally, read(2) or write(2) may return the value shorter
  18221. + * than requested. But many applications don't support it,
  18222. + * for example bash.
  18223. + */
  18224. + err = -ENOMEM;
  18225. + if (args.count > PAGE_SIZE)
  18226. + args.count = PAGE_SIZE;
  18227. + args.kbuf = kmalloc(args.count, GFP_KERNEL);
  18228. + if (unlikely(!args.kbuf))
  18229. + goto out;
  18230. +
  18231. + written = 0;
  18232. + do {
  18233. + if (unlikely(copy_from_user(args.kbuf, ubuf, args.count))) {
  18234. + err = -EFAULT;
  18235. + goto out_free;
  18236. + }
  18237. +
  18238. + au_wkq_wait(call_write_k, &args, /*dlgt*/1);
  18239. + if (err > 0) {
  18240. + count -= err;
  18241. + if (count < args.count)
  18242. + args.count = count;
  18243. + ubuf += err;
  18244. + written += err;
  18245. + } else if (!err)
  18246. + break;
  18247. + else if (unlikely(err < 0))
  18248. + goto out_free;
  18249. + } while (count);
  18250. + err = written;
  18251. +
  18252. + out_free:
  18253. + kfree(args.kbuf);
  18254. + out:
  18255. + return err;
  18256. + }
  18257. +}
  18258. +
  18259. +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18260. + int dlgt)
  18261. +{
  18262. + if (!dlgt)
  18263. + return do_vfsub_write_k(file, kbuf, count, ppos);
  18264. + else {
  18265. + ssize_t err;
  18266. + struct write_args args = {
  18267. + .errp = &err,
  18268. + .file = file,
  18269. + .count = count,
  18270. + .ppos = ppos
  18271. + };
  18272. + args.kbuf = kbuf;
  18273. + au_wkq_wait(call_write_k, &args, /*dlgt*/1);
  18274. + return err;
  18275. + }
  18276. +}
  18277. +
  18278. +struct readdir_args {
  18279. + int *errp;
  18280. + struct file *file;
  18281. + filldir_t filldir;
  18282. + void *arg;
  18283. +};
  18284. +
  18285. +static void call_readdir(void *args)
  18286. +{
  18287. + struct readdir_args *a = args;
  18288. + *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
  18289. +}
  18290. +
  18291. +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
  18292. +{
  18293. + if (!dlgt)
  18294. + return do_vfsub_readdir(file, filldir, arg);
  18295. + else {
  18296. + int err;
  18297. + struct readdir_args args = {
  18298. + .errp = &err,
  18299. + .file = file,
  18300. + .filldir = filldir,
  18301. + .arg = arg
  18302. + };
  18303. + au_wkq_wait(call_readdir, &args, /*dlgt*/1);
  18304. + return err;
  18305. + }
  18306. +}
  18307. +#endif /* CONFIG_AUFS_DLGT */
  18308. +
  18309. +/* ---------------------------------------------------------------------- */
  18310. +
  18311. +struct notify_change_args {
  18312. + int *errp;
  18313. + struct dentry *h_dentry;
  18314. + struct iattr *ia;
  18315. +};
  18316. +
  18317. +static void call_notify_change(void *args)
  18318. +{
  18319. + struct notify_change_args *a = args;
  18320. + struct inode *h_inode;
  18321. +
  18322. + LKTRTrace("%.*s, ia_valid 0x%x\n",
  18323. + DLNPair(a->h_dentry), a->ia->ia_valid);
  18324. + h_inode = a->h_dentry->d_inode;
  18325. + IMustLock(h_inode);
  18326. +
  18327. + *a->errp = -EPERM;
  18328. + if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
  18329. + lockdep_off();
  18330. + *a->errp = notify_change(a->h_dentry, a->ia);
  18331. + lockdep_on();
  18332. + }
  18333. + TraceErr(*a->errp);
  18334. +}
  18335. +
  18336. +int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt)
  18337. +{
  18338. + int err;
  18339. + struct notify_change_args args = {
  18340. + .errp = &err,
  18341. + .h_dentry = dentry,
  18342. + .ia = ia
  18343. + };
  18344. +
  18345. +#ifndef CONFIG_AUFS_DLGT
  18346. + call_notify_change(&args);
  18347. +#else
  18348. + if (!dlgt)
  18349. + call_notify_change(&args);
  18350. + else
  18351. + au_wkq_wait(call_notify_change, &args, /*dlgt*/1);
  18352. +#endif
  18353. +
  18354. + TraceErr(err);
  18355. + return err;
  18356. +}
  18357. +
  18358. +/* ---------------------------------------------------------------------- */
  18359. +
  18360. +struct unlink_args {
  18361. + int *errp;
  18362. + struct inode *dir;
  18363. + struct dentry *dentry;
  18364. +};
  18365. +
  18366. +static void call_unlink(void *args)
  18367. +{
  18368. + struct unlink_args *a = args;
  18369. + struct inode *h_inode;
  18370. + const int stop_sillyrename = (au_is_nfs(a->dentry->d_sb)
  18371. + && atomic_read(&a->dentry->d_count) == 1);
  18372. +
  18373. + LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
  18374. + DLNPair(a->dentry), stop_sillyrename,
  18375. + atomic_read(&a->dentry->d_count));
  18376. + IMustLock(a->dir);
  18377. +
  18378. + if (!stop_sillyrename)
  18379. + dget(a->dentry);
  18380. + h_inode = a->dentry->d_inode;
  18381. + if (h_inode)
  18382. + atomic_inc(&h_inode->i_count);
  18383. +#if 0 // partial testing
  18384. + {
  18385. + struct qstr *name = &a->dentry->d_name;
  18386. + if (name->len == sizeof(AUFS_XINO_FNAME) - 1
  18387. + && !strncmp(name->name, AUFS_XINO_FNAME, name->len)) {
  18388. + lockdep_off();
  18389. + *a->errp = vfs_unlink(a->dir, a->dentry);
  18390. + lockdep_on();
  18391. + } else
  18392. + err = -1;
  18393. + }
  18394. +#else
  18395. + // vfs_unlink() locks inode
  18396. + lockdep_off();
  18397. + *a->errp = vfs_unlink(a->dir, a->dentry);
  18398. + lockdep_on();
  18399. +#endif
  18400. +
  18401. + if (!stop_sillyrename)
  18402. + dput(a->dentry);
  18403. + if (h_inode)
  18404. + iput(h_inode);
  18405. +
  18406. + TraceErr(*a->errp);
  18407. +}
  18408. +
  18409. +/*
  18410. + * @dir: must be locked.
  18411. + * @dentry: target dentry.
  18412. + */
  18413. +int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt)
  18414. +{
  18415. + int err;
  18416. + struct unlink_args args = {
  18417. + .errp = &err,
  18418. + .dir = dir,
  18419. + .dentry = dentry
  18420. + };
  18421. +
  18422. +#ifndef CONFIG_AUFS_DLGT
  18423. + call_unlink(&args);
  18424. +#else
  18425. + if (!dlgt)
  18426. + call_unlink(&args);
  18427. + else
  18428. + au_wkq_wait(call_unlink, &args, /*dlgt*/1);
  18429. +#endif
  18430. + return err;
  18431. +}
  18432. +
  18433. +/* ---------------------------------------------------------------------- */
  18434. +
  18435. +struct statfs_args {
  18436. + int *errp;
  18437. + void *arg;
  18438. + struct kstatfs *buf;
  18439. +};
  18440. +
  18441. +static void call_statfs(void *args)
  18442. +{
  18443. + struct statfs_args *a = args;
  18444. + *a->errp = vfs_statfs(a->arg, a->buf);
  18445. +}
  18446. +
  18447. +int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
  18448. +{
  18449. + int err;
  18450. + struct statfs_args args = {
  18451. + .errp = &err,
  18452. + .arg = arg,
  18453. + .buf = buf
  18454. + };
  18455. +
  18456. +#ifndef CONFIG_AUFS_DLGT
  18457. + call_statfs(&args);
  18458. +#else
  18459. + if (!dlgt)
  18460. + call_statfs(&args);
  18461. + else
  18462. + au_wkq_wait(call_statfs, &args, /*dlgt*/1);
  18463. +#endif
  18464. + return err;
  18465. +}
  18466. diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
  18467. new file mode 100755
  18468. index 0000000..52f15cc
  18469. --- /dev/null
  18470. +++ b/fs/aufs/vfsub.h
  18471. @@ -0,0 +1,427 @@
  18472. +/*
  18473. + * Copyright (C) 2007 Junjiro Okajima
  18474. + *
  18475. + * This program, aufs is free software; you can redistribute it and/or modify
  18476. + * it under the terms of the GNU General Public License as published by
  18477. + * the Free Software Foundation; either version 2 of the License, or
  18478. + * (at your option) any later version.
  18479. + *
  18480. + * This program is distributed in the hope that it will be useful,
  18481. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18482. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18483. + * GNU General Public License for more details.
  18484. + *
  18485. + * You should have received a copy of the GNU General Public License
  18486. + * along with this program; if not, write to the Free Software
  18487. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18488. + */
  18489. +
  18490. +/* $Id: vfsub.h,v 1.8 2007/05/14 03:39:10 sfjro Exp $ */
  18491. +
  18492. +#ifndef __AUFS_VFSUB_H__
  18493. +#define __AUFS_VFSUB_H__
  18494. +
  18495. +#ifdef __KERNEL__
  18496. +
  18497. +#include <linux/fs.h>
  18498. +#include <asm/uaccess.h>
  18499. +#include "wkq.h"
  18500. +
  18501. +/* ---------------------------------------------------------------------- */
  18502. +
  18503. +/* simple abstractions, for future use */
  18504. +static inline
  18505. +int do_vfsub_permission(struct inode *inode, int mask, struct nameidata *nd)
  18506. +{
  18507. + LKTRTrace("i%lu, mask 0x%x, nd %p\n", inode->i_ino, mask, nd);
  18508. +#if 0
  18509. +#else
  18510. + return permission(inode, mask, nd);
  18511. +#endif
  18512. +}
  18513. +
  18514. +static inline
  18515. +struct file *vfsub_filp_open(const char *path, int oflags, int mode)
  18516. +{
  18517. + struct file *err;
  18518. +
  18519. + LKTRTrace("%s\n", path);
  18520. +
  18521. + lockdep_off();
  18522. + err = filp_open(path, oflags, mode);
  18523. + lockdep_on();
  18524. + return err;
  18525. +}
  18526. +
  18527. +static inline
  18528. +int vfsub_path_lookup(const char *name, unsigned int flags,
  18529. + struct nameidata *nd)
  18530. +{
  18531. + int err;
  18532. +
  18533. + LKTRTrace("%s\n", name);
  18534. +
  18535. + //lockdep_off();
  18536. + err = path_lookup(name, flags, nd);
  18537. + //lockdep_on();
  18538. + return err;
  18539. +}
  18540. +
  18541. +/* ---------------------------------------------------------------------- */
  18542. +
  18543. +static inline
  18544. +int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  18545. + struct nameidata *nd)
  18546. +{
  18547. + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
  18548. +#if 0
  18549. +#else
  18550. + return vfs_create(dir, dentry, mode, nd);
  18551. +#endif
  18552. +}
  18553. +
  18554. +static inline
  18555. +int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
  18556. + const char *symname, int mode)
  18557. +{
  18558. + LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
  18559. + dir->i_ino, DLNPair(dentry), symname, mode);
  18560. +#if 0
  18561. +#else
  18562. + return vfs_symlink(dir, dentry, symname, mode);
  18563. +#endif
  18564. +}
  18565. +
  18566. +static inline
  18567. +int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
  18568. + dev_t dev)
  18569. +{
  18570. + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
  18571. +#if 0
  18572. +#else
  18573. + return vfs_mknod(dir, dentry, mode, dev);
  18574. +#endif
  18575. +}
  18576. +
  18577. +static inline
  18578. +int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
  18579. + struct dentry *dentry)
  18580. +{
  18581. + int err;
  18582. +
  18583. + LKTRTrace("%.*s, i%lu, %.*s\n",
  18584. + DLNPair(src_dentry), dir->i_ino, DLNPair(dentry));
  18585. +
  18586. + lockdep_off();
  18587. +#if 0
  18588. +#else
  18589. + err = vfs_link(src_dentry, dir, dentry);
  18590. +#endif
  18591. + lockdep_on();
  18592. + return err;
  18593. +}
  18594. +
  18595. +static inline
  18596. +int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  18597. + struct inode *dir, struct dentry *dentry)
  18598. +{
  18599. + int err;
  18600. +
  18601. + LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
  18602. + src_dir->i_ino, DLNPair(src_dentry),
  18603. + dir->i_ino, DLNPair(dentry));
  18604. +
  18605. + lockdep_off();
  18606. +#if 0
  18607. +#else
  18608. + err = vfs_rename(src_dir, src_dentry, dir, dentry);
  18609. +#endif
  18610. + lockdep_on();
  18611. + return err;
  18612. +}
  18613. +
  18614. +static inline
  18615. +int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  18616. +{
  18617. + LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, DLNPair(dentry), mode);
  18618. +#if 0
  18619. +#else
  18620. + return vfs_mkdir(dir, dentry, mode);
  18621. +#endif
  18622. +}
  18623. +
  18624. +static inline int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
  18625. +{
  18626. + int err;
  18627. +
  18628. + LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry));
  18629. +
  18630. + lockdep_off();
  18631. +#if 0
  18632. +#else
  18633. + err = vfs_rmdir(dir, dentry);
  18634. +#endif
  18635. + lockdep_on();
  18636. + return err;
  18637. +}
  18638. +
  18639. +/* ---------------------------------------------------------------------- */
  18640. +
  18641. +static inline
  18642. +ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18643. + loff_t *ppos)
  18644. +{
  18645. + ssize_t err;
  18646. +
  18647. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  18648. + DLNPair(file->f_dentry), (unsigned long)count, *ppos);
  18649. +
  18650. + /* nfs uses some locks */
  18651. + lockdep_off();
  18652. +#if 0
  18653. +#else
  18654. + err = vfs_read(file, ubuf, count, ppos);
  18655. +#endif
  18656. + lockdep_on();
  18657. + return err;
  18658. +}
  18659. +
  18660. +// kernel_read() ??
  18661. +static inline
  18662. +ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
  18663. + loff_t *ppos)
  18664. +{
  18665. + ssize_t err;
  18666. + mm_segment_t oldfs;
  18667. +
  18668. + oldfs = get_fs();
  18669. + set_fs(KERNEL_DS);
  18670. + err = do_vfsub_read_u(file, (char __user*)kbuf, count, ppos);
  18671. + set_fs(oldfs);
  18672. + return err;
  18673. +}
  18674. +
  18675. +static inline
  18676. +ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
  18677. + size_t count, loff_t *ppos)
  18678. +{
  18679. + ssize_t err;
  18680. +
  18681. + LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
  18682. + DLNPair(file->f_dentry), (unsigned long)count, *ppos);
  18683. +
  18684. + lockdep_off();
  18685. +#if 0
  18686. +#else
  18687. + err = vfs_write(file, ubuf, count, ppos);
  18688. +#endif
  18689. + lockdep_on();
  18690. + return err;
  18691. +}
  18692. +
  18693. +static inline
  18694. +ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
  18695. + loff_t *ppos)
  18696. +{
  18697. + ssize_t err;
  18698. + mm_segment_t oldfs;
  18699. +
  18700. + oldfs = get_fs();
  18701. + set_fs(KERNEL_DS);
  18702. + err = do_vfsub_write_u(file, (const char __user*)kbuf, count, ppos);
  18703. + set_fs(oldfs);
  18704. + return err;
  18705. +}
  18706. +
  18707. +static inline
  18708. +int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
  18709. +{
  18710. + int err;
  18711. +
  18712. + LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
  18713. +
  18714. + lockdep_off();
  18715. +#if 0
  18716. +#else
  18717. + err = vfs_readdir(file, filldir, arg);
  18718. +#endif
  18719. + lockdep_on();
  18720. + return err;
  18721. +}
  18722. +
  18723. +/* ---------------------------------------------------------------------- */
  18724. +
  18725. +static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
  18726. +{
  18727. + loff_t err;
  18728. +
  18729. + LKTRTrace("%.*s\n", DLNPair(file->f_dentry));
  18730. +
  18731. + lockdep_off();
  18732. +#if 0
  18733. +#else
  18734. + err = vfs_llseek(file, offset, origin);
  18735. +#endif
  18736. + lockdep_on();
  18737. + return err;
  18738. +}
  18739. +
  18740. +/* ---------------------------------------------------------------------- */
  18741. +
  18742. +#ifdef CONFIG_AUFS_DLGT
  18743. +static inline int need_dlgt(struct super_block *sb)
  18744. +{
  18745. + return (au_flag_test(sb, AuFlag_DLGT) && !is_au_wkq(current));
  18746. +}
  18747. +
  18748. +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
  18749. + int dlgt);
  18750. +
  18751. +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  18752. + struct nameidata *nd, int dlgt);
  18753. +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
  18754. + int mode, int dlgt);
  18755. +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
  18756. + int dlgt);
  18757. +int vfsub_link(struct dentry *src_dentry, struct inode *dir,
  18758. + struct dentry *dentry, int dlgt);
  18759. +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  18760. + struct inode *dir, struct dentry *dentry, int dlgt);
  18761. +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt);
  18762. +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt);
  18763. +
  18764. +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18765. + loff_t *ppos, int dlgt);
  18766. +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18767. + int dlgt);
  18768. +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
  18769. + loff_t *ppos, int dlgt);
  18770. +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18771. + int dlgt);
  18772. +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt);
  18773. +
  18774. +#else
  18775. +
  18776. +static inline int need_dlgt(struct super_block *sb)
  18777. +{
  18778. + return 0;
  18779. +}
  18780. +
  18781. +static inline
  18782. +int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
  18783. + int dlgt)
  18784. +{
  18785. + return do_vfsub_permission(inode, mask, nd);
  18786. +}
  18787. +
  18788. +static inline
  18789. +int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
  18790. + struct nameidata *nd, int dlgt)
  18791. +{
  18792. + return do_vfsub_create(dir, dentry, mode, nd);
  18793. +}
  18794. +
  18795. +static inline
  18796. +int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
  18797. + int mode, int dlgt)
  18798. +{
  18799. + return do_vfsub_symlink(dir, dentry, symname, mode);
  18800. +}
  18801. +
  18802. +static inline
  18803. +int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
  18804. + int dlgt)
  18805. +{
  18806. + return do_vfsub_mknod(dir, dentry, mode, dev);
  18807. +}
  18808. +
  18809. +static inline
  18810. +int vfsub_link(struct dentry *src_dentry, struct inode *dir,
  18811. + struct dentry *dentry, int dlgt)
  18812. +{
  18813. + return do_vfsub_link(src_dentry, dir, dentry);
  18814. +}
  18815. +
  18816. +static inline
  18817. +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
  18818. + struct inode *dir, struct dentry *dentry, int dlgt)
  18819. +{
  18820. + return do_vfsub_rename(src_dir, src_dentry, dir, dentry);
  18821. +}
  18822. +
  18823. +static inline
  18824. +int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode,
  18825. + int dlgt)
  18826. +{
  18827. + return do_vfsub_mkdir(dir, dentry, mode);
  18828. +}
  18829. +
  18830. +static inline
  18831. +int vfsub_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
  18832. +{
  18833. + return do_vfsub_rmdir(dir, dentry);
  18834. +}
  18835. +
  18836. +static inline
  18837. +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
  18838. + loff_t *ppos, int dlgt)
  18839. +{
  18840. + return do_vfsub_read_u(file, ubuf, count, ppos);
  18841. +}
  18842. +
  18843. +static inline
  18844. +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18845. + int dlgt)
  18846. +{
  18847. + return do_vfsub_read_k(file, kbuf, count, ppos);
  18848. +}
  18849. +
  18850. +static inline
  18851. +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
  18852. + loff_t *ppos, int dlgt)
  18853. +{
  18854. + return do_vfsub_write_u(file, ubuf, count, ppos);
  18855. +}
  18856. +
  18857. +static inline
  18858. +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
  18859. + int dlgt)
  18860. +{
  18861. + return do_vfsub_write_k(file, kbuf, count, ppos);
  18862. +}
  18863. +
  18864. +static inline
  18865. +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
  18866. +{
  18867. + return do_vfsub_readdir(file, filldir, arg);
  18868. +}
  18869. +#endif /* CONFIG_AUFS_DLGT */
  18870. +
  18871. +/* ---------------------------------------------------------------------- */
  18872. +
  18873. +static inline
  18874. +struct dentry *vfsub_lock_rename(struct dentry *d1, struct dentry *d2)
  18875. +{
  18876. + struct dentry *d;
  18877. +
  18878. + lockdep_off();
  18879. + d = lock_rename(d1, d2);
  18880. + lockdep_on();
  18881. + return d;
  18882. +}
  18883. +
  18884. +static inline void vfsub_unlock_rename(struct dentry *d1, struct dentry *d2)
  18885. +{
  18886. + lockdep_off();
  18887. + unlock_rename(d1, d2);
  18888. + lockdep_on();
  18889. +}
  18890. +
  18891. +/* ---------------------------------------------------------------------- */
  18892. +
  18893. +int vfsub_notify_change(struct dentry *dentry, struct iattr *ia, int dlgt);
  18894. +int vfsub_unlink(struct inode *dir, struct dentry *dentry, int dlgt);
  18895. +int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt);
  18896. +
  18897. +#endif /* __KERNEL__ */
  18898. +#endif /* __AUFS_VFSUB_H__ */
  18899. diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c
  18900. new file mode 100755
  18901. index 0000000..b7f874c
  18902. --- /dev/null
  18903. +++ b/fs/aufs/whout.c
  18904. @@ -0,0 +1,933 @@
  18905. +/*
  18906. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  18907. + *
  18908. + * This program, aufs is free software; you can redistribute it and/or modify
  18909. + * it under the terms of the GNU General Public License as published by
  18910. + * the Free Software Foundation; either version 2 of the License, or
  18911. + * (at your option) any later version.
  18912. + *
  18913. + * This program is distributed in the hope that it will be useful,
  18914. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18915. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18916. + * GNU General Public License for more details.
  18917. + *
  18918. + * You should have received a copy of the GNU General Public License
  18919. + * along with this program; if not, write to the Free Software
  18920. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18921. + */
  18922. +
  18923. +/* $Id: whout.c,v 1.14 2007/05/14 03:40:40 sfjro Exp $ */
  18924. +
  18925. +#include <linux/fs.h>
  18926. +#include <linux/namei.h>
  18927. +#include <linux/random.h>
  18928. +#include <linux/security.h>
  18929. +#include "aufs.h"
  18930. +
  18931. +#define WH_MASK S_IRUGO
  18932. +
  18933. +/* If a directory contains this file, then it is opaque. We start with the
  18934. + * .wh. flag so that it is blocked by lookup.
  18935. + */
  18936. +static struct qstr diropq_name = {
  18937. + .name = AUFS_WH_DIROPQ,
  18938. + .len = sizeof(AUFS_WH_DIROPQ) - 1
  18939. +};
  18940. +
  18941. +/*
  18942. + * generate whiteout name, which is NOT terminated by NULL.
  18943. + * @name: original d_name.name
  18944. + * @len: original d_name.len
  18945. + * @wh: whiteout qstr
  18946. + * returns zero when succeeds, otherwise error.
  18947. + * succeeded value as wh->name should be freed by au_free_whname().
  18948. + */
  18949. +int au_alloc_whname(const char *name, int len, struct qstr *wh)
  18950. +{
  18951. + char *p;
  18952. +
  18953. + DEBUG_ON(!name || !len || !wh);
  18954. +
  18955. + if (unlikely(len > PATH_MAX - AUFS_WH_PFX_LEN))
  18956. + return -ENAMETOOLONG;
  18957. +
  18958. + wh->len = len + AUFS_WH_PFX_LEN;
  18959. + wh->name = p = kmalloc(wh->len, GFP_KERNEL);
  18960. + //if (LktrCond) {kfree(p); wh->name = p = NULL;}
  18961. + if (p) {
  18962. + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
  18963. + memcpy(p + AUFS_WH_PFX_LEN, name, len);
  18964. + //smp_mb();
  18965. + return 0;
  18966. + }
  18967. + return -ENOMEM;
  18968. +}
  18969. +
  18970. +void au_free_whname(struct qstr *wh)
  18971. +{
  18972. + DEBUG_ON(!wh || !wh->name);
  18973. + kfree(wh->name);
  18974. +#ifdef CONFIG_AUFS_DEBUG
  18975. + wh->name = NULL;
  18976. +#endif
  18977. +}
  18978. +
  18979. +/* ---------------------------------------------------------------------- */
  18980. +
  18981. +/*
  18982. + * test if the @wh_name exists under @hidden_parent.
  18983. + * @try_sio specifies the necessary of super-io.
  18984. + */
  18985. +int is_wh(struct dentry *hidden_parent, struct qstr *wh_name, int try_sio,
  18986. + struct lkup_args *lkup)
  18987. +{
  18988. + int err;
  18989. + struct dentry *wh_dentry;
  18990. + struct inode *hidden_dir;
  18991. +
  18992. + LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n", DLNPair(hidden_parent),
  18993. + wh_name->len, wh_name->name, lkup->nfsmnt, lkup->dlgt);
  18994. + hidden_dir = hidden_parent->d_inode;
  18995. + DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
  18996. + IMustLock(hidden_dir);
  18997. +
  18998. + if (!try_sio)
  18999. + wh_dentry = lkup_one(wh_name->name, hidden_parent,
  19000. + wh_name->len, lkup);
  19001. + else
  19002. + wh_dentry = sio_lkup_one(wh_name->name, hidden_parent,
  19003. + wh_name->len, lkup);
  19004. + //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
  19005. + err = PTR_ERR(wh_dentry);
  19006. + if (IS_ERR(wh_dentry))
  19007. + goto out;
  19008. +
  19009. + err = 0;
  19010. + if (!wh_dentry->d_inode)
  19011. + goto out_wh; /* success */
  19012. +
  19013. + err = 1;
  19014. + if (S_ISREG(wh_dentry->d_inode->i_mode))
  19015. + goto out_wh; /* success */
  19016. +
  19017. + err = -EIO;
  19018. + IOErr("%.*s Invalid whiteout entry type 0%o.\n",
  19019. + DLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
  19020. +
  19021. + out_wh:
  19022. + dput(wh_dentry);
  19023. + out:
  19024. + TraceErr(err);
  19025. + return err;
  19026. +}
  19027. +
  19028. +/*
  19029. + * test if the @hidden_dentry sets opaque or not.
  19030. + */
  19031. +int is_diropq(struct dentry *hidden_dentry, struct lkup_args *lkup)
  19032. +{
  19033. + int err;
  19034. + struct inode *hidden_dir;
  19035. +
  19036. + LKTRTrace("dentry %.*s\n", DLNPair(hidden_dentry));
  19037. + hidden_dir = hidden_dentry->d_inode;
  19038. + DEBUG_ON(!S_ISDIR(hidden_dir->i_mode));
  19039. + IMustLock(hidden_dir);
  19040. +
  19041. + err = is_wh(hidden_dentry, &diropq_name, /*try_sio*/1, lkup);
  19042. + TraceErr(err);
  19043. + return err;
  19044. +}
  19045. +
  19046. +/*
  19047. + * returns a negative dentry whose name is unique and temporary.
  19048. + */
  19049. +struct dentry *lkup_whtmp(struct dentry *hidden_parent, struct qstr *prefix,
  19050. + struct lkup_args *lkup)
  19051. +{
  19052. +#define HEX_LEN 4
  19053. + struct dentry *dentry;
  19054. + int len, i;
  19055. + char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
  19056. + + HEX_LEN + 1], *name, *p;
  19057. + static unsigned char cnt;
  19058. +
  19059. + LKTRTrace("hp %.*s, prefix %.*s\n",
  19060. + DLNPair(hidden_parent), prefix->len, prefix->name);
  19061. + DEBUG_ON(!hidden_parent->d_inode);
  19062. + IMustLock(hidden_parent->d_inode);
  19063. +
  19064. + name = defname;
  19065. + len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
  19066. + if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
  19067. + dentry = ERR_PTR(-ENAMETOOLONG);
  19068. + if (unlikely(len >= PATH_MAX))
  19069. + goto out;
  19070. + dentry = ERR_PTR(-ENOMEM);
  19071. + name = kmalloc(len + 1, GFP_KERNEL);
  19072. + //if (LktrCond) {kfree(name); name = NULL;}
  19073. + if (unlikely(!name))
  19074. + goto out;
  19075. + }
  19076. +
  19077. + // doubly whiteout-ed
  19078. + memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
  19079. + p = name + AUFS_WH_PFX_LEN * 2;
  19080. + memcpy(p, prefix->name, prefix->len);
  19081. + p += prefix->len;
  19082. + *p++ = '.';
  19083. + DEBUG_ON(name + len + 1 - p <= HEX_LEN);
  19084. +
  19085. + for (i = 0; i < 3; i++) {
  19086. + sprintf(p, "%.*d", HEX_LEN, cnt++);
  19087. + dentry = sio_lkup_one(name, hidden_parent, len, lkup);
  19088. + //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
  19089. + if (unlikely(IS_ERR(dentry) || !dentry->d_inode))
  19090. + goto out_name;
  19091. + dput(dentry);
  19092. + }
  19093. + //Warn("could not get random name\n");
  19094. + dentry = ERR_PTR(-EEXIST);
  19095. + Dbg("%.*s\n", len, name);
  19096. + BUG();
  19097. +
  19098. + out_name:
  19099. + if (unlikely(name != defname))
  19100. + kfree(name);
  19101. + out:
  19102. + TraceErrPtr(dentry);
  19103. + return dentry;
  19104. +#undef HEX_LEN
  19105. +}
  19106. +
  19107. +/*
  19108. + * rename the @dentry of @bindex to the whiteouted temporary name.
  19109. + */
  19110. +int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex)
  19111. +{
  19112. + int err;
  19113. + struct inode *hidden_dir;
  19114. + struct dentry *hidden_dentry, *hidden_parent, *tmp_dentry;
  19115. + struct super_block *sb;
  19116. + struct lkup_args lkup;
  19117. +
  19118. + LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex);
  19119. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  19120. + DEBUG_ON(!hidden_dentry || !hidden_dentry->d_inode);
  19121. + hidden_parent = hidden_dentry->d_parent;
  19122. + hidden_dir = hidden_parent->d_inode;
  19123. + IMustLock(hidden_dir);
  19124. +
  19125. + sb = dentry->d_sb;
  19126. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  19127. + lkup.dlgt = need_dlgt(sb);
  19128. + tmp_dentry = lkup_whtmp(hidden_parent, &hidden_dentry->d_name, &lkup);
  19129. + //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);}
  19130. + err = PTR_ERR(tmp_dentry);
  19131. + if (!IS_ERR(tmp_dentry)) {
  19132. + /* under the same dir, no need to lock_rename() */
  19133. + err = vfsub_rename(hidden_dir, hidden_dentry,
  19134. + hidden_dir, tmp_dentry, lkup.dlgt);
  19135. + //if (LktrCond) err = -1; //unavailable
  19136. + TraceErr(err);
  19137. + dput(tmp_dentry);
  19138. + }
  19139. +
  19140. + TraceErr(err);
  19141. + return err;
  19142. +}
  19143. +
  19144. +/* ---------------------------------------------------------------------- */
  19145. +
  19146. +int au_unlink_wh_dentry(struct inode *hidden_dir, struct dentry *wh_dentry,
  19147. + struct dentry *dentry, int dlgt)
  19148. +{
  19149. + int err;
  19150. +
  19151. + LKTRTrace("hi%lu, wh %.*s, d %p\n", hidden_dir->i_ino,
  19152. + DLNPair(wh_dentry), dentry);
  19153. + DEBUG_ON((dentry && dbwh(dentry) == -1)
  19154. + || !wh_dentry->d_inode
  19155. + || !S_ISREG(wh_dentry->d_inode->i_mode));
  19156. + IMustLock(hidden_dir);
  19157. +
  19158. + err = vfsub_unlink(hidden_dir, wh_dentry, dlgt);
  19159. + //if (LktrCond) err = -1; // unavailable
  19160. + if (!err && dentry)
  19161. + set_dbwh(dentry, -1);
  19162. +
  19163. + TraceErr(err);
  19164. + return err;
  19165. +}
  19166. +
  19167. +static int unlink_wh_name(struct dentry *hidden_parent, struct qstr *wh,
  19168. + struct lkup_args *lkup)
  19169. +{
  19170. + int err;
  19171. + struct inode *hidden_dir;
  19172. + struct dentry *hidden_dentry;
  19173. +
  19174. + LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(wh));
  19175. + hidden_dir = hidden_parent->d_inode;
  19176. + IMustLock(hidden_dir);
  19177. +
  19178. + // au_test_perm() is already done
  19179. + hidden_dentry = lkup_one(wh->name, hidden_parent, wh->len, lkup);
  19180. + //if (LktrCond) {dput(hidden_dentry); hidden_dentry = ERR_PTR(-1);}
  19181. + if (!IS_ERR(hidden_dentry)) {
  19182. + err = 0;
  19183. + if (hidden_dentry->d_inode)
  19184. + err = vfsub_unlink(hidden_dir, hidden_dentry,
  19185. + lkup->dlgt);
  19186. + dput(hidden_dentry);
  19187. + } else
  19188. + err = PTR_ERR(hidden_dentry);
  19189. +
  19190. + TraceErr(err);
  19191. + return err;
  19192. +}
  19193. +
  19194. +/* ---------------------------------------------------------------------- */
  19195. +
  19196. +static void clean_wh(struct inode *h_dir, struct dentry *wh)
  19197. +{
  19198. + TraceEnter();
  19199. + if (wh->d_inode) {
  19200. + int err = vfsub_unlink(h_dir, wh, /*dlgt*/0);
  19201. + if (unlikely(err))
  19202. + Warn("failed unlink %.*s (%d), ignored.\n",
  19203. + DLNPair(wh), err);
  19204. + }
  19205. +}
  19206. +
  19207. +static void clean_plink(struct inode *h_dir, struct dentry *plink)
  19208. +{
  19209. + TraceEnter();
  19210. + if (plink->d_inode) {
  19211. + int err = vfsub_rmdir(h_dir, plink, /*dlgt*/0);
  19212. + if (unlikely(err))
  19213. + Warn("failed rmdir %.*s (%d), ignored.\n",
  19214. + DLNPair(plink), err);
  19215. + }
  19216. +}
  19217. +
  19218. +static int test_linkable(struct inode *h_dir)
  19219. +{
  19220. + if (h_dir->i_op && h_dir->i_op->link)
  19221. + return 0;
  19222. + return -ENOSYS;
  19223. +}
  19224. +
  19225. +static int plink_dir(struct inode *h_dir, struct dentry *plink)
  19226. +{
  19227. + int err;
  19228. +
  19229. + err = -EEXIST;
  19230. + if (!plink->d_inode) {
  19231. + int mode = S_IRWXU;
  19232. + if (unlikely(au_is_nfs(plink->d_sb)))
  19233. + mode |= S_IXUGO;
  19234. + err = vfsub_mkdir(h_dir, plink, mode, /*dlgt*/0);
  19235. + } else if (S_ISDIR(plink->d_inode->i_mode))
  19236. + err = 0;
  19237. + else
  19238. + Err("unknown %.*s exists\n", DLNPair(plink));
  19239. +
  19240. + return err;
  19241. +}
  19242. +
  19243. +/*
  19244. + * initialize the whiteout base file/dir for @br.
  19245. + */
  19246. +int init_wh(struct dentry *h_root, struct aufs_branch *br,
  19247. + struct vfsmount *nfsmnt, struct super_block *sb)
  19248. +{
  19249. + int err;
  19250. + struct dentry *wh, *plink;
  19251. + struct inode *h_dir;
  19252. + static struct qstr base_name[] = {
  19253. + {.name = AUFS_WH_BASENAME, .len = sizeof(AUFS_WH_BASENAME) - 1},
  19254. + {.name = AUFS_WH_PLINKDIR, .len = sizeof(AUFS_WH_PLINKDIR) - 1}
  19255. + };
  19256. + struct lkup_args lkup = {
  19257. + .nfsmnt = nfsmnt,
  19258. + .dlgt = 0 // always no dlgt
  19259. + };
  19260. + const int do_plink = au_flag_test(sb, AuFlag_PLINK);
  19261. +
  19262. + LKTRTrace("nfsmnt %p\n", nfsmnt);
  19263. + BrWhMustWriteLock(br);
  19264. + SiMustWriteLock(sb);
  19265. + h_dir = h_root->d_inode;
  19266. + IMustLock(h_dir);
  19267. +
  19268. + // doubly whiteouted
  19269. + wh = lkup_wh(h_root, base_name + 0, &lkup);
  19270. + //if (LktrCond) {dput(wh); wh = ERR_PTR(-1);}
  19271. + err = PTR_ERR(wh);
  19272. + if (IS_ERR(wh))
  19273. + goto out;
  19274. + DEBUG_ON(br->br_wh && br->br_wh != wh);
  19275. +
  19276. + plink = lkup_wh(h_root, base_name + 1, &lkup);
  19277. + err = PTR_ERR(plink);
  19278. + if (IS_ERR(plink))
  19279. + goto out_dput_wh;
  19280. + DEBUG_ON(br->br_plink && br->br_plink != plink);
  19281. +
  19282. + dput(br->br_wh);
  19283. + dput(br->br_plink);
  19284. + br->br_wh = br->br_plink = NULL;
  19285. +
  19286. + err = 0;
  19287. + switch (br->br_perm) {
  19288. + case AuBr_RR:
  19289. + case AuBr_RO:
  19290. + case AuBr_RRWH:
  19291. + case AuBr_ROWH:
  19292. + clean_wh(h_dir, wh);
  19293. + clean_plink(h_dir, plink);
  19294. + break;
  19295. +
  19296. + case AuBr_RWNoLinkWH:
  19297. + clean_wh(h_dir, wh);
  19298. + if (do_plink) {
  19299. + err = test_linkable(h_dir);
  19300. + if (unlikely(err))
  19301. + goto out_nolink;
  19302. +
  19303. + err = plink_dir(h_dir, plink);
  19304. + if (unlikely(err))
  19305. + goto out_err;
  19306. + br->br_plink = dget(plink);
  19307. + } else
  19308. + clean_plink(h_dir, plink);
  19309. + break;
  19310. +
  19311. + case AuBr_RW:
  19312. + /*
  19313. + * for the moment, aufs supports the branch filesystem
  19314. + * which does not support link(2).
  19315. + * testing on FAT which does not support i_op->setattr() fully either,
  19316. + * copyup failed.
  19317. + * finally, such filesystem will not be used as the writable branch.
  19318. + */
  19319. + err = test_linkable(h_dir);
  19320. + if (unlikely(err))
  19321. + goto out_nolink;
  19322. +
  19323. + err = -EEXIST;
  19324. + if (!wh->d_inode)
  19325. + err = vfsub_create(h_dir, wh, WH_MASK, NULL, /*dlgt*/0);
  19326. + else if (S_ISREG(wh->d_inode->i_mode))
  19327. + err = 0;
  19328. + else
  19329. + Err("unknown %.*s/%.*s exists\n",
  19330. + DLNPair(h_root), DLNPair(wh));
  19331. + if (unlikely(err))
  19332. + goto out_err;
  19333. +
  19334. + if (do_plink) {
  19335. + err = plink_dir(h_dir, plink);
  19336. + if (unlikely(err))
  19337. + goto out_err;
  19338. + br->br_plink = dget(plink);
  19339. + } else
  19340. + clean_plink(h_dir, plink);
  19341. + br->br_wh = dget(wh);
  19342. + break;
  19343. +
  19344. + default:
  19345. + BUG();
  19346. + }
  19347. +
  19348. + out_dput:
  19349. + dput(plink);
  19350. + out_dput_wh:
  19351. + dput(wh);
  19352. + out:
  19353. + TraceErr(err);
  19354. + return err;
  19355. + out_nolink:
  19356. + Err("%.*s doesn't support link(2), use noplink and rw+nolwh\n",
  19357. + DLNPair(h_root));
  19358. + goto out_dput;
  19359. + out_err:
  19360. + Err("an error(%d) on the writable branch %.*s(%s)\n",
  19361. + err, DLNPair(h_root), au_sbtype(h_root->d_sb));
  19362. + goto out_dput;
  19363. +}
  19364. +
  19365. +struct reinit_br_wh {
  19366. + struct super_block *sb;
  19367. + struct aufs_branch *br;
  19368. +};
  19369. +
  19370. +static void reinit_br_wh(void *arg)
  19371. +{
  19372. + int err;
  19373. + struct reinit_br_wh *a = arg;
  19374. + struct inode *hidden_dir, *dir;
  19375. + struct dentry *hidden_root;
  19376. + aufs_bindex_t bindex;
  19377. +
  19378. + TraceEnter();
  19379. + DEBUG_ON(!a->br->br_wh || !a->br->br_wh->d_inode || current->fsuid);
  19380. +
  19381. + err = 0;
  19382. + /* big lock */
  19383. + si_write_lock(a->sb);
  19384. + if (unlikely(!br_writable(a->br->br_perm)))
  19385. + goto out;
  19386. + bindex = find_brindex(a->sb, a->br->br_id);
  19387. + if (unlikely(bindex < 0))
  19388. + goto out;
  19389. +
  19390. + dir = a->sb->s_root->d_inode;
  19391. + hidden_root = a->br->br_wh->d_parent;
  19392. + hidden_dir = hidden_root->d_inode;
  19393. + DEBUG_ON(!hidden_dir->i_op || !hidden_dir->i_op->link);
  19394. + hdir_lock(hidden_dir, dir, bindex);
  19395. + br_wh_write_lock(a->br);
  19396. + err = vfsub_unlink(hidden_dir, a->br->br_wh, /*dlgt*/0);
  19397. + //if (LktrCond) err = -1;
  19398. + dput(a->br->br_wh);
  19399. + a->br->br_wh = NULL;
  19400. + if (!err)
  19401. + err = init_wh(hidden_root, a->br, au_do_nfsmnt(a->br->br_mnt),
  19402. + a->sb);
  19403. + br_wh_write_unlock(a->br);
  19404. + hdir_unlock(hidden_dir, dir, bindex);
  19405. +
  19406. + out:
  19407. + atomic_dec(&a->br->br_wh_running);
  19408. + br_put(a->br);
  19409. + si_write_unlock(a->sb);
  19410. + au_mntput(a->sb);
  19411. + kfree(arg);
  19412. + if (unlikely(err))
  19413. + IOErr("err %d\n", err);
  19414. +}
  19415. +
  19416. +static void kick_reinit_br_wh(struct super_block *sb, struct aufs_branch *br)
  19417. +{
  19418. + int do_dec;
  19419. + struct reinit_br_wh *arg;
  19420. +
  19421. + do_dec = 1;
  19422. + if (atomic_inc_return(&br->br_wh_running) != 1)
  19423. + goto out;
  19424. +
  19425. + // ignore ENOMEM
  19426. + arg = kmalloc(sizeof(*arg), GFP_KERNEL);
  19427. + if (arg) {
  19428. + // dec(wh_running), kfree(arg) and br_put() in reinit function
  19429. + arg->sb = sb;
  19430. + arg->br = br;
  19431. + br_get(br);
  19432. + /* prohibit umount */
  19433. + au_mntget(sb);
  19434. + au_wkq_nowait(reinit_br_wh, arg, /*dlgt*/0);
  19435. + do_dec = 0;
  19436. + }
  19437. +
  19438. + out:
  19439. + if (do_dec)
  19440. + atomic_dec(&br->br_wh_running);
  19441. +}
  19442. +
  19443. +/*
  19444. + * create the whiteoute @wh.
  19445. + */
  19446. +static int link_or_create_wh(struct dentry *wh, struct super_block *sb,
  19447. + aufs_bindex_t bindex)
  19448. +{
  19449. + int err, dlgt;
  19450. + struct aufs_branch *br;
  19451. + struct dentry *hidden_parent;
  19452. + struct inode *hidden_dir;
  19453. +
  19454. + LKTRTrace("%.*s\n", DLNPair(wh));
  19455. + SiMustReadLock(sb);
  19456. + hidden_parent = wh->d_parent;
  19457. + hidden_dir = hidden_parent->d_inode;
  19458. + IMustLock(hidden_dir);
  19459. +
  19460. + dlgt = need_dlgt(sb);
  19461. + br = stobr(sb, bindex);
  19462. + br_wh_read_lock(br);
  19463. + if (br->br_wh) {
  19464. + err = vfsub_link(br->br_wh, hidden_dir, wh, dlgt);
  19465. + if (!err || err != -EMLINK)
  19466. + goto out;
  19467. +
  19468. + // link count full. re-initialize br_wh.
  19469. + kick_reinit_br_wh(sb, br);
  19470. + }
  19471. +
  19472. + // return this error in this context
  19473. + err = vfsub_create(hidden_dir, wh, WH_MASK, NULL, dlgt);
  19474. +
  19475. + out:
  19476. + br_wh_read_unlock(br);
  19477. + TraceErr(err);
  19478. + return err;
  19479. +}
  19480. +
  19481. +/* ---------------------------------------------------------------------- */
  19482. +
  19483. +/*
  19484. + * create or remove the diropq.
  19485. + */
  19486. +static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19487. + int do_create, int dlgt)
  19488. +{
  19489. + struct dentry *opq_dentry, *hidden_dentry;
  19490. + struct inode *hidden_dir;
  19491. + int err;
  19492. + struct super_block *sb;
  19493. + struct lkup_args lkup;
  19494. +
  19495. + LKTRTrace("%.*s, bindex %d, do_create %d\n", DLNPair(dentry),
  19496. + bindex, do_create);
  19497. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  19498. + DEBUG_ON(!hidden_dentry);
  19499. + hidden_dir = hidden_dentry->d_inode;
  19500. + DEBUG_ON(!hidden_dir || !S_ISDIR(hidden_dir->i_mode));
  19501. + IMustLock(hidden_dir);
  19502. +
  19503. + // already checked by au_test_perm().
  19504. + sb = dentry->d_sb;
  19505. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  19506. + lkup.dlgt = dlgt;
  19507. + opq_dentry = lkup_one(diropq_name.name, hidden_dentry, diropq_name.len,
  19508. + &lkup);
  19509. + //if (LktrCond) {dput(opq_dentry); opq_dentry = ERR_PTR(-1);}
  19510. + if (IS_ERR(opq_dentry))
  19511. + goto out;
  19512. +
  19513. + if (do_create) {
  19514. + DEBUG_ON(opq_dentry->d_inode);
  19515. + err = link_or_create_wh(opq_dentry, sb, bindex);
  19516. + //if (LktrCond) {vfs_unlink(hidden_dir, opq_dentry); err = -1;}
  19517. + if (!err) {
  19518. + set_dbdiropq(dentry, bindex);
  19519. + goto out; /* success */
  19520. + }
  19521. + } else {
  19522. + DEBUG_ON(/* !S_ISDIR(dentry->d_inode->i_mode)
  19523. + * || */!opq_dentry->d_inode);
  19524. + err = vfsub_unlink(hidden_dir, opq_dentry, lkup.dlgt);
  19525. + //if (LktrCond) err = -1;
  19526. + if (!err)
  19527. + set_dbdiropq(dentry, -1);
  19528. + }
  19529. + dput(opq_dentry);
  19530. + opq_dentry = ERR_PTR(err);
  19531. +
  19532. + out:
  19533. + TraceErrPtr(opq_dentry);
  19534. + return opq_dentry;
  19535. +}
  19536. +
  19537. +struct do_diropq_args {
  19538. + struct dentry **errp;
  19539. + struct dentry *dentry;
  19540. + aufs_bindex_t bindex;
  19541. + int do_create, dlgt;
  19542. +};
  19543. +
  19544. +static void call_do_diropq(void *args)
  19545. +{
  19546. + struct do_diropq_args *a = args;
  19547. + *a->errp = do_diropq(a->dentry, a->bindex, a->do_create, a->dlgt);
  19548. +}
  19549. +
  19550. +struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19551. + int do_create, int dlgt)
  19552. +{
  19553. + struct dentry *diropq, *hidden_dentry;
  19554. +
  19555. + LKTRTrace("%.*s, bindex %d, do_create %d\n",
  19556. + DLNPair(dentry), bindex, do_create);
  19557. +
  19558. + hidden_dentry = au_h_dptr_i(dentry, bindex);
  19559. + if (!au_test_perm(hidden_dentry->d_inode, MAY_EXEC | MAY_WRITE, dlgt))
  19560. + diropq = do_diropq(dentry, bindex, do_create, dlgt);
  19561. + else {
  19562. + struct do_diropq_args args = {
  19563. + .errp = &diropq,
  19564. + .dentry = dentry,
  19565. + .bindex = bindex,
  19566. + .do_create = do_create,
  19567. + .dlgt = dlgt
  19568. + };
  19569. + au_wkq_wait(call_do_diropq, &args, /*dlgt*/0);
  19570. + }
  19571. +
  19572. + TraceErrPtr(diropq);
  19573. + return diropq;
  19574. +}
  19575. +
  19576. +/* ---------------------------------------------------------------------- */
  19577. +
  19578. +/*
  19579. + * lookup whiteout dentry.
  19580. + * @hidden_parent: hidden parent dentry which must exist and be locked
  19581. + * @base_name: name of dentry which will be whiteouted
  19582. + * returns dentry for whiteout.
  19583. + */
  19584. +struct dentry *lkup_wh(struct dentry *hidden_parent, struct qstr *base_name,
  19585. + struct lkup_args *lkup)
  19586. +{
  19587. + int err;
  19588. + struct qstr wh_name;
  19589. + struct dentry *wh_dentry;
  19590. +
  19591. + LKTRTrace("%.*s/%.*s\n", DLNPair(hidden_parent), LNPair(base_name));
  19592. + IMustLock(hidden_parent->d_inode);
  19593. +
  19594. + err = au_alloc_whname(base_name->name, base_name->len, &wh_name);
  19595. + //if (LktrCond) {au_free_whname(&wh_name); err = -1;}
  19596. + wh_dentry = ERR_PTR(err);
  19597. + if (!err) {
  19598. + // do not superio.
  19599. + wh_dentry = lkup_one(wh_name.name, hidden_parent, wh_name.len,
  19600. + lkup);
  19601. + au_free_whname(&wh_name);
  19602. + }
  19603. + TraceErrPtr(wh_dentry);
  19604. + return wh_dentry;
  19605. +}
  19606. +
  19607. +/*
  19608. + * link/create a whiteout for @dentry on @bindex.
  19609. + */
  19610. +struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
  19611. + struct dentry *hidden_parent,
  19612. + struct lkup_args *lkup)
  19613. +{
  19614. + struct dentry *wh_dentry;
  19615. + int err;
  19616. + struct super_block *sb;
  19617. +
  19618. + LKTRTrace("%.*s/%.*s on b%d\n", DLNPair(hidden_parent),
  19619. + DLNPair(dentry), bindex);
  19620. +
  19621. + sb = dentry->d_sb;
  19622. + wh_dentry = lkup_wh(hidden_parent, &dentry->d_name, lkup);
  19623. + //au_nfsmnt(sb, bindex), need_dlgt(sb));
  19624. + //if (LktrCond) {dput(wh_dentry); wh_dentry = ERR_PTR(-1);}
  19625. + if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
  19626. + IMustLock(hidden_parent->d_inode);
  19627. + err = link_or_create_wh(wh_dentry, sb, bindex);
  19628. + if (!err)
  19629. + set_dbwh(dentry, bindex);
  19630. + else {
  19631. + dput(wh_dentry);
  19632. + wh_dentry = ERR_PTR(err);
  19633. + }
  19634. + }
  19635. +
  19636. + TraceErrPtr(wh_dentry);
  19637. + return wh_dentry;
  19638. +}
  19639. +
  19640. +/* ---------------------------------------------------------------------- */
  19641. +
  19642. +/* Delete all whiteouts in this directory in branch bindex. */
  19643. +static int del_wh_children(struct aufs_nhash *whlist,
  19644. + struct dentry *hidden_parent, aufs_bindex_t bindex,
  19645. + struct lkup_args *lkup)
  19646. +{
  19647. + int err, i;
  19648. + struct qstr wh_name;
  19649. + char *p;
  19650. + struct inode *hidden_dir;
  19651. + struct hlist_head *head;
  19652. + struct aufs_wh *tpos;
  19653. + struct hlist_node *pos;
  19654. + struct aufs_destr *str;
  19655. +
  19656. + LKTRTrace("%.*s\n", DLNPair(hidden_parent));
  19657. + hidden_dir = hidden_parent->d_inode;
  19658. + IMustLock(hidden_dir);
  19659. + DEBUG_ON(IS_RDONLY(hidden_dir));
  19660. + //SiMustReadLock(??);
  19661. +
  19662. + err = -ENOMEM;
  19663. + wh_name.name = p = __getname();
  19664. + //if (LktrCond) {__putname(p); wh_name.name = p = NULL;}
  19665. + if (unlikely(!wh_name.name))
  19666. + goto out;
  19667. + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
  19668. + p += AUFS_WH_PFX_LEN;
  19669. +
  19670. + // already checked by au_test_perm().
  19671. + err = 0;
  19672. + for (i = 0; !err && i < AUFS_NHASH_SIZE; i++) {
  19673. + head = whlist->heads + i;
  19674. + hlist_for_each_entry(tpos, pos, head, wh_hash) {
  19675. + if (tpos->wh_bindex != bindex)
  19676. + continue;
  19677. + str = &tpos->wh_str;
  19678. + if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
  19679. + memcpy(p, str->name, str->len);
  19680. + wh_name.len = AUFS_WH_PFX_LEN + str->len;
  19681. + err = unlink_wh_name(hidden_parent, &wh_name,
  19682. + lkup);
  19683. + //if (LktrCond) err = -1;
  19684. + if (!err)
  19685. + continue;
  19686. + break;
  19687. + }
  19688. + IOErr("whiteout name too long %.*s\n",
  19689. + str->len, str->name);
  19690. + err = -EIO;
  19691. + break;
  19692. + }
  19693. + }
  19694. + __putname(wh_name.name);
  19695. +
  19696. + out:
  19697. + TraceErr(err);
  19698. + return err;
  19699. +}
  19700. +
  19701. +struct del_wh_children_args {
  19702. + int *errp;
  19703. + struct aufs_nhash *whlist;
  19704. + struct dentry *hidden_parent;
  19705. + aufs_bindex_t bindex;
  19706. + struct lkup_args *lkup;
  19707. +};
  19708. +
  19709. +static void call_del_wh_children(void *args)
  19710. +{
  19711. + struct del_wh_children_args *a = args;
  19712. + *a->errp = del_wh_children(a->whlist, a->hidden_parent, a->bindex,
  19713. + a->lkup);
  19714. +}
  19715. +
  19716. +/* ---------------------------------------------------------------------- */
  19717. +
  19718. +/*
  19719. + * rmdir the whiteouted temporary named dir @hidden_dentry.
  19720. + * @whlist: whiteouted children.
  19721. + */
  19722. +int rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
  19723. + aufs_bindex_t bindex, struct inode *dir, struct inode *inode)
  19724. +{
  19725. + int err;
  19726. + struct inode *hidden_inode, *hidden_dir;
  19727. + struct lkup_args lkup;
  19728. + struct super_block *sb;
  19729. +
  19730. + LKTRTrace("hd %.*s, b%d, i%lu\n",
  19731. + DLNPair(hidden_dentry), bindex, dir->i_ino);
  19732. + IMustLock(dir);
  19733. + IiMustAnyLock(dir);
  19734. + hidden_dir = hidden_dentry->d_parent->d_inode;
  19735. + IMustLock(hidden_dir);
  19736. +
  19737. + sb = inode->i_sb;
  19738. + lkup.nfsmnt = au_nfsmnt(sb, bindex);
  19739. + lkup.dlgt = need_dlgt(sb);
  19740. + hidden_inode = hidden_dentry->d_inode;
  19741. + DEBUG_ON(hidden_inode != au_h_iptr_i(inode, bindex));
  19742. + hdir2_lock(hidden_inode, inode, bindex);
  19743. + if (!au_test_perm(hidden_inode, MAY_EXEC | MAY_WRITE, lkup.dlgt))
  19744. + err = del_wh_children(whlist, hidden_dentry, bindex, &lkup);
  19745. + else {
  19746. + // ugly
  19747. + int dlgt = lkup.dlgt;
  19748. + struct del_wh_children_args args = {
  19749. + .errp = &err,
  19750. + .whlist = whlist,
  19751. + .hidden_parent = hidden_dentry,
  19752. + .bindex = bindex,
  19753. + .lkup = &lkup
  19754. + };
  19755. +
  19756. + lkup.dlgt = 0;
  19757. + au_wkq_wait(call_del_wh_children, &args, /*dlgt*/0);
  19758. + lkup.dlgt = dlgt;
  19759. + }
  19760. + hdir_unlock(hidden_inode, inode, bindex);
  19761. +
  19762. + if (!err) {
  19763. + err = vfsub_rmdir(hidden_dir, hidden_dentry, lkup.dlgt);
  19764. + //d_drop(hidden_dentry);
  19765. + //if (LktrCond) err = -1;
  19766. + }
  19767. +
  19768. + if (!err) {
  19769. + if (ibstart(dir) == bindex) {
  19770. + au_cpup_attr_timesizes(dir);
  19771. + //au_cpup_attr_nlink(dir);
  19772. + dir->i_nlink--;
  19773. + }
  19774. + return 0; /* success */
  19775. + }
  19776. +
  19777. + Warn("failed removing %.*s(%d), ignored\n",
  19778. + DLNPair(hidden_dentry), err);
  19779. + return err;
  19780. +}
  19781. +
  19782. +static void do_rmdir_whtmp(void *arg)
  19783. +{
  19784. + int err;
  19785. + struct rmdir_whtmp_arg *a = arg;
  19786. + struct super_block *sb;
  19787. +
  19788. + LKTRTrace("%.*s, b%d, dir i%lu\n",
  19789. + DLNPair(a->h_dentry), a->bindex, a->dir->i_ino);
  19790. +
  19791. + i_lock(a->dir);
  19792. + sb = a->dir->i_sb;
  19793. + si_read_lock(sb);
  19794. + err = test_ro(sb, a->bindex, NULL);
  19795. + if (!err) {
  19796. + struct inode *hidden_dir = a->h_dentry->d_parent->d_inode;
  19797. +
  19798. + ii_write_lock_child(a->inode);
  19799. + ii_write_lock_parent(a->dir);
  19800. + hdir_lock(hidden_dir, a->dir, a->bindex);
  19801. + err = rmdir_whtmp(a->h_dentry, &a->whlist, a->bindex,
  19802. + a->dir, a->inode);
  19803. + hdir_unlock(hidden_dir, a->dir, a->bindex);
  19804. + ii_write_unlock(a->dir);
  19805. + ii_write_unlock(a->inode);
  19806. + }
  19807. + dput(a->h_dentry);
  19808. + nhash_fin(&a->whlist);
  19809. + iput(a->inode);
  19810. + si_read_unlock(sb);
  19811. + au_mntput(sb);
  19812. + i_unlock(a->dir);
  19813. + iput(a->dir);
  19814. + kfree(arg);
  19815. + if (unlikely(err))
  19816. + IOErr("err %d\n", err);
  19817. +}
  19818. +
  19819. +void kick_rmdir_whtmp(struct dentry *hidden_dentry, struct aufs_nhash *whlist,
  19820. + aufs_bindex_t bindex, struct inode *dir,
  19821. + struct inode *inode, struct rmdir_whtmp_arg *arg)
  19822. +{
  19823. + LKTRTrace("%.*s\n", DLNPair(hidden_dentry));
  19824. + IMustLock(dir);
  19825. +
  19826. + // all post-process will be done in do_rmdir_whtmp().
  19827. + arg->h_dentry = dget(hidden_dentry);
  19828. + nhash_init(&arg->whlist);
  19829. + nhash_move(&arg->whlist, whlist);
  19830. + arg->bindex = bindex;
  19831. + arg->dir = igrab(dir);
  19832. + arg->inode = igrab(inode);
  19833. + /* prohibit umount */
  19834. + au_mntget(dir->i_sb);
  19835. +
  19836. + au_wkq_nowait(do_rmdir_whtmp, arg, /*dlgt*/0);
  19837. +}
  19838. diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h
  19839. new file mode 100755
  19840. index 0000000..d44c3cd
  19841. --- /dev/null
  19842. +++ b/fs/aufs/whout.h
  19843. @@ -0,0 +1,87 @@
  19844. +/*
  19845. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  19846. + *
  19847. + * This program, aufs is free software; you can redistribute it and/or modify
  19848. + * it under the terms of the GNU General Public License as published by
  19849. + * the Free Software Foundation; either version 2 of the License, or
  19850. + * (at your option) any later version.
  19851. + *
  19852. + * This program is distributed in the hope that it will be useful,
  19853. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19854. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19855. + * GNU General Public License for more details.
  19856. + *
  19857. + * You should have received a copy of the GNU General Public License
  19858. + * along with this program; if not, write to the Free Software
  19859. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19860. + */
  19861. +
  19862. +/* $Id: whout.h,v 1.8 2007/05/14 03:41:52 sfjro Exp $ */
  19863. +
  19864. +#ifndef __AUFS_WHOUT_H__
  19865. +#define __AUFS_WHOUT_H__
  19866. +
  19867. +#ifdef __KERNEL__
  19868. +
  19869. +#include <linux/fs.h>
  19870. +#include <linux/aufs_type.h>
  19871. +
  19872. +int au_alloc_whname(const char *name, int len, struct qstr *wh);
  19873. +void au_free_whname(struct qstr *wh);
  19874. +
  19875. +struct lkup_args;
  19876. +int is_wh(struct dentry *h_parent, struct qstr *wh_name, int try_sio,
  19877. + struct lkup_args *lkup);
  19878. +int is_diropq(struct dentry *h_dentry, struct lkup_args *lkup);
  19879. +
  19880. +struct dentry *lkup_whtmp(struct dentry *h_parent, struct qstr *prefix,
  19881. + struct lkup_args *lkup);
  19882. +int rename_whtmp(struct dentry *dentry, aufs_bindex_t bindex);
  19883. +int au_unlink_wh_dentry(struct inode *h_dir, struct dentry *wh_dentry,
  19884. + struct dentry *dentry, int dlgt);
  19885. +
  19886. +struct aufs_branch;
  19887. +int init_wh(struct dentry *h_parent, struct aufs_branch *br,
  19888. + struct vfsmount *nfsmnt, struct super_block *sb);
  19889. +
  19890. +struct dentry *sio_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19891. + int do_create, int dlgt);
  19892. +
  19893. +struct dentry *lkup_wh(struct dentry *h_parent, struct qstr *base_name,
  19894. + struct lkup_args *lkup);
  19895. +struct dentry *simple_create_wh(struct dentry *dentry, aufs_bindex_t bindex,
  19896. + struct dentry *h_parent,
  19897. + struct lkup_args *lkup);
  19898. +
  19899. +/* real rmdir the whiteout-ed dir */
  19900. +struct rmdir_whtmp_arg {
  19901. + struct dentry *h_dentry;
  19902. + struct aufs_nhash whlist;
  19903. + aufs_bindex_t bindex;
  19904. + struct inode *dir, *inode;
  19905. +};
  19906. +
  19907. +struct aufs_nhash;
  19908. +int rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
  19909. + aufs_bindex_t bindex, struct inode *dir, struct inode *inode);
  19910. +void kick_rmdir_whtmp(struct dentry *h_dentry, struct aufs_nhash *whlist,
  19911. + aufs_bindex_t bindex, struct inode *dir,
  19912. + struct inode *inode, struct rmdir_whtmp_arg *arg);
  19913. +
  19914. +/* ---------------------------------------------------------------------- */
  19915. +
  19916. +static inline
  19917. +struct dentry *create_diropq(struct dentry *dentry, aufs_bindex_t bindex,
  19918. + int dlgt)
  19919. +{
  19920. + return sio_diropq(dentry, bindex, 1, dlgt);
  19921. +}
  19922. +
  19923. +static inline
  19924. +int remove_diropq(struct dentry *dentry, aufs_bindex_t bindex, int dlgt)
  19925. +{
  19926. + return PTR_ERR(sio_diropq(dentry, bindex, 0, dlgt));
  19927. +}
  19928. +
  19929. +#endif /* __KERNEL__ */
  19930. +#endif /* __AUFS_WHOUT_H__ */
  19931. diff --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c
  19932. new file mode 100755
  19933. index 0000000..b5ab023
  19934. --- /dev/null
  19935. +++ b/fs/aufs/wkq.c
  19936. @@ -0,0 +1,283 @@
  19937. +/*
  19938. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  19939. + *
  19940. + * This program, aufs is free software; you can redistribute it and/or modify
  19941. + * it under the terms of the GNU General Public License as published by
  19942. + * the Free Software Foundation; either version 2 of the License, or
  19943. + * (at your option) any later version.
  19944. + *
  19945. + * This program is distributed in the hope that it will be useful,
  19946. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19947. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19948. + * GNU General Public License for more details.
  19949. + *
  19950. + * You should have received a copy of the GNU General Public License
  19951. + * along with this program; if not, write to the Free Software
  19952. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19953. + */
  19954. +
  19955. +/* $Id: wkq.c,v 1.14 2007/05/14 03:39:10 sfjro Exp $ */
  19956. +
  19957. +#include <linux/module.h>
  19958. +#include "aufs.h"
  19959. +
  19960. +struct au_wkq *au_wkq;
  19961. +
  19962. +struct au_cred {
  19963. +#ifdef CONFIG_AUFS_DLGT
  19964. + uid_t fsuid;
  19965. + gid_t fsgid;
  19966. + kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
  19967. + //unsigned keep_capabilities:1;
  19968. + //struct user_struct *user;
  19969. + //struct fs_struct *fs;
  19970. + //struct nsproxy *nsproxy;
  19971. +#endif
  19972. +};
  19973. +
  19974. +struct au_wkinfo {
  19975. + struct work_struct wk;
  19976. +
  19977. + unsigned int wait:1;
  19978. + unsigned int dlgt:1;
  19979. + struct au_cred cred;
  19980. +
  19981. + au_wkq_func_t func;
  19982. + void *args;
  19983. +
  19984. + atomic_t *busyp;
  19985. + struct completion *comp;
  19986. +};
  19987. +
  19988. +/* ---------------------------------------------------------------------- */
  19989. +
  19990. +#ifdef CONFIG_AUFS_DLGT
  19991. +static void cred_store(struct au_cred *cred)
  19992. +{
  19993. + cred->fsuid = current->fsuid;
  19994. + cred->fsgid = current->fsgid;
  19995. + cred->cap_effective = current->cap_effective;
  19996. + cred->cap_inheritable = current->cap_inheritable;
  19997. + cred->cap_permitted = current->cap_permitted;
  19998. +}
  19999. +
  20000. +static void cred_revert(struct au_cred *cred)
  20001. +{
  20002. + DEBUG_ON(!is_au_wkq(current));
  20003. + current->fsuid = cred->fsuid;
  20004. + current->fsgid = cred->fsgid;
  20005. + current->cap_effective = cred->cap_effective;
  20006. + current->cap_inheritable = cred->cap_inheritable;
  20007. + current->cap_permitted = cred->cap_permitted;
  20008. +}
  20009. +
  20010. +static void cred_switch(struct au_cred *old, struct au_cred *new)
  20011. +{
  20012. + cred_store(old);
  20013. + cred_revert(new);
  20014. +}
  20015. +#endif
  20016. +
  20017. +/* ---------------------------------------------------------------------- */
  20018. +
  20019. +static void update_busy(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
  20020. +{
  20021. +#ifdef CONFIG_AUFS_SYSAUFS
  20022. + unsigned int new, old;
  20023. +
  20024. + do {
  20025. + new = atomic_read(wkinfo->busyp);
  20026. + old = wkq->max_busy;
  20027. + if (new <= old)
  20028. + break;
  20029. + } while (cmpxchg(&wkq->max_busy, old, new) == old);
  20030. +#endif
  20031. +}
  20032. +
  20033. +static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
  20034. +{
  20035. + wkinfo->busyp = &wkq->busy;
  20036. + update_busy(wkq, wkinfo);
  20037. + if (wkinfo->wait)
  20038. + return !queue_work(wkq->q, &wkinfo->wk);
  20039. + else
  20040. + return !schedule_work(&wkinfo->wk);
  20041. +}
  20042. +
  20043. +static void do_wkq(struct au_wkinfo *wkinfo)
  20044. +{
  20045. + unsigned int idle, n;
  20046. + int i, idle_idx;
  20047. +
  20048. + TraceEnter();
  20049. +
  20050. + while (1) {
  20051. + if (wkinfo->wait) {
  20052. + idle_idx = 0;
  20053. + idle = UINT_MAX;
  20054. + for (i = 0; i < aufs_nwkq; i++) {
  20055. + n = atomic_inc_return(&au_wkq[i].busy);
  20056. + if (n == 1 && !enqueue(au_wkq + i, wkinfo))
  20057. + return; /* success */
  20058. +
  20059. + if (n < idle) {
  20060. + idle_idx = i;
  20061. + idle = n;
  20062. + }
  20063. + atomic_dec(&au_wkq[i].busy);
  20064. + }
  20065. + } else
  20066. + idle_idx = aufs_nwkq;
  20067. +
  20068. + atomic_inc(&au_wkq[idle_idx].busy);
  20069. + if (!enqueue(au_wkq + idle_idx, wkinfo))
  20070. + return; /* success */
  20071. +
  20072. + /* impossible? */
  20073. + Warn1("failed to queue_work()\n");
  20074. + yield();
  20075. + }
  20076. +}
  20077. +
  20078. +static AuWkqFunc(wkq_func, wk)
  20079. +{
  20080. + struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
  20081. +
  20082. + LKTRTrace("wkinfo{%u, %u, %p, %p, %p}\n",
  20083. + wkinfo->wait, wkinfo->dlgt, wkinfo->func, wkinfo->busyp,
  20084. + wkinfo->comp);
  20085. +#ifdef CONFIG_AUFS_DLGT
  20086. + if (!wkinfo->dlgt)
  20087. + wkinfo->func(wkinfo->args);
  20088. + else {
  20089. + struct au_cred cred;
  20090. + cred_switch(&cred, &wkinfo->cred);
  20091. + wkinfo->func(wkinfo->args);
  20092. + cred_revert(&cred);
  20093. + }
  20094. +#else
  20095. + wkinfo->func(wkinfo->args);
  20096. +#endif
  20097. + atomic_dec(wkinfo->busyp);
  20098. + if (wkinfo->wait)
  20099. + complete(wkinfo->comp);
  20100. + else {
  20101. + kfree(wkinfo);
  20102. + module_put(THIS_MODULE);
  20103. + }
  20104. +}
  20105. +
  20106. +void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait)
  20107. +{
  20108. + DECLARE_COMPLETION_ONSTACK(comp);
  20109. + struct au_wkinfo _wkinfo = {
  20110. + .wait = 1,
  20111. + .dlgt = !!dlgt,
  20112. + .func = func,
  20113. + .args = args,
  20114. + .comp = &comp
  20115. + }, *wkinfo = &_wkinfo;
  20116. +
  20117. + LKTRTrace("dlgt %d, do_wait %d\n", dlgt, do_wait);
  20118. + DEBUG_ON(is_au_wkq(current));
  20119. +
  20120. + if (unlikely(!do_wait)) {
  20121. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  20122. + /*
  20123. + * never fail.
  20124. + * wkq_func() must free this wkinfo.
  20125. + * it highly depends upon the implementation of workqueue.
  20126. + */
  20127. + wait_event(wq, (wkinfo = kmalloc(sizeof(*wkinfo), GFP_KERNEL)));
  20128. + wkinfo->wait = 0;
  20129. + wkinfo->dlgt = !!dlgt;
  20130. + wkinfo->func = func;
  20131. + wkinfo->args = args;
  20132. + wkinfo->comp = NULL;
  20133. + __module_get(THIS_MODULE);
  20134. + }
  20135. +
  20136. + AuInitWkq(&wkinfo->wk, wkq_func);
  20137. +#ifdef CONFIG_AUFS_DLGT
  20138. + if (dlgt)
  20139. + cred_store(&wkinfo->cred);
  20140. +#endif
  20141. + do_wkq(wkinfo);
  20142. + if (do_wait)
  20143. + wait_for_completion(wkinfo->comp);
  20144. +}
  20145. +
  20146. +#if 0
  20147. +void au_wkq_wait_nwtask(void)
  20148. +{
  20149. + static DECLARE_WAIT_QUEUE_HEAD(wq);
  20150. + wait_event(wq, !atomic_read(&au_wkq[aufs_nwkq].busy));
  20151. +}
  20152. +#endif
  20153. +
  20154. +void au_wkq_fin(void)
  20155. +{
  20156. + int i;
  20157. +
  20158. + TraceEnter();
  20159. +
  20160. + for (i = 0; i < aufs_nwkq; i++)
  20161. + if (au_wkq[i].q && !IS_ERR(au_wkq[i].q))
  20162. + destroy_workqueue(au_wkq[i].q);
  20163. + kfree(au_wkq);
  20164. +}
  20165. +
  20166. +int __init au_wkq_init(void)
  20167. +{
  20168. + int err, i;
  20169. + struct au_wkq *nowaitq;
  20170. +
  20171. + LKTRTrace("%d\n", aufs_nwkq);
  20172. +
  20173. + /* '+1' is for accounting of nowait queue */
  20174. + err = -ENOMEM;
  20175. + au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_KERNEL);
  20176. + if (unlikely(!au_wkq))
  20177. + goto out;
  20178. +
  20179. + err = 0;
  20180. + for (i = 0; i < aufs_nwkq; i++) {
  20181. + au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
  20182. + if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
  20183. + atomic_set(&au_wkq[i].busy, 0);
  20184. + au_wkq[i].max_busy = 0;
  20185. + continue;
  20186. + }
  20187. +
  20188. + err = PTR_ERR(au_wkq[i].q);
  20189. + au_wkq_fin();
  20190. + break;
  20191. + }
  20192. +
  20193. + /* nowait accounting */
  20194. + nowaitq = au_wkq + aufs_nwkq;
  20195. + atomic_set(&nowaitq->busy, 0);
  20196. + nowaitq->max_busy = 0;
  20197. + nowaitq->q = NULL;
  20198. +
  20199. +#if 0 // test accouting
  20200. + if (!err) {
  20201. + static void f(void *args) {
  20202. + DbgSleep(1);
  20203. + }
  20204. + int i;
  20205. + //au_debug_on();
  20206. + LKTRTrace("f %p\n", f);
  20207. + for (i = 0; i < 10; i++)
  20208. + au_wkq_nowait(f, NULL, 0);
  20209. + for (i = 0; i < aufs_nwkq; i++)
  20210. + au_wkq_wait(f, NULL, 0);
  20211. + DbgSleep(11);
  20212. + //au_debug_off();
  20213. + }
  20214. +#endif
  20215. +
  20216. + out:
  20217. + TraceErr(err);
  20218. + return err;
  20219. +}
  20220. diff --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h
  20221. new file mode 100755
  20222. index 0000000..cc1bb25
  20223. --- /dev/null
  20224. +++ b/fs/aufs/wkq.h
  20225. @@ -0,0 +1,81 @@
  20226. +/*
  20227. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  20228. + *
  20229. + * This program, aufs is free software; you can redistribute it and/or modify
  20230. + * it under the terms of the GNU General Public License as published by
  20231. + * the Free Software Foundation; either version 2 of the License, or
  20232. + * (at your option) any later version.
  20233. + *
  20234. + * This program is distributed in the hope that it will be useful,
  20235. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20236. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20237. + * GNU General Public License for more details.
  20238. + *
  20239. + * You should have received a copy of the GNU General Public License
  20240. + * along with this program; if not, write to the Free Software
  20241. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20242. + */
  20243. +
  20244. +/* $Id: wkq.h,v 1.9 2007/05/14 03:39:10 sfjro Exp $ */
  20245. +
  20246. +#ifndef __AUFS_WKQ_H__
  20247. +#define __AUFS_WKQ_H__
  20248. +
  20249. +#ifdef __KERNEL__
  20250. +
  20251. +#include <linux/sched.h>
  20252. +#include <linux/version.h>
  20253. +#include <linux/workqueue.h>
  20254. +
  20255. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  20256. +#define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work)
  20257. +#endif
  20258. +
  20259. +/* ---------------------------------------------------------------------- */
  20260. +
  20261. +/* internal workqueue named AUFS_WKQ_NAME */
  20262. +struct au_wkq {
  20263. + struct workqueue_struct *q;
  20264. +
  20265. + /* accounting */
  20266. + atomic_t busy;
  20267. + unsigned int max_busy;
  20268. +} ;//__attribute__ ((aligned));
  20269. +
  20270. +typedef void (*au_wkq_func_t)(void *args);
  20271. +
  20272. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
  20273. +#define AuInitWkq(wk, func) INIT_WORK(wk, func)
  20274. +#define AuWkqFunc(name, arg) void name(struct work_struct *arg)
  20275. +#else
  20276. +typedef void (*work_func_t)(void *arg);
  20277. +#define AuInitWkq(wk, func) INIT_WORK(wk, func, wk)
  20278. +#define AuWkqFunc(name, arg) void name(void *arg)
  20279. +#endif
  20280. +
  20281. +extern struct au_wkq *au_wkq;
  20282. +
  20283. +void au_wkq_run(au_wkq_func_t func, void *args, int dlgt, int do_wait);
  20284. +//void au_wkq_wait_nwtask(void);
  20285. +int __init au_wkq_init(void);
  20286. +void au_wkq_fin(void);
  20287. +
  20288. +/* ---------------------------------------------------------------------- */
  20289. +
  20290. +static inline int is_au_wkq(struct task_struct *tsk)
  20291. +{
  20292. + return (!tsk->mm && !strcmp(current->comm, AUFS_WKQ_NAME));
  20293. +}
  20294. +
  20295. +static inline void au_wkq_wait(au_wkq_func_t func, void *args, int dlgt)
  20296. +{
  20297. + au_wkq_run(func, args, dlgt, /*do_wait*/1);
  20298. +}
  20299. +
  20300. +static inline void au_wkq_nowait(au_wkq_func_t func, void *args, int dlgt)
  20301. +{
  20302. + au_wkq_run(func, args, dlgt, /*do_wait*/0);
  20303. +}
  20304. +
  20305. +#endif /* __KERNEL__ */
  20306. +#endif /* __AUFS_WKQ_H__ */
  20307. diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c
  20308. new file mode 100755
  20309. index 0000000..145491e
  20310. --- /dev/null
  20311. +++ b/fs/aufs/xino.c
  20312. @@ -0,0 +1,644 @@
  20313. +/*
  20314. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  20315. + *
  20316. + * This program, aufs is free software; you can redistribute it and/or modify
  20317. + * it under the terms of the GNU General Public License as published by
  20318. + * the Free Software Foundation; either version 2 of the License, or
  20319. + * (at your option) any later version.
  20320. + *
  20321. + * This program is distributed in the hope that it will be useful,
  20322. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20323. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20324. + * GNU General Public License for more details.
  20325. + *
  20326. + * You should have received a copy of the GNU General Public License
  20327. + * along with this program; if not, write to the Free Software
  20328. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20329. + */
  20330. +
  20331. +/* $Id: xino.c,v 1.27 2007/05/14 03:39:10 sfjro Exp $ */
  20332. +
  20333. +//#include <linux/fs.h>
  20334. +#include <linux/fsnotify.h>
  20335. +#include <asm/uaccess.h>
  20336. +#include "aufs.h"
  20337. +
  20338. +static readf_t find_readf(struct file *h_file)
  20339. +{
  20340. + const struct file_operations *fop = h_file->f_op;
  20341. +
  20342. + if (fop) {
  20343. + if (fop->read)
  20344. + return fop->read;
  20345. + if (fop->aio_read)
  20346. + return do_sync_read;
  20347. + }
  20348. + return ERR_PTR(-ENOSYS);
  20349. +}
  20350. +
  20351. +static writef_t find_writef(struct file *h_file)
  20352. +{
  20353. + const struct file_operations *fop = h_file->f_op;
  20354. +
  20355. + if (fop) {
  20356. + if (fop->write)
  20357. + return fop->write;
  20358. + if (fop->aio_write)
  20359. + return do_sync_write;
  20360. + }
  20361. + return ERR_PTR(-ENOSYS);
  20362. +}
  20363. +
  20364. +/* ---------------------------------------------------------------------- */
  20365. +
  20366. +static ssize_t xino_fread(readf_t func, struct file *file, void *buf,
  20367. + size_t size, loff_t *pos)
  20368. +{
  20369. + ssize_t err;
  20370. + mm_segment_t oldfs;
  20371. +
  20372. + LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
  20373. + DLNPair(file->f_dentry), (unsigned long)size, *pos);
  20374. +
  20375. + oldfs = get_fs();
  20376. + set_fs(KERNEL_DS);
  20377. + do {
  20378. + err = func(file, (char __user*)buf, size, pos);
  20379. + } while (err == -EAGAIN || err == -EINTR);
  20380. + set_fs(oldfs);
  20381. +
  20382. +#if 0
  20383. + if (err > 0)
  20384. + fsnotify_access(file->f_dentry);
  20385. +#endif
  20386. +
  20387. + TraceErr(err);
  20388. + return err;
  20389. +}
  20390. +
  20391. +/* ---------------------------------------------------------------------- */
  20392. +
  20393. +static ssize_t do_xino_fwrite(writef_t func, struct file *file, void *buf,
  20394. + size_t size, loff_t *pos)
  20395. +{
  20396. + ssize_t err;
  20397. + mm_segment_t oldfs;
  20398. +
  20399. + lockdep_off();
  20400. + oldfs = get_fs();
  20401. + set_fs(KERNEL_DS);
  20402. + do {
  20403. + err = func(file, (const char __user*)buf, size, pos);
  20404. + } while (err == -EAGAIN || err == -EINTR);
  20405. + set_fs(oldfs);
  20406. + lockdep_on();
  20407. +
  20408. +#if 0
  20409. + if (err > 0)
  20410. + fsnotify_modify(file->f_dentry);
  20411. +#endif
  20412. +
  20413. + TraceErr(err);
  20414. + return err;
  20415. +}
  20416. +
  20417. +struct do_xino_fwrite_args {
  20418. + ssize_t *errp;
  20419. + writef_t func;
  20420. + struct file *file;
  20421. + void *buf;
  20422. + size_t size;
  20423. + loff_t *pos;
  20424. +};
  20425. +
  20426. +static void call_do_xino_fwrite(void *args)
  20427. +{
  20428. + struct do_xino_fwrite_args *a = args;
  20429. + *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
  20430. +}
  20431. +
  20432. +static ssize_t xino_fwrite(writef_t func, struct file *file, void *buf,
  20433. + size_t size, loff_t *pos)
  20434. +{
  20435. + ssize_t err;
  20436. +
  20437. + LKTRTrace("%.*s, sz %lu, *pos %Ld\n",
  20438. + DLNPair(file->f_dentry), (unsigned long)size, *pos);
  20439. +
  20440. + // signal block and no wkq?
  20441. + /*
  20442. + * it breaks RLIMIT_FSIZE and normal user's limit,
  20443. + * users should care about quota and real 'filesystem full.'
  20444. + */
  20445. + if (!is_au_wkq(current)) {
  20446. + struct do_xino_fwrite_args args = {
  20447. + .errp = &err,
  20448. + .func = func,
  20449. + .file = file,
  20450. + .buf = buf,
  20451. + .size = size,
  20452. + .pos = pos
  20453. + };
  20454. + au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0);
  20455. + } else
  20456. + err = do_xino_fwrite(func, file, buf, size, pos);
  20457. +
  20458. + TraceErr(err);
  20459. + return err;
  20460. +}
  20461. +
  20462. +/* ---------------------------------------------------------------------- */
  20463. +
  20464. +/*
  20465. + * write @ino to the xinofile for the specified branch{@sb, @bindex}
  20466. + * at the position of @_ino.
  20467. + * when @ino is zero, it is written to the xinofile and means no entry.
  20468. + */
  20469. +int xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  20470. + struct xino *xino)
  20471. +{
  20472. + struct aufs_branch *br;
  20473. + loff_t pos;
  20474. + ssize_t sz;
  20475. +
  20476. + LKTRTrace("b%d, hi%lu, i%lu\n", bindex, h_ino, xino->ino);
  20477. + //DEBUG_ON(!xino->ino /* || !xino->h_gen */);
  20478. + //WARN_ON(bindex == 0 && h_ino == 31);
  20479. +
  20480. + if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
  20481. + return 0;
  20482. +
  20483. + br = stobr(sb, bindex);
  20484. + DEBUG_ON(!br || !br->br_xino);
  20485. + pos = h_ino * sizeof(*xino);
  20486. + sz = xino_fwrite(br->br_xino_write, br->br_xino, xino, sizeof(*xino),
  20487. + &pos);
  20488. + //if (LktrCond) sz = 1;
  20489. + if (sz == sizeof(*xino))
  20490. + return 0; /* success */
  20491. +
  20492. + IOErr("write failed (%ld)\n", (long)sz);
  20493. + return -EIO;
  20494. +}
  20495. +
  20496. +int xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino)
  20497. +{
  20498. + struct xino xino = {
  20499. + .ino = 0
  20500. + };
  20501. + return xino_write(sb, bindex, h_ino, &xino);
  20502. +}
  20503. +
  20504. +// why is not atomic_long_inc_return defined?
  20505. +static DEFINE_SPINLOCK(alir_lock);
  20506. +static long atomic_long_inc_return(atomic_long_t *a)
  20507. +{
  20508. + long l;
  20509. +
  20510. + spin_lock(&alir_lock);
  20511. + atomic_long_inc(a);
  20512. + l = atomic_long_read(a);
  20513. + spin_unlock(&alir_lock);
  20514. + return l;
  20515. +}
  20516. +
  20517. +ino_t xino_new_ino(struct super_block *sb)
  20518. +{
  20519. + ino_t ino;
  20520. +
  20521. + TraceEnter();
  20522. + ino = atomic_long_inc_return(&stosi(sb)->si_xino);
  20523. + BUILD_BUG_ON(AUFS_FIRST_INO < AUFS_ROOT_INO);
  20524. + if (ino >= AUFS_ROOT_INO)
  20525. + return ino;
  20526. + else {
  20527. + atomic_long_dec(&stosi(sb)->si_xino);
  20528. + IOErr1("inode number overflow\n");
  20529. + return 0;
  20530. + }
  20531. +}
  20532. +
  20533. +/*
  20534. + * read @ino from xinofile for the specified branch{@sb, @bindex}
  20535. + * at the position of @h_ino.
  20536. + * if @ino does not exist and @do_new is true, get new one.
  20537. + */
  20538. +int xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
  20539. + struct xino *xino)
  20540. +{
  20541. + int err;
  20542. + struct aufs_branch *br;
  20543. + struct file *file;
  20544. + loff_t pos;
  20545. + ssize_t sz;
  20546. +
  20547. + LKTRTrace("b%d, hi%lu\n", bindex, h_ino);
  20548. +
  20549. + err = 0;
  20550. + xino->ino = 0;
  20551. + if (unlikely(!au_flag_test(sb, AuFlag_XINO)))
  20552. + return 0; /* no ino */
  20553. +
  20554. + br = stobr(sb, bindex);
  20555. + file = br->br_xino;
  20556. + DEBUG_ON(!file);
  20557. + pos = h_ino * sizeof(*xino);
  20558. + if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*xino))
  20559. + return 0; /* no ino */
  20560. +
  20561. + sz = xino_fread(br->br_xino_read, file, xino, sizeof(*xino), &pos);
  20562. + if (sz == sizeof(*xino))
  20563. + return 0; /* success */
  20564. +
  20565. + err = sz;
  20566. + if (unlikely(sz >= 0)) {
  20567. + err = -EIO;
  20568. + IOErr("xino read error (%ld)\n", (long)sz);
  20569. + }
  20570. +
  20571. + TraceErr(err);
  20572. + return err;
  20573. +}
  20574. +
  20575. +/* ---------------------------------------------------------------------- */
  20576. +
  20577. +struct file *xino_create(struct super_block *sb, char *fname, int silent,
  20578. + struct dentry *parent)
  20579. +{
  20580. + struct file *file;
  20581. + int err;
  20582. + struct dentry *hidden_parent;
  20583. + struct inode *hidden_dir;
  20584. + //const int udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY);
  20585. +
  20586. + LKTRTrace("%s\n", fname);
  20587. + //DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
  20588. +
  20589. + // LSM may detect it
  20590. + // use sio?
  20591. + file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
  20592. + S_IRUGO | S_IWUGO);
  20593. + //file = ERR_PTR(-1);
  20594. + if (IS_ERR(file)) {
  20595. + if (!silent)
  20596. + Err("open %s(%ld)\n", fname, PTR_ERR(file));
  20597. + return file;
  20598. + }
  20599. +#if 0
  20600. + if (unlikely(udba && parent))
  20601. + au_direval_dec(parent);
  20602. +#endif
  20603. +
  20604. + /* keep file count */
  20605. + hidden_parent = dget_parent(file->f_dentry);
  20606. + hidden_dir = hidden_parent->d_inode;
  20607. + hi_lock_parent(hidden_dir);
  20608. + err = vfsub_unlink(hidden_dir, file->f_dentry, /*dlgt*/0);
  20609. +#if 0
  20610. + if (unlikely(!err && udba && parent))
  20611. + au_direval_dec(parent);
  20612. +#endif
  20613. + i_unlock(hidden_dir);
  20614. + dput(hidden_parent);
  20615. + if (unlikely(err)) {
  20616. + if (!silent)
  20617. + Err("unlink %s(%d)\n", fname, err);
  20618. + goto out;
  20619. + }
  20620. + if (sb != file->f_dentry->d_sb)
  20621. + return file; /* success */
  20622. +
  20623. + if (!silent)
  20624. + Err("%s must be outside\n", fname);
  20625. + err = -EINVAL;
  20626. +
  20627. + out:
  20628. + fput(file);
  20629. + file = ERR_PTR(err);
  20630. + return file;
  20631. +}
  20632. +
  20633. +/*
  20634. + * find another branch who is on the same filesystem of the specified
  20635. + * branch{@btgt}. search until @bend.
  20636. + */
  20637. +static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
  20638. + aufs_bindex_t bend)
  20639. +{
  20640. + aufs_bindex_t bindex;
  20641. + struct super_block *tgt_sb = sbr_sb(sb, btgt);
  20642. +
  20643. + for (bindex = 0; bindex <= bend; bindex++)
  20644. + if (unlikely(btgt != bindex && tgt_sb == sbr_sb(sb, bindex)))
  20645. + return bindex;
  20646. + return -1;
  20647. +}
  20648. +
  20649. +/*
  20650. + * create a new xinofile at the same place/path as @base_file.
  20651. + */
  20652. +static struct file *xino_create2(struct file *base_file)
  20653. +{
  20654. + struct file *file;
  20655. + int err;
  20656. + struct dentry *base, *dentry, *parent;
  20657. + struct inode *dir;
  20658. + struct qstr *name;
  20659. + struct lkup_args lkup = {
  20660. + .nfsmnt = NULL,
  20661. + .dlgt = 0
  20662. + };
  20663. +
  20664. + base = base_file->f_dentry;
  20665. + LKTRTrace("%.*s\n", DLNPair(base));
  20666. + parent = dget_parent(base);
  20667. + dir = parent->d_inode;
  20668. + IMustLock(dir);
  20669. +
  20670. + file = ERR_PTR(-EINVAL);
  20671. + if (unlikely(au_is_nfs(parent->d_sb)))
  20672. + goto out;
  20673. +
  20674. + // do not superio, nor NFS.
  20675. + name = &base->d_name;
  20676. + dentry = lkup_one(name->name, parent, name->len, &lkup);
  20677. + //if (LktrCond) {dput(dentry); dentry = ERR_PTR(-1);}
  20678. + if (IS_ERR(dentry)) {
  20679. + file = (void*)dentry;
  20680. + Err("%.*s lookup err %ld\n", LNPair(name), PTR_ERR(dentry));
  20681. + goto out;
  20682. + }
  20683. + err = vfsub_create(dir, dentry, S_IRUGO | S_IWUGO, NULL, /*dlgt*/0);
  20684. + //if (LktrCond) {vfs_unlink(dir, dentry); err = -1;}
  20685. + if (unlikely(err)) {
  20686. + file = ERR_PTR(err);
  20687. + Err("%.*s create err %d\n", LNPair(name), err);
  20688. + goto out_dput;
  20689. + }
  20690. + file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
  20691. + O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE);
  20692. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20693. + if (IS_ERR(file)) {
  20694. + Err("%.*s open err %ld\n", LNPair(name), PTR_ERR(file));
  20695. + goto out_dput;
  20696. + }
  20697. + err = vfsub_unlink(dir, dentry, /*dlgt*/0);
  20698. + //if (LktrCond) err = -1;
  20699. + if (!err)
  20700. + goto out_dput; /* success */
  20701. +
  20702. + Err("%.*s unlink err %d\n", LNPair(name), err);
  20703. + fput(file);
  20704. + file = ERR_PTR(err);
  20705. +
  20706. + out_dput:
  20707. + dput(dentry);
  20708. + out:
  20709. + dput(parent);
  20710. + TraceErrPtr(file);
  20711. + return file;
  20712. +}
  20713. +
  20714. +/*
  20715. + * initialize the xinofile for the specified branch{@sb, @bindex}
  20716. + * at the place/path where @base_file indicates.
  20717. + * test whether another branch is on the same filesystem or not,
  20718. + * if @do_test is true.
  20719. + */
  20720. +int xino_init(struct super_block *sb, aufs_bindex_t bindex,
  20721. + struct file *base_file, int do_test)
  20722. +{
  20723. + int err;
  20724. + struct aufs_branch *br;
  20725. + aufs_bindex_t bshared, bend;
  20726. + struct file *file;
  20727. + struct inode *inode, *hidden_inode;
  20728. + struct xino xino;
  20729. +
  20730. + LKTRTrace("b%d, base_file %p, do_test %d\n",
  20731. + bindex, base_file, do_test);
  20732. + SiMustWriteLock(sb);
  20733. + DEBUG_ON(!au_flag_test(sb, AuFlag_XINO));
  20734. + br = stobr(sb, bindex);
  20735. + DEBUG_ON(br->br_xino);
  20736. +
  20737. + file = NULL;
  20738. + bshared = -1;
  20739. + bend = sbend(sb);
  20740. + if (do_test)
  20741. + bshared = is_sb_shared(sb, bindex, bend);
  20742. + if (unlikely(bshared >= 0)) {
  20743. + struct aufs_branch *shared_br = stobr(sb, bshared);
  20744. + if (shared_br->br_xino) {
  20745. + file = shared_br->br_xino;
  20746. + get_file(file);
  20747. + }
  20748. + }
  20749. +
  20750. + if (!file) {
  20751. + struct dentry *parent = dget_parent(base_file->f_dentry);
  20752. + struct inode *dir = parent->d_inode;
  20753. +
  20754. + hi_lock_parent(dir);
  20755. + file = xino_create2(base_file);
  20756. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20757. + i_unlock(dir);
  20758. + dput(parent);
  20759. + err = PTR_ERR(file);
  20760. + if (IS_ERR(file))
  20761. + goto out;
  20762. + }
  20763. + br->br_xino_read = find_readf(file);
  20764. + err = PTR_ERR(br->br_xino_read);
  20765. + if (IS_ERR(br->br_xino_read))
  20766. + goto out_put;
  20767. + br->br_xino_write = find_writef(file);
  20768. + err = PTR_ERR(br->br_xino_write);
  20769. + if (IS_ERR(br->br_xino_write))
  20770. + goto out_put;
  20771. + br->br_xino = file;
  20772. +
  20773. + inode = sb->s_root->d_inode;
  20774. + hidden_inode = au_h_iptr_i(inode, bindex);
  20775. + xino.ino = inode->i_ino;
  20776. + //xino.h_gen = hidden_inode->i_generation;
  20777. + //WARN_ON(xino.h_gen == AuXino_INVALID_HGEN);
  20778. + err = xino_write(sb, bindex, hidden_inode->i_ino, &xino);
  20779. + //if (LktrCond) err = -1;
  20780. + if (!err)
  20781. + return 0; /* success */
  20782. +
  20783. + br->br_xino = NULL;
  20784. +
  20785. + out_put:
  20786. + fput(file);
  20787. + out:
  20788. + TraceErr(err);
  20789. + return err;
  20790. +}
  20791. +
  20792. +/*
  20793. + * set xino mount option.
  20794. + */
  20795. +int xino_set(struct super_block *sb, struct opt_xino *xino, int remount)
  20796. +{
  20797. + int err, sparse;
  20798. + aufs_bindex_t bindex, bend;
  20799. + struct aufs_branch *br;
  20800. + struct dentry *parent;
  20801. + struct qstr *name;
  20802. + struct file *cur_xino;
  20803. + struct inode *dir;
  20804. +
  20805. + LKTRTrace("%s\n", xino->path);
  20806. +
  20807. + err = 0;
  20808. + name = &xino->file->f_dentry->d_name;
  20809. + parent = dget_parent(xino->file->f_dentry);
  20810. + dir = parent->d_inode;
  20811. + cur_xino = stobr(sb, 0)->br_xino;
  20812. + if (remount
  20813. + && cur_xino
  20814. + && cur_xino->f_dentry->d_parent == parent
  20815. + && name->len == cur_xino->f_dentry->d_name.len
  20816. + && !memcmp(name->name, cur_xino->f_dentry->d_name.name, name->len))
  20817. + goto out;
  20818. +
  20819. + au_flag_set(sb, AuFlag_XINO);
  20820. + bend = sbend(sb);
  20821. + for (bindex = bend; bindex >= 0; bindex--) {
  20822. + br = stobr(sb, bindex);
  20823. + if (unlikely(br->br_xino && file_count(br->br_xino) > 1)) {
  20824. + fput(br->br_xino);
  20825. + br->br_xino = NULL;
  20826. + }
  20827. + }
  20828. +
  20829. + for (bindex = 0; bindex <= bend; bindex++) {
  20830. + struct file *file;
  20831. + struct inode *inode;
  20832. +
  20833. + br = stobr(sb, bindex);
  20834. + if (unlikely(!br->br_xino))
  20835. + continue;
  20836. +
  20837. + DEBUG_ON(file_count(br->br_xino) != 1);
  20838. + hi_lock_parent(dir);
  20839. + file = xino_create2(xino->file);
  20840. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20841. + err = PTR_ERR(file);
  20842. + if (IS_ERR(file)) {
  20843. + i_unlock(dir);
  20844. + break;
  20845. + }
  20846. + inode = br->br_xino->f_dentry->d_inode;
  20847. + err = au_copy_file(file, br->br_xino, i_size_read(inode), sb,
  20848. + &sparse);
  20849. + //if (LktrCond) err = -1;
  20850. + i_unlock(dir);
  20851. + if (unlikely(err)) {
  20852. + fput(file);
  20853. + break;
  20854. + }
  20855. + fput(br->br_xino);
  20856. + br->br_xino = file;
  20857. + br->br_xino_read = find_readf(file);
  20858. + DEBUG_ON(IS_ERR(br->br_xino_read));
  20859. + br->br_xino_write = find_writef(file);
  20860. + DEBUG_ON(IS_ERR(br->br_xino_write));
  20861. + }
  20862. +
  20863. + for (bindex = 0; bindex <= bend; bindex++)
  20864. + if (unlikely(!stobr(sb, bindex)->br_xino)) {
  20865. + err = xino_init(sb, bindex, xino->file, /*do_test*/1);
  20866. + //if (LktrCond) {fput(stobr(sb, bindex)->br_xino);
  20867. + //stobr(sb, bindex)->br_xino = NULL; err = -1;}
  20868. + if (!err)
  20869. + continue;
  20870. + IOErr("creating xino for branch %d(%d), "
  20871. + "forcing noxino\n", bindex, err);
  20872. + err = -EIO;
  20873. + break;
  20874. + }
  20875. + out:
  20876. + dput(parent);
  20877. + if (!err)
  20878. + au_flag_set(sb, AuFlag_XINO);
  20879. + else
  20880. + au_flag_clr(sb, AuFlag_XINO);
  20881. + TraceErr(err);
  20882. + return err;
  20883. +}
  20884. +
  20885. +/*
  20886. + * clear xino mount option
  20887. + */
  20888. +int xino_clr(struct super_block *sb)
  20889. +{
  20890. + aufs_bindex_t bindex, bend;
  20891. +
  20892. + TraceEnter();
  20893. + SiMustWriteLock(sb);
  20894. +
  20895. + bend = sbend(sb);
  20896. + for (bindex = 0; bindex <= bend; bindex++) {
  20897. + struct aufs_branch *br;
  20898. + br = stobr(sb, bindex);
  20899. + if (br->br_xino) {
  20900. + fput(br->br_xino);
  20901. + br->br_xino = NULL;
  20902. + }
  20903. + }
  20904. +
  20905. + //todo: need to make iunique() to return the larger inode number
  20906. +
  20907. + au_flag_clr(sb, AuFlag_XINO);
  20908. + return 0;
  20909. +}
  20910. +
  20911. +/*
  20912. + * create a xinofile at the default place/path.
  20913. + */
  20914. +struct file *xino_def(struct super_block *sb)
  20915. +{
  20916. + struct file *file;
  20917. + aufs_bindex_t bend, bindex, bwr;
  20918. + char *page, *p;
  20919. +
  20920. + bend = sbend(sb);
  20921. + bwr = -1;
  20922. + for (bindex = 0; bindex <= bend; bindex++)
  20923. + if (br_writable(sbr_perm(sb, bindex))
  20924. + && !au_is_nfs(au_h_dptr_i(sb->s_root, bindex)->d_sb)) {
  20925. + bwr = bindex;
  20926. + break;
  20927. + }
  20928. +
  20929. + if (bwr != -1) {
  20930. + // todo: rewrite with lkup_one()
  20931. + file = ERR_PTR(-ENOMEM);
  20932. + page = __getname();
  20933. + //if (LktrCond) {__putname(page); page = NULL;}
  20934. + if (unlikely(!page))
  20935. + goto out;
  20936. + p = d_path(au_h_dptr_i(sb->s_root, bwr), sbr_mnt(sb, bwr), page,
  20937. + PATH_MAX - sizeof(AUFS_XINO_FNAME));
  20938. + //if (LktrCond) p = ERR_PTR(-1);
  20939. + file = (void*)p;
  20940. + if (p && !IS_ERR(p)) {
  20941. + strcat(p, "/" AUFS_XINO_FNAME);
  20942. + LKTRTrace("%s\n", p);
  20943. + file = xino_create(sb, p, /*silent*/0, sb->s_root);
  20944. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20945. + }
  20946. + __putname(page);
  20947. + } else {
  20948. + file = xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
  20949. + /*parent*/NULL);
  20950. + //if (LktrCond) {fput(file); file = ERR_PTR(-1);}
  20951. + }
  20952. +
  20953. + out:
  20954. + TraceErrPtr(file);
  20955. + return file;
  20956. +}
  20957. diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
  20958. new file mode 100644
  20959. index 0000000..1bc7b06
  20960. --- /dev/null
  20961. +++ b/fs/squashfs/Makefile
  20962. @@ -0,0 +1,7 @@
  20963. +#
  20964. +# Makefile for the linux squashfs routines.
  20965. +#
  20966. +
  20967. +obj-$(CONFIG_SQUASHFS) += squashfs.o
  20968. +squashfs-y += inode.o
  20969. +squashfs-y += squashfs2_0.o
  20970. diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
  20971. new file mode 100644
  20972. index 0000000..895b699
  20973. --- /dev/null
  20974. +++ b/fs/squashfs/inode.c
  20975. @@ -0,0 +1,2329 @@
  20976. +/*
  20977. + * Squashfs - a compressed read only filesystem for Linux
  20978. + *
  20979. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  20980. + * Phillip Lougher <phillip@lougher.org.uk>
  20981. + *
  20982. + * This program is free software; you can redistribute it and/or
  20983. + * modify it under the terms of the GNU General Public License
  20984. + * as published by the Free Software Foundation; either version 2,
  20985. + * or (at your option) any later version.
  20986. + *
  20987. + * This program is distributed in the hope that it will be useful,
  20988. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20989. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20990. + * GNU General Public License for more details.
  20991. + *
  20992. + * You should have received a copy of the GNU General Public License
  20993. + * along with this program; if not, write to the Free Software
  20994. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20995. + *
  20996. + * inode.c
  20997. + */
  20998. +
  20999. +#include <linux/squashfs_fs.h>
  21000. +#include <linux/module.h>
  21001. +#include <linux/zlib.h>
  21002. +#include <linux/fs.h>
  21003. +#include <linux/squashfs_fs_sb.h>
  21004. +#include <linux/squashfs_fs_i.h>
  21005. +#include <linux/buffer_head.h>
  21006. +#include <linux/vfs.h>
  21007. +#include <linux/vmalloc.h>
  21008. +#include <linux/smp_lock.h>
  21009. +
  21010. +#include "squashfs.h"
  21011. +
  21012. +static void vfs_read_inode(struct inode *i);
  21013. +static struct dentry *squashfs_get_parent(struct dentry *child);
  21014. +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);
  21015. +static int squashfs_statfs(struct dentry *, struct kstatfs *);
  21016. +static int squashfs_symlink_readpage(struct file *file, struct page *page);
  21017. +static long long read_blocklist(struct inode *inode, int index,
  21018. + int readahead_blks, char *block_list,
  21019. + unsigned short **block_p, unsigned int *bsize);
  21020. +static int squashfs_readpage(struct file *file, struct page *page);
  21021. +static int squashfs_readpage4K(struct file *file, struct page *page);
  21022. +static int squashfs_readdir(struct file *, void *, filldir_t);
  21023. +static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
  21024. + struct nameidata *);
  21025. +static int squashfs_remount(struct super_block *s, int *flags, char *data);
  21026. +static void squashfs_put_super(struct super_block *);
  21027. +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,
  21028. + struct vfsmount *);
  21029. +static struct inode *squashfs_alloc_inode(struct super_block *sb);
  21030. +static void squashfs_destroy_inode(struct inode *inode);
  21031. +static int init_inodecache(void);
  21032. +static void destroy_inodecache(void);
  21033. +
  21034. +static struct file_system_type squashfs_fs_type = {
  21035. + .owner = THIS_MODULE,
  21036. + .name = "squashfs",
  21037. + .get_sb = squashfs_get_sb,
  21038. + .kill_sb = kill_block_super,
  21039. + .fs_flags = FS_REQUIRES_DEV
  21040. +};
  21041. +
  21042. +static const unsigned char squashfs_filetype_table[] = {
  21043. + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
  21044. +};
  21045. +
  21046. +static struct super_operations squashfs_super_ops = {
  21047. + .alloc_inode = squashfs_alloc_inode,
  21048. + .destroy_inode = squashfs_destroy_inode,
  21049. + .statfs = squashfs_statfs,
  21050. + .put_super = squashfs_put_super,
  21051. + .remount_fs = squashfs_remount
  21052. +};
  21053. +
  21054. +static struct super_operations squashfs_export_super_ops = {
  21055. + .alloc_inode = squashfs_alloc_inode,
  21056. + .destroy_inode = squashfs_destroy_inode,
  21057. + .statfs = squashfs_statfs,
  21058. + .put_super = squashfs_put_super,
  21059. + .read_inode = vfs_read_inode
  21060. +};
  21061. +
  21062. +static struct export_operations squashfs_export_ops = {
  21063. + .get_parent = squashfs_get_parent
  21064. +};
  21065. +
  21066. +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {
  21067. + .readpage = squashfs_symlink_readpage
  21068. +};
  21069. +
  21070. +SQSH_EXTERN const struct address_space_operations squashfs_aops = {
  21071. + .readpage = squashfs_readpage
  21072. +};
  21073. +
  21074. +SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {
  21075. + .readpage = squashfs_readpage4K
  21076. +};
  21077. +
  21078. +static const struct file_operations squashfs_dir_ops = {
  21079. + .read = generic_read_dir,
  21080. + .readdir = squashfs_readdir
  21081. +};
  21082. +
  21083. +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
  21084. + .lookup = squashfs_lookup
  21085. +};
  21086. +
  21087. +
  21088. +static struct buffer_head *get_block_length(struct super_block *s,
  21089. + int *cur_index, int *offset, int *c_byte)
  21090. +{
  21091. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21092. + unsigned short temp;
  21093. + struct buffer_head *bh;
  21094. +
  21095. + if (!(bh = sb_bread(s, *cur_index)))
  21096. + goto out;
  21097. +
  21098. + if (msblk->devblksize - *offset == 1) {
  21099. + if (msblk->swap)
  21100. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  21101. + (bh->b_data + *offset));
  21102. + else
  21103. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  21104. + (bh->b_data + *offset));
  21105. + brelse(bh);
  21106. + if (!(bh = sb_bread(s, ++(*cur_index))))
  21107. + goto out;
  21108. + if (msblk->swap)
  21109. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  21110. + bh->b_data);
  21111. + else
  21112. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  21113. + bh->b_data);
  21114. + *c_byte = temp;
  21115. + *offset = 1;
  21116. + } else {
  21117. + if (msblk->swap) {
  21118. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  21119. + (bh->b_data + *offset));
  21120. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  21121. + (bh->b_data + *offset + 1));
  21122. + } else {
  21123. + ((unsigned char *) &temp)[0] = *((unsigned char *)
  21124. + (bh->b_data + *offset));
  21125. + ((unsigned char *) &temp)[1] = *((unsigned char *)
  21126. + (bh->b_data + *offset + 1));
  21127. + }
  21128. + *c_byte = temp;
  21129. + *offset += 2;
  21130. + }
  21131. +
  21132. + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
  21133. + if (*offset == msblk->devblksize) {
  21134. + brelse(bh);
  21135. + if (!(bh = sb_bread(s, ++(*cur_index))))
  21136. + goto out;
  21137. + *offset = 0;
  21138. + }
  21139. + if (*((unsigned char *) (bh->b_data + *offset)) !=
  21140. + SQUASHFS_MARKER_BYTE) {
  21141. + ERROR("Metadata block marker corrupt @ %x\n",
  21142. + *cur_index);
  21143. + brelse(bh);
  21144. + goto out;
  21145. + }
  21146. + (*offset)++;
  21147. + }
  21148. + return bh;
  21149. +
  21150. +out:
  21151. + return NULL;
  21152. +}
  21153. +
  21154. +
  21155. +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
  21156. + long long index, unsigned int length,
  21157. + long long *next_index, int srclength)
  21158. +{
  21159. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21160. + struct squashfs_super_block *sblk = &msblk->sblk;
  21161. + struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
  21162. + msblk->devblksize_log2) + 2];
  21163. + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
  21164. + unsigned int cur_index = index >> msblk->devblksize_log2;
  21165. + int bytes, avail_bytes, b = 0, k = 0;
  21166. + unsigned int compressed;
  21167. + unsigned int c_byte = length;
  21168. +
  21169. + if (c_byte) {
  21170. + bytes = msblk->devblksize - offset;
  21171. + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
  21172. + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
  21173. +
  21174. + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
  21175. + ? "" : "un", (unsigned int) c_byte, srclength);
  21176. +
  21177. + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
  21178. + goto read_failure;
  21179. +
  21180. + if (!(bh[0] = sb_getblk(s, cur_index)))
  21181. + goto block_release;
  21182. +
  21183. + for (b = 1; bytes < c_byte; b++) {
  21184. + if (!(bh[b] = sb_getblk(s, ++cur_index)))
  21185. + goto block_release;
  21186. + bytes += msblk->devblksize;
  21187. + }
  21188. + ll_rw_block(READ, b, bh);
  21189. + } else {
  21190. + if (index < 0 || (index + 2) > sblk->bytes_used)
  21191. + goto read_failure;
  21192. +
  21193. + if (!(bh[0] = get_block_length(s, &cur_index, &offset,
  21194. + &c_byte)))
  21195. + goto read_failure;
  21196. +
  21197. + bytes = msblk->devblksize - offset;
  21198. + compressed = SQUASHFS_COMPRESSED(c_byte);
  21199. + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  21200. +
  21201. + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
  21202. + ? "" : "un", (unsigned int) c_byte);
  21203. +
  21204. + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
  21205. + goto read_failure;
  21206. +
  21207. + for (b = 1; bytes < c_byte; b++) {
  21208. + if (!(bh[b] = sb_getblk(s, ++cur_index)))
  21209. + goto block_release;
  21210. + bytes += msblk->devblksize;
  21211. + }
  21212. + ll_rw_block(READ, b - 1, bh + 1);
  21213. + }
  21214. +
  21215. + if (compressed) {
  21216. + int zlib_err = 0;
  21217. +
  21218. + /*
  21219. + * uncompress block
  21220. + */
  21221. +
  21222. + mutex_lock(&msblk->read_data_mutex);
  21223. +
  21224. + msblk->stream.next_out = buffer;
  21225. + msblk->stream.avail_out = srclength;
  21226. +
  21227. + for (bytes = 0; k < b; k++) {
  21228. + avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
  21229. + msblk->devblksize - offset :
  21230. + c_byte - bytes;
  21231. + wait_on_buffer(bh[k]);
  21232. + if (!buffer_uptodate(bh[k]))
  21233. + goto release_mutex;
  21234. +
  21235. + msblk->stream.next_in = bh[k]->b_data + offset;
  21236. + msblk->stream.avail_in = avail_bytes;
  21237. +
  21238. + if (k == 0) {
  21239. + zlib_err = zlib_inflateInit(&msblk->stream);
  21240. + if (zlib_err != Z_OK) {
  21241. + ERROR("zlib_inflateInit returned unexpected result 0x%x, srclength %d\n",
  21242. + zlib_err, srclength);
  21243. + goto release_mutex;
  21244. + }
  21245. +
  21246. + if (avail_bytes == 0) {
  21247. + offset = 0;
  21248. + brelse(bh[k]);
  21249. + continue;
  21250. + }
  21251. + }
  21252. +
  21253. + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
  21254. + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) {
  21255. + ERROR("zlib_inflate returned unexpected result 0x%x, srclength %d, avail_in %d, avail_out %d\n",
  21256. + zlib_err, srclength, msblk->stream.avail_in, msblk->stream.avail_out);
  21257. + goto release_mutex;
  21258. + }
  21259. +
  21260. + bytes += avail_bytes;
  21261. + offset = 0;
  21262. + brelse(bh[k]);
  21263. + }
  21264. +
  21265. + if (zlib_err != Z_STREAM_END)
  21266. + goto release_mutex;
  21267. +
  21268. + zlib_err = zlib_inflateEnd(&msblk->stream);
  21269. + if (zlib_err != Z_OK) {
  21270. + ERROR("zlib_inflateEnd returned unexpected result 0x%x, srclength %d\n",
  21271. + zlib_err, srclength);
  21272. + goto release_mutex;
  21273. + }
  21274. + bytes = msblk->stream.total_out;
  21275. + mutex_unlock(&msblk->read_data_mutex);
  21276. + } else {
  21277. + int i;
  21278. +
  21279. + for(i = 0; i < b; i++) {
  21280. + wait_on_buffer(bh[i]);
  21281. + if(!buffer_uptodate(bh[i]))
  21282. + goto block_release;
  21283. + }
  21284. +
  21285. + for (bytes = 0; k < b; k++) {
  21286. + avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
  21287. + msblk->devblksize - offset :
  21288. + c_byte - bytes;
  21289. + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);
  21290. + bytes += avail_bytes;
  21291. + offset = 0;
  21292. + brelse(bh[k]);
  21293. + }
  21294. + }
  21295. +
  21296. + if (next_index)
  21297. + *next_index = index + c_byte + (length ? 0 :
  21298. + (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
  21299. + ? 3 : 2));
  21300. + return bytes;
  21301. +
  21302. +release_mutex:
  21303. + mutex_unlock(&msblk->read_data_mutex);
  21304. +
  21305. +block_release:
  21306. + for (; k < b; k++)
  21307. + brelse(bh[k]);
  21308. +
  21309. +read_failure:
  21310. + ERROR("sb_bread failed reading block 0x%x\n", cur_index);
  21311. + return 0;
  21312. +}
  21313. +
  21314. +
  21315. +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
  21316. + long long block, unsigned int offset,
  21317. + int length, long long *next_block,
  21318. + unsigned int *next_offset)
  21319. +{
  21320. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21321. + int n, i, bytes, return_length = length;
  21322. + long long next_index;
  21323. +
  21324. + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
  21325. +
  21326. + while ( 1 ) {
  21327. + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
  21328. + if (msblk->block_cache[i].block == block)
  21329. + break;
  21330. +
  21331. + mutex_lock(&msblk->block_cache_mutex);
  21332. +
  21333. + if (i == SQUASHFS_CACHED_BLKS) {
  21334. + /* read inode header block */
  21335. + for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
  21336. + n ; n --, i = (i + 1) %
  21337. + SQUASHFS_CACHED_BLKS)
  21338. + if (msblk->block_cache[i].block !=
  21339. + SQUASHFS_USED_BLK)
  21340. + break;
  21341. +
  21342. + if (n == 0) {
  21343. + wait_queue_t wait;
  21344. +
  21345. + init_waitqueue_entry(&wait, current);
  21346. + add_wait_queue(&msblk->waitq, &wait);
  21347. + set_current_state(TASK_UNINTERRUPTIBLE);
  21348. + mutex_unlock(&msblk->block_cache_mutex);
  21349. + schedule();
  21350. + set_current_state(TASK_RUNNING);
  21351. + remove_wait_queue(&msblk->waitq, &wait);
  21352. + continue;
  21353. + }
  21354. + msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
  21355. +
  21356. + if (msblk->block_cache[i].block ==
  21357. + SQUASHFS_INVALID_BLK) {
  21358. + if (!(msblk->block_cache[i].data =
  21359. + kmalloc(SQUASHFS_METADATA_SIZE,
  21360. + GFP_KERNEL))) {
  21361. + ERROR("Failed to allocate cache"
  21362. + "block\n");
  21363. + mutex_unlock(&msblk->block_cache_mutex);
  21364. + goto out;
  21365. + }
  21366. + }
  21367. +
  21368. + msblk->block_cache[i].block = SQUASHFS_USED_BLK;
  21369. + mutex_unlock(&msblk->block_cache_mutex);
  21370. +
  21371. + msblk->block_cache[i].length = squashfs_read_data(s,
  21372. + msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);
  21373. + if (msblk->block_cache[i].length == 0) {
  21374. + ERROR("Unable to read cache block [%llx:%x]\n",
  21375. + block, offset);
  21376. + mutex_lock(&msblk->block_cache_mutex);
  21377. + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
  21378. + kfree(msblk->block_cache[i].data);
  21379. + wake_up(&msblk->waitq);
  21380. + mutex_unlock(&msblk->block_cache_mutex);
  21381. + goto out;
  21382. + }
  21383. +
  21384. + mutex_lock(&msblk->block_cache_mutex);
  21385. + wake_up(&msblk->waitq);
  21386. + msblk->block_cache[i].block = block;
  21387. + msblk->block_cache[i].next_index = next_index;
  21388. + TRACE("Read cache block [%llx:%x]\n", block, offset);
  21389. + }
  21390. +
  21391. + if (msblk->block_cache[i].block != block) {
  21392. + mutex_unlock(&msblk->block_cache_mutex);
  21393. + continue;
  21394. + }
  21395. +
  21396. + bytes = msblk->block_cache[i].length - offset;
  21397. +
  21398. + if (bytes < 1) {
  21399. + mutex_unlock(&msblk->block_cache_mutex);
  21400. + goto out;
  21401. + } else if (bytes >= length) {
  21402. + if (buffer)
  21403. + memcpy(buffer, msblk->block_cache[i].data +
  21404. + offset, length);
  21405. + if (msblk->block_cache[i].length - offset == length) {
  21406. + *next_block = msblk->block_cache[i].next_index;
  21407. + *next_offset = 0;
  21408. + } else {
  21409. + *next_block = block;
  21410. + *next_offset = offset + length;
  21411. + }
  21412. + mutex_unlock(&msblk->block_cache_mutex);
  21413. + goto finish;
  21414. + } else {
  21415. + if (buffer) {
  21416. + memcpy(buffer, msblk->block_cache[i].data +
  21417. + offset, bytes);
  21418. + buffer += bytes;
  21419. + }
  21420. + block = msblk->block_cache[i].next_index;
  21421. + mutex_unlock(&msblk->block_cache_mutex);
  21422. + length -= bytes;
  21423. + offset = 0;
  21424. + }
  21425. + }
  21426. +
  21427. +finish:
  21428. + return return_length;
  21429. +out:
  21430. + return 0;
  21431. +}
  21432. +
  21433. +
  21434. +static int get_fragment_location(struct super_block *s, unsigned int fragment,
  21435. + long long *fragment_start_block,
  21436. + unsigned int *fragment_size)
  21437. +{
  21438. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21439. + long long start_block =
  21440. + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
  21441. + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
  21442. + struct squashfs_fragment_entry fragment_entry;
  21443. +
  21444. + if (msblk->swap) {
  21445. + struct squashfs_fragment_entry sfragment_entry;
  21446. +
  21447. + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
  21448. + start_block, offset,
  21449. + sizeof(sfragment_entry), &start_block,
  21450. + &offset))
  21451. + goto out;
  21452. + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
  21453. + } else
  21454. + if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
  21455. + start_block, offset,
  21456. + sizeof(fragment_entry), &start_block,
  21457. + &offset))
  21458. + goto out;
  21459. +
  21460. + *fragment_start_block = fragment_entry.start_block;
  21461. + *fragment_size = fragment_entry.size;
  21462. +
  21463. + return 1;
  21464. +
  21465. +out:
  21466. + return 0;
  21467. +}
  21468. +
  21469. +
  21470. +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
  21471. + squashfs_fragment_cache *fragment)
  21472. +{
  21473. + mutex_lock(&msblk->fragment_mutex);
  21474. + fragment->locked --;
  21475. + wake_up(&msblk->fragment_wait_queue);
  21476. + mutex_unlock(&msblk->fragment_mutex);
  21477. +}
  21478. +
  21479. +
  21480. +SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
  21481. + *s, long long start_block,
  21482. + int length)
  21483. +{
  21484. + int i, n;
  21485. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21486. + struct squashfs_super_block *sblk = &msblk->sblk;
  21487. +
  21488. + while ( 1 ) {
  21489. + mutex_lock(&msblk->fragment_mutex);
  21490. +
  21491. + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
  21492. + msblk->fragment[i].block != start_block; i++);
  21493. +
  21494. + if (i == SQUASHFS_CACHED_FRAGMENTS) {
  21495. + for (i = msblk->next_fragment, n =
  21496. + SQUASHFS_CACHED_FRAGMENTS; n &&
  21497. + msblk->fragment[i].locked; n--, i = (i + 1) %
  21498. + SQUASHFS_CACHED_FRAGMENTS);
  21499. +
  21500. + if (n == 0) {
  21501. + wait_queue_t wait;
  21502. +
  21503. + init_waitqueue_entry(&wait, current);
  21504. + add_wait_queue(&msblk->fragment_wait_queue,
  21505. + &wait);
  21506. + set_current_state(TASK_UNINTERRUPTIBLE);
  21507. + mutex_unlock(&msblk->fragment_mutex);
  21508. + schedule();
  21509. + set_current_state(TASK_RUNNING);
  21510. + remove_wait_queue(&msblk->fragment_wait_queue,
  21511. + &wait);
  21512. + continue;
  21513. + }
  21514. + msblk->next_fragment = (msblk->next_fragment + 1) %
  21515. + SQUASHFS_CACHED_FRAGMENTS;
  21516. +
  21517. + if (msblk->fragment[i].data == NULL)
  21518. + if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
  21519. + (SQUASHFS_FILE_MAX_SIZE))) {
  21520. + ERROR("Failed to allocate fragment "
  21521. + "cache block\n");
  21522. + mutex_unlock(&msblk->fragment_mutex);
  21523. + goto out;
  21524. + }
  21525. +
  21526. + msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
  21527. + msblk->fragment[i].locked = 1;
  21528. + mutex_unlock(&msblk->fragment_mutex);
  21529. +
  21530. + if (!(msblk->fragment[i].length = squashfs_read_data(s,
  21531. + msblk->fragment[i].data,
  21532. + start_block, length, NULL, sblk->block_size))) {
  21533. + ERROR("Unable to read fragment cache block "
  21534. + "[%llx]\n", start_block);
  21535. + msblk->fragment[i].locked = 0;
  21536. + smp_mb();
  21537. + goto out;
  21538. + }
  21539. +
  21540. + mutex_lock(&msblk->fragment_mutex);
  21541. + msblk->fragment[i].block = start_block;
  21542. + TRACE("New fragment %d, start block %lld, locked %d\n",
  21543. + i, msblk->fragment[i].block,
  21544. + msblk->fragment[i].locked);
  21545. + mutex_unlock(&msblk->fragment_mutex);
  21546. + break;
  21547. + }
  21548. +
  21549. + msblk->fragment[i].locked++;
  21550. + mutex_unlock(&msblk->fragment_mutex);
  21551. + TRACE("Got fragment %d, start block %lld, locked %d\n", i,
  21552. + msblk->fragment[i].block,
  21553. + msblk->fragment[i].locked);
  21554. + break;
  21555. + }
  21556. +
  21557. + return &msblk->fragment[i];
  21558. +
  21559. +out:
  21560. + return NULL;
  21561. +}
  21562. +
  21563. +
  21564. +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
  21565. + struct squashfs_base_inode_header *inodeb)
  21566. +{
  21567. + i->i_ino = inodeb->inode_number;
  21568. + i->i_mtime.tv_sec = inodeb->mtime;
  21569. + i->i_atime.tv_sec = inodeb->mtime;
  21570. + i->i_ctime.tv_sec = inodeb->mtime;
  21571. + i->i_uid = msblk->uid[inodeb->uid];
  21572. + i->i_mode = inodeb->mode;
  21573. + i->i_size = 0;
  21574. + if (inodeb->guid == SQUASHFS_GUIDS)
  21575. + i->i_gid = i->i_uid;
  21576. + else
  21577. + i->i_gid = msblk->guid[inodeb->guid];
  21578. +}
  21579. +
  21580. +
  21581. +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)
  21582. +{
  21583. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21584. + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];
  21585. + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
  21586. + squashfs_inode_t inode;
  21587. +
  21588. + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
  21589. +
  21590. + if (msblk->swap) {
  21591. + squashfs_inode_t sinode;
  21592. +
  21593. + if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,
  21594. + sizeof(sinode), &start, &offset))
  21595. + goto out;
  21596. + SQUASHFS_SWAP_INODE_T((&inode), &sinode);
  21597. + } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,
  21598. + sizeof(inode), &start, &offset))
  21599. + goto out;
  21600. +
  21601. + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);
  21602. +
  21603. + return inode;
  21604. +
  21605. +out:
  21606. + return SQUASHFS_INVALID_BLK;
  21607. +}
  21608. +
  21609. +
  21610. +static void vfs_read_inode(struct inode *i)
  21611. +{
  21612. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  21613. + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);
  21614. +
  21615. + TRACE("Entered vfs_read_inode\n");
  21616. +
  21617. + if(inode != SQUASHFS_INVALID_BLK)
  21618. + (msblk->read_inode)(i, inode);
  21619. +}
  21620. +
  21621. +
  21622. +static struct dentry *squashfs_get_parent(struct dentry *child)
  21623. +{
  21624. + struct inode *i = child->d_inode;
  21625. + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);
  21626. + struct dentry *rv;
  21627. +
  21628. + TRACE("Entered squashfs_get_parent\n");
  21629. +
  21630. + if(parent == NULL) {
  21631. + rv = ERR_PTR(-EACCES);
  21632. + goto out;
  21633. + }
  21634. +
  21635. + rv = d_alloc_anon(parent);
  21636. + if(rv == NULL)
  21637. + rv = ERR_PTR(-ENOMEM);
  21638. +
  21639. +out:
  21640. + return rv;
  21641. +}
  21642. +
  21643. +
  21644. +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)
  21645. +{
  21646. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21647. + struct inode *i = iget_locked(s, inode_number);
  21648. +
  21649. + TRACE("Entered squashfs_iget\n");
  21650. +
  21651. + if(i && (i->i_state & I_NEW)) {
  21652. + (msblk->read_inode)(i, inode);
  21653. + unlock_new_inode(i);
  21654. + }
  21655. +
  21656. + return i;
  21657. +}
  21658. +
  21659. +
  21660. +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)
  21661. +{
  21662. + struct super_block *s = i->i_sb;
  21663. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21664. + struct squashfs_super_block *sblk = &msblk->sblk;
  21665. + long long block = SQUASHFS_INODE_BLK(inode) +
  21666. + sblk->inode_table_start;
  21667. + unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
  21668. + long long next_block;
  21669. + unsigned int next_offset;
  21670. + union squashfs_inode_header id, sid;
  21671. + struct squashfs_base_inode_header *inodeb = &id.base,
  21672. + *sinodeb = &sid.base;
  21673. +
  21674. + TRACE("Entered squashfs_read_inode\n");
  21675. +
  21676. + if (msblk->swap) {
  21677. + if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
  21678. + offset, sizeof(*sinodeb), &next_block,
  21679. + &next_offset))
  21680. + goto failed_read;
  21681. + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
  21682. + sizeof(*sinodeb));
  21683. + } else
  21684. + if (!squashfs_get_cached_block(s, (char *) inodeb, block,
  21685. + offset, sizeof(*inodeb), &next_block,
  21686. + &next_offset))
  21687. + goto failed_read;
  21688. +
  21689. + squashfs_new_inode(msblk, i, inodeb);
  21690. +
  21691. + switch(inodeb->inode_type) {
  21692. + case SQUASHFS_FILE_TYPE: {
  21693. + unsigned int frag_size;
  21694. + long long frag_blk;
  21695. + struct squashfs_reg_inode_header *inodep = &id.reg;
  21696. + struct squashfs_reg_inode_header *sinodep = &sid.reg;
  21697. +
  21698. + if (msblk->swap) {
  21699. + if (!squashfs_get_cached_block(s, (char *)
  21700. + sinodep, block, offset,
  21701. + sizeof(*sinodep), &next_block,
  21702. + &next_offset))
  21703. + goto failed_read;
  21704. + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
  21705. + } else
  21706. + if (!squashfs_get_cached_block(s, (char *)
  21707. + inodep, block, offset,
  21708. + sizeof(*inodep), &next_block,
  21709. + &next_offset))
  21710. + goto failed_read;
  21711. +
  21712. + frag_blk = SQUASHFS_INVALID_BLK;
  21713. + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
  21714. + !get_fragment_location(s,
  21715. + inodep->fragment, &frag_blk, &frag_size))
  21716. + goto failed_read;
  21717. +
  21718. + i->i_nlink = 1;
  21719. + i->i_size = inodep->file_size;
  21720. + i->i_fop = &generic_ro_fops;
  21721. + i->i_mode |= S_IFREG;
  21722. + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
  21723. + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
  21724. + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
  21725. + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
  21726. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21727. + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
  21728. + SQUASHFS_I(i)->offset = next_offset;
  21729. + if (sblk->block_size > 4096)
  21730. + i->i_data.a_ops = &squashfs_aops;
  21731. + else
  21732. + i->i_data.a_ops = &squashfs_aops_4K;
  21733. +
  21734. + TRACE("File inode %x:%x, start_block %llx, "
  21735. + "block_list_start %llx, offset %x\n",
  21736. + SQUASHFS_INODE_BLK(inode), offset,
  21737. + inodep->start_block, next_block,
  21738. + next_offset);
  21739. + break;
  21740. + }
  21741. + case SQUASHFS_LREG_TYPE: {
  21742. + unsigned int frag_size;
  21743. + long long frag_blk;
  21744. + struct squashfs_lreg_inode_header *inodep = &id.lreg;
  21745. + struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
  21746. +
  21747. + if (msblk->swap) {
  21748. + if (!squashfs_get_cached_block(s, (char *)
  21749. + sinodep, block, offset,
  21750. + sizeof(*sinodep), &next_block,
  21751. + &next_offset))
  21752. + goto failed_read;
  21753. + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
  21754. + } else
  21755. + if (!squashfs_get_cached_block(s, (char *)
  21756. + inodep, block, offset,
  21757. + sizeof(*inodep), &next_block,
  21758. + &next_offset))
  21759. + goto failed_read;
  21760. +
  21761. + frag_blk = SQUASHFS_INVALID_BLK;
  21762. + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
  21763. + !get_fragment_location(s,
  21764. + inodep->fragment, &frag_blk, &frag_size))
  21765. + goto failed_read;
  21766. +
  21767. + i->i_nlink = inodep->nlink;
  21768. + i->i_size = inodep->file_size;
  21769. + i->i_fop = &generic_ro_fops;
  21770. + i->i_mode |= S_IFREG;
  21771. + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
  21772. + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
  21773. + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
  21774. + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
  21775. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21776. + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
  21777. + SQUASHFS_I(i)->offset = next_offset;
  21778. + if (sblk->block_size > 4096)
  21779. + i->i_data.a_ops = &squashfs_aops;
  21780. + else
  21781. + i->i_data.a_ops = &squashfs_aops_4K;
  21782. +
  21783. + TRACE("File inode %x:%x, start_block %llx, "
  21784. + "block_list_start %llx, offset %x\n",
  21785. + SQUASHFS_INODE_BLK(inode), offset,
  21786. + inodep->start_block, next_block,
  21787. + next_offset);
  21788. + break;
  21789. + }
  21790. + case SQUASHFS_DIR_TYPE: {
  21791. + struct squashfs_dir_inode_header *inodep = &id.dir;
  21792. + struct squashfs_dir_inode_header *sinodep = &sid.dir;
  21793. +
  21794. + if (msblk->swap) {
  21795. + if (!squashfs_get_cached_block(s, (char *)
  21796. + sinodep, block, offset,
  21797. + sizeof(*sinodep), &next_block,
  21798. + &next_offset))
  21799. + goto failed_read;
  21800. + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
  21801. + } else
  21802. + if (!squashfs_get_cached_block(s, (char *)
  21803. + inodep, block, offset,
  21804. + sizeof(*inodep), &next_block,
  21805. + &next_offset))
  21806. + goto failed_read;
  21807. +
  21808. + i->i_nlink = inodep->nlink;
  21809. + i->i_size = inodep->file_size;
  21810. + i->i_op = &squashfs_dir_inode_ops;
  21811. + i->i_fop = &squashfs_dir_ops;
  21812. + i->i_mode |= S_IFDIR;
  21813. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21814. + SQUASHFS_I(i)->offset = inodep->offset;
  21815. + SQUASHFS_I(i)->u.s2.directory_index_count = 0;
  21816. + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
  21817. +
  21818. + TRACE("Directory inode %x:%x, start_block %x, offset "
  21819. + "%x\n", SQUASHFS_INODE_BLK(inode),
  21820. + offset, inodep->start_block,
  21821. + inodep->offset);
  21822. + break;
  21823. + }
  21824. + case SQUASHFS_LDIR_TYPE: {
  21825. + struct squashfs_ldir_inode_header *inodep = &id.ldir;
  21826. + struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
  21827. +
  21828. + if (msblk->swap) {
  21829. + if (!squashfs_get_cached_block(s, (char *)
  21830. + sinodep, block, offset,
  21831. + sizeof(*sinodep), &next_block,
  21832. + &next_offset))
  21833. + goto failed_read;
  21834. + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
  21835. + sinodep);
  21836. + } else
  21837. + if (!squashfs_get_cached_block(s, (char *)
  21838. + inodep, block, offset,
  21839. + sizeof(*inodep), &next_block,
  21840. + &next_offset))
  21841. + goto failed_read;
  21842. +
  21843. + i->i_nlink = inodep->nlink;
  21844. + i->i_size = inodep->file_size;
  21845. + i->i_op = &squashfs_dir_inode_ops;
  21846. + i->i_fop = &squashfs_dir_ops;
  21847. + i->i_mode |= S_IFDIR;
  21848. + SQUASHFS_I(i)->start_block = inodep->start_block;
  21849. + SQUASHFS_I(i)->offset = inodep->offset;
  21850. + SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
  21851. + SQUASHFS_I(i)->u.s2.directory_index_offset =
  21852. + next_offset;
  21853. + SQUASHFS_I(i)->u.s2.directory_index_count =
  21854. + inodep->i_count;
  21855. + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
  21856. +
  21857. + TRACE("Long directory inode %x:%x, start_block %x, "
  21858. + "offset %x\n",
  21859. + SQUASHFS_INODE_BLK(inode), offset,
  21860. + inodep->start_block, inodep->offset);
  21861. + break;
  21862. + }
  21863. + case SQUASHFS_SYMLINK_TYPE: {
  21864. + struct squashfs_symlink_inode_header *inodep =
  21865. + &id.symlink;
  21866. + struct squashfs_symlink_inode_header *sinodep =
  21867. + &sid.symlink;
  21868. +
  21869. + if (msblk->swap) {
  21870. + if (!squashfs_get_cached_block(s, (char *)
  21871. + sinodep, block, offset,
  21872. + sizeof(*sinodep), &next_block,
  21873. + &next_offset))
  21874. + goto failed_read;
  21875. + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
  21876. + sinodep);
  21877. + } else
  21878. + if (!squashfs_get_cached_block(s, (char *)
  21879. + inodep, block, offset,
  21880. + sizeof(*inodep), &next_block,
  21881. + &next_offset))
  21882. + goto failed_read;
  21883. +
  21884. + i->i_nlink = inodep->nlink;
  21885. + i->i_size = inodep->symlink_size;
  21886. + i->i_op = &page_symlink_inode_operations;
  21887. + i->i_data.a_ops = &squashfs_symlink_aops;
  21888. + i->i_mode |= S_IFLNK;
  21889. + SQUASHFS_I(i)->start_block = next_block;
  21890. + SQUASHFS_I(i)->offset = next_offset;
  21891. +
  21892. + TRACE("Symbolic link inode %x:%x, start_block %llx, "
  21893. + "offset %x\n",
  21894. + SQUASHFS_INODE_BLK(inode), offset,
  21895. + next_block, next_offset);
  21896. + break;
  21897. + }
  21898. + case SQUASHFS_BLKDEV_TYPE:
  21899. + case SQUASHFS_CHRDEV_TYPE: {
  21900. + struct squashfs_dev_inode_header *inodep = &id.dev;
  21901. + struct squashfs_dev_inode_header *sinodep = &sid.dev;
  21902. +
  21903. + if (msblk->swap) {
  21904. + if (!squashfs_get_cached_block(s, (char *)
  21905. + sinodep, block, offset,
  21906. + sizeof(*sinodep), &next_block,
  21907. + &next_offset))
  21908. + goto failed_read;
  21909. + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
  21910. + } else
  21911. + if (!squashfs_get_cached_block(s, (char *)
  21912. + inodep, block, offset,
  21913. + sizeof(*inodep), &next_block,
  21914. + &next_offset))
  21915. + goto failed_read;
  21916. +
  21917. + i->i_nlink = inodep->nlink;
  21918. + i->i_mode |= (inodeb->inode_type ==
  21919. + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
  21920. + S_IFBLK;
  21921. + init_special_inode(i, i->i_mode,
  21922. + old_decode_dev(inodep->rdev));
  21923. +
  21924. + TRACE("Device inode %x:%x, rdev %x\n",
  21925. + SQUASHFS_INODE_BLK(inode), offset,
  21926. + inodep->rdev);
  21927. + break;
  21928. + }
  21929. + case SQUASHFS_FIFO_TYPE:
  21930. + case SQUASHFS_SOCKET_TYPE: {
  21931. + struct squashfs_ipc_inode_header *inodep = &id.ipc;
  21932. + struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
  21933. +
  21934. + if (msblk->swap) {
  21935. + if (!squashfs_get_cached_block(s, (char *)
  21936. + sinodep, block, offset,
  21937. + sizeof(*sinodep), &next_block,
  21938. + &next_offset))
  21939. + goto failed_read;
  21940. + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
  21941. + } else
  21942. + if (!squashfs_get_cached_block(s, (char *)
  21943. + inodep, block, offset,
  21944. + sizeof(*inodep), &next_block,
  21945. + &next_offset))
  21946. + goto failed_read;
  21947. +
  21948. + i->i_nlink = inodep->nlink;
  21949. + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
  21950. + ? S_IFIFO : S_IFSOCK;
  21951. + init_special_inode(i, i->i_mode, 0);
  21952. + break;
  21953. + }
  21954. + default:
  21955. + ERROR("Unknown inode type %d in squashfs_iget!\n",
  21956. + inodeb->inode_type);
  21957. + goto failed_read1;
  21958. + }
  21959. +
  21960. + return 1;
  21961. +
  21962. +failed_read:
  21963. + ERROR("Unable to read inode [%llx:%x]\n", block, offset);
  21964. +
  21965. +failed_read1:
  21966. + make_bad_inode(i);
  21967. + return 0;
  21968. +}
  21969. +
  21970. +
  21971. +static int read_inode_lookup_table(struct super_block *s)
  21972. +{
  21973. + struct squashfs_sb_info *msblk = s->s_fs_info;
  21974. + struct squashfs_super_block *sblk = &msblk->sblk;
  21975. + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);
  21976. +
  21977. + TRACE("In read_inode_lookup_table, length %d\n", length);
  21978. +
  21979. + /* Allocate inode lookup table */
  21980. + if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {
  21981. + ERROR("Failed to allocate inode lookup table\n");
  21982. + return 0;
  21983. + }
  21984. +
  21985. + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,
  21986. + sblk->lookup_table_start, length |
  21987. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
  21988. + ERROR("unable to read inode lookup table\n");
  21989. + return 0;
  21990. + }
  21991. +
  21992. + if (msblk->swap) {
  21993. + int i;
  21994. + long long block;
  21995. +
  21996. + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {
  21997. + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),
  21998. + &msblk->inode_lookup_table[i], 1);
  21999. + msblk->inode_lookup_table[i] = block;
  22000. + }
  22001. + }
  22002. +
  22003. + return 1;
  22004. +}
  22005. +
  22006. +
  22007. +static int read_fragment_index_table(struct super_block *s)
  22008. +{
  22009. + struct squashfs_sb_info *msblk = s->s_fs_info;
  22010. + struct squashfs_super_block *sblk = &msblk->sblk;
  22011. + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
  22012. +
  22013. + if(length == 0)
  22014. + return 1;
  22015. +
  22016. + /* Allocate fragment index table */
  22017. + if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {
  22018. + ERROR("Failed to allocate fragment index table\n");
  22019. + return 0;
  22020. + }
  22021. +
  22022. + if (!squashfs_read_data(s, (char *) msblk->fragment_index,
  22023. + sblk->fragment_table_start, length |
  22024. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
  22025. + ERROR("unable to read fragment index table\n");
  22026. + return 0;
  22027. + }
  22028. +
  22029. + if (msblk->swap) {
  22030. + int i;
  22031. + long long fragment;
  22032. +
  22033. + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {
  22034. + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
  22035. + &msblk->fragment_index[i], 1);
  22036. + msblk->fragment_index[i] = fragment;
  22037. + }
  22038. + }
  22039. +
  22040. + return 1;
  22041. +}
  22042. +
  22043. +
  22044. +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
  22045. +{
  22046. + struct squashfs_super_block *sblk = &msblk->sblk;
  22047. +
  22048. + msblk->read_inode = squashfs_read_inode;
  22049. + msblk->read_blocklist = read_blocklist;
  22050. + msblk->read_fragment_index_table = read_fragment_index_table;
  22051. +
  22052. + if (sblk->s_major == 1) {
  22053. + if (!squashfs_1_0_supported(msblk)) {
  22054. + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
  22055. + "are unsupported\n");
  22056. + SERROR("Please recompile with "
  22057. + "Squashfs 1.0 support enabled\n");
  22058. + return 0;
  22059. + }
  22060. + } else if (sblk->s_major == 2) {
  22061. + if (!squashfs_2_0_supported(msblk)) {
  22062. + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
  22063. + "are unsupported\n");
  22064. + SERROR("Please recompile with "
  22065. + "Squashfs 2.0 support enabled\n");
  22066. + return 0;
  22067. + }
  22068. + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
  22069. + SQUASHFS_MINOR) {
  22070. + SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
  22071. + "filesystem\n", sblk->s_major, sblk->s_minor);
  22072. + SERROR("Please update your kernel\n");
  22073. + return 0;
  22074. + }
  22075. +
  22076. + return 1;
  22077. +}
  22078. +
  22079. +
  22080. +static int squashfs_fill_super(struct super_block *s, void *data, int silent)
  22081. +{
  22082. + struct squashfs_sb_info *msblk;
  22083. + struct squashfs_super_block *sblk;
  22084. + int i;
  22085. + char b[BDEVNAME_SIZE];
  22086. + struct inode *root;
  22087. +
  22088. + TRACE("Entered squashfs_read_superblock\n");
  22089. +
  22090. + if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
  22091. + GFP_KERNEL))) {
  22092. + ERROR("Failed to allocate superblock\n");
  22093. + goto failure;
  22094. + }
  22095. + memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
  22096. + msblk = s->s_fs_info;
  22097. + if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
  22098. + ERROR("Failed to allocate zlib workspace\n");
  22099. + goto failure;
  22100. + }
  22101. + sblk = &msblk->sblk;
  22102. +
  22103. + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
  22104. + msblk->devblksize_log2 = ffz(~msblk->devblksize);
  22105. +
  22106. + mutex_init(&msblk->read_data_mutex);
  22107. + mutex_init(&msblk->read_page_mutex);
  22108. + mutex_init(&msblk->block_cache_mutex);
  22109. + mutex_init(&msblk->fragment_mutex);
  22110. + mutex_init(&msblk->meta_index_mutex);
  22111. +
  22112. + init_waitqueue_head(&msblk->waitq);
  22113. + init_waitqueue_head(&msblk->fragment_wait_queue);
  22114. +
  22115. + sblk->bytes_used = sizeof(struct squashfs_super_block);
  22116. + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
  22117. + sizeof(struct squashfs_super_block) |
  22118. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {
  22119. + SERROR("unable to read superblock\n");
  22120. + goto failed_mount;
  22121. + }
  22122. +
  22123. + /* Check it is a SQUASHFS superblock */
  22124. + msblk->swap = 0;
  22125. + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
  22126. + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
  22127. + struct squashfs_super_block ssblk;
  22128. +
  22129. + WARNING("Mounting a different endian SQUASHFS "
  22130. + "filesystem on %s\n", bdevname(s->s_bdev, b));
  22131. +
  22132. + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
  22133. + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
  22134. + msblk->swap = 1;
  22135. + } else {
  22136. + SERROR("Can't find a SQUASHFS superblock on %s\n",
  22137. + bdevname(s->s_bdev, b));
  22138. + goto failed_mount;
  22139. + }
  22140. + }
  22141. +
  22142. + /* Check the MAJOR & MINOR versions */
  22143. + if(!supported_squashfs_filesystem(msblk, silent))
  22144. + goto failed_mount;
  22145. +
  22146. + /* Check the filesystem does not extend beyond the end of the
  22147. + block device */
  22148. + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
  22149. + goto failed_mount;
  22150. +
  22151. + /* Check the root inode for sanity */
  22152. + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
  22153. + goto failed_mount;
  22154. +
  22155. + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
  22156. + TRACE("Inodes are %scompressed\n",
  22157. + SQUASHFS_UNCOMPRESSED_INODES
  22158. + (sblk->flags) ? "un" : "");
  22159. + TRACE("Data is %scompressed\n",
  22160. + SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
  22161. + ? "un" : "");
  22162. + TRACE("Check data is %s present in the filesystem\n",
  22163. + SQUASHFS_CHECK_DATA(sblk->flags) ?
  22164. + "" : "not");
  22165. + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
  22166. + TRACE("Block size %d\n", sblk->block_size);
  22167. + TRACE("Number of inodes %d\n", sblk->inodes);
  22168. + if (sblk->s_major > 1)
  22169. + TRACE("Number of fragments %d\n", sblk->fragments);
  22170. + TRACE("Number of uids %d\n", sblk->no_uids);
  22171. + TRACE("Number of gids %d\n", sblk->no_guids);
  22172. + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
  22173. + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
  22174. + if (sblk->s_major > 1)
  22175. + TRACE("sblk->fragment_table_start %llx\n",
  22176. + sblk->fragment_table_start);
  22177. + TRACE("sblk->uid_start %llx\n", sblk->uid_start);
  22178. +
  22179. + s->s_flags |= MS_RDONLY;
  22180. + s->s_op = &squashfs_super_ops;
  22181. +
  22182. + /* Init inode_table block pointer array */
  22183. + if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
  22184. + SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
  22185. + ERROR("Failed to allocate block cache\n");
  22186. + goto failed_mount;
  22187. + }
  22188. +
  22189. + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
  22190. + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
  22191. +
  22192. + msblk->next_cache = 0;
  22193. +
  22194. + /* Allocate read_page block */
  22195. + if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
  22196. + ERROR("Failed to allocate read_page block\n");
  22197. + goto failed_mount;
  22198. + }
  22199. +
  22200. + /* Allocate uid and gid tables */
  22201. + if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
  22202. + sizeof(unsigned int), GFP_KERNEL))) {
  22203. + ERROR("Failed to allocate uid/gid table\n");
  22204. + goto failed_mount;
  22205. + }
  22206. + msblk->guid = msblk->uid + sblk->no_uids;
  22207. +
  22208. + if (msblk->swap) {
  22209. + unsigned int suid[sblk->no_uids + sblk->no_guids];
  22210. +
  22211. + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
  22212. + ((sblk->no_uids + sblk->no_guids) *
  22213. + sizeof(unsigned int)) |
  22214. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
  22215. + ERROR("unable to read uid/gid table\n");
  22216. + goto failed_mount;
  22217. + }
  22218. +
  22219. + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
  22220. + sblk->no_guids), (sizeof(unsigned int) * 8));
  22221. + } else
  22222. + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
  22223. + ((sblk->no_uids + sblk->no_guids) *
  22224. + sizeof(unsigned int)) |
  22225. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
  22226. + ERROR("unable to read uid/gid table\n");
  22227. + goto failed_mount;
  22228. + }
  22229. +
  22230. +
  22231. + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
  22232. + goto allocate_root;
  22233. +
  22234. + if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
  22235. + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
  22236. + ERROR("Failed to allocate fragment block cache\n");
  22237. + goto failed_mount;
  22238. + }
  22239. +
  22240. + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
  22241. + msblk->fragment[i].locked = 0;
  22242. + msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
  22243. + msblk->fragment[i].data = NULL;
  22244. + }
  22245. +
  22246. + msblk->next_fragment = 0;
  22247. +
  22248. + /* Allocate and read fragment index table */
  22249. + if (msblk->read_fragment_index_table(s) == 0)
  22250. + goto failed_mount;
  22251. +
  22252. + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)
  22253. + goto allocate_root;
  22254. +
  22255. + /* Allocate and read inode lookup table */
  22256. + if (read_inode_lookup_table(s) == 0)
  22257. + goto failed_mount;
  22258. +
  22259. + s->s_op = &squashfs_export_super_ops;
  22260. + s->s_export_op = &squashfs_export_ops;
  22261. +
  22262. +allocate_root:
  22263. + root = new_inode(s);
  22264. + if ((msblk->read_inode)(root, sblk->root_inode) == 0)
  22265. + goto failed_mount;
  22266. + insert_inode_hash(root);
  22267. +
  22268. + if ((s->s_root = d_alloc_root(root)) == NULL) {
  22269. + ERROR("Root inode create failed\n");
  22270. + iput(root);
  22271. + goto failed_mount;
  22272. + }
  22273. +
  22274. + TRACE("Leaving squashfs_read_super\n");
  22275. + return 0;
  22276. +
  22277. +failed_mount:
  22278. + kfree(msblk->inode_lookup_table);
  22279. + kfree(msblk->fragment_index);
  22280. + kfree(msblk->fragment);
  22281. + kfree(msblk->uid);
  22282. + kfree(msblk->read_page);
  22283. + kfree(msblk->block_cache);
  22284. + kfree(msblk->fragment_index_2);
  22285. + vfree(msblk->stream.workspace);
  22286. + kfree(s->s_fs_info);
  22287. + s->s_fs_info = NULL;
  22288. + return -EINVAL;
  22289. +
  22290. +failure:
  22291. + return -ENOMEM;
  22292. +}
  22293. +
  22294. +
  22295. +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  22296. +{
  22297. + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
  22298. + struct squashfs_super_block *sblk = &msblk->sblk;
  22299. +
  22300. + TRACE("Entered squashfs_statfs\n");
  22301. +
  22302. + buf->f_type = SQUASHFS_MAGIC;
  22303. + buf->f_bsize = sblk->block_size;
  22304. + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
  22305. + buf->f_bfree = buf->f_bavail = 0;
  22306. + buf->f_files = sblk->inodes;
  22307. + buf->f_ffree = 0;
  22308. + buf->f_namelen = SQUASHFS_NAME_LEN;
  22309. +
  22310. + return 0;
  22311. +}
  22312. +
  22313. +
  22314. +static int squashfs_symlink_readpage(struct file *file, struct page *page)
  22315. +{
  22316. + struct inode *inode = page->mapping->host;
  22317. + int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
  22318. + long long block = SQUASHFS_I(inode)->start_block;
  22319. + int offset = SQUASHFS_I(inode)->offset;
  22320. + void *pageaddr = kmap(page);
  22321. +
  22322. + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
  22323. + "%llx, offset %x\n", page->index,
  22324. + SQUASHFS_I(inode)->start_block,
  22325. + SQUASHFS_I(inode)->offset);
  22326. +
  22327. + for (length = 0; length < index; length += bytes) {
  22328. + if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
  22329. + block, offset, PAGE_CACHE_SIZE, &block,
  22330. + &offset))) {
  22331. + ERROR("Unable to read symbolic link [%llx:%x]\n", block,
  22332. + offset);
  22333. + goto skip_read;
  22334. + }
  22335. + }
  22336. +
  22337. + if (length != index) {
  22338. + ERROR("(squashfs_symlink_readpage) length != index\n");
  22339. + bytes = 0;
  22340. + goto skip_read;
  22341. + }
  22342. +
  22343. + bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
  22344. + i_size_read(inode) - length;
  22345. +
  22346. + if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
  22347. + offset, bytes, &block, &offset)))
  22348. + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
  22349. +
  22350. +skip_read:
  22351. + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
  22352. + kunmap(page);
  22353. + flush_dcache_page(page);
  22354. + SetPageUptodate(page);
  22355. + unlock_page(page);
  22356. +
  22357. + return 0;
  22358. +}
  22359. +
  22360. +
  22361. +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
  22362. +{
  22363. + struct meta_index *meta = NULL;
  22364. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22365. + int i;
  22366. +
  22367. + mutex_lock(&msblk->meta_index_mutex);
  22368. +
  22369. + TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
  22370. +
  22371. + if(msblk->meta_index == NULL)
  22372. + goto not_allocated;
  22373. +
  22374. + for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
  22375. + if (msblk->meta_index[i].inode_number == inode->i_ino &&
  22376. + msblk->meta_index[i].offset >= offset &&
  22377. + msblk->meta_index[i].offset <= index &&
  22378. + msblk->meta_index[i].locked == 0) {
  22379. + TRACE("locate_meta_index: entry %d, offset %d\n", i,
  22380. + msblk->meta_index[i].offset);
  22381. + meta = &msblk->meta_index[i];
  22382. + offset = meta->offset;
  22383. + }
  22384. +
  22385. + if (meta)
  22386. + meta->locked = 1;
  22387. +
  22388. +not_allocated:
  22389. + mutex_unlock(&msblk->meta_index_mutex);
  22390. +
  22391. + return meta;
  22392. +}
  22393. +
  22394. +
  22395. +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
  22396. +{
  22397. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22398. + struct meta_index *meta = NULL;
  22399. + int i;
  22400. +
  22401. + mutex_lock(&msblk->meta_index_mutex);
  22402. +
  22403. + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
  22404. +
  22405. + if(msblk->meta_index == NULL) {
  22406. + if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
  22407. + SQUASHFS_META_NUMBER, GFP_KERNEL))) {
  22408. + ERROR("Failed to allocate meta_index\n");
  22409. + goto failed;
  22410. + }
  22411. + for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
  22412. + msblk->meta_index[i].inode_number = 0;
  22413. + msblk->meta_index[i].locked = 0;
  22414. + }
  22415. + msblk->next_meta_index = 0;
  22416. + }
  22417. +
  22418. + for(i = SQUASHFS_META_NUMBER; i &&
  22419. + msblk->meta_index[msblk->next_meta_index].locked; i --)
  22420. + msblk->next_meta_index = (msblk->next_meta_index + 1) %
  22421. + SQUASHFS_META_NUMBER;
  22422. +
  22423. + if(i == 0) {
  22424. + TRACE("empty_meta_index: failed!\n");
  22425. + goto failed;
  22426. + }
  22427. +
  22428. + TRACE("empty_meta_index: returned meta entry %d, %p\n",
  22429. + msblk->next_meta_index,
  22430. + &msblk->meta_index[msblk->next_meta_index]);
  22431. +
  22432. + meta = &msblk->meta_index[msblk->next_meta_index];
  22433. + msblk->next_meta_index = (msblk->next_meta_index + 1) %
  22434. + SQUASHFS_META_NUMBER;
  22435. +
  22436. + meta->inode_number = inode->i_ino;
  22437. + meta->offset = offset;
  22438. + meta->skip = skip;
  22439. + meta->entries = 0;
  22440. + meta->locked = 1;
  22441. +
  22442. +failed:
  22443. + mutex_unlock(&msblk->meta_index_mutex);
  22444. + return meta;
  22445. +}
  22446. +
  22447. +
  22448. +void release_meta_index(struct inode *inode, struct meta_index *meta)
  22449. +{
  22450. + meta->locked = 0;
  22451. + smp_mb();
  22452. +}
  22453. +
  22454. +
  22455. +static int read_block_index(struct super_block *s, int blocks, char *block_list,
  22456. + long long *start_block, int *offset)
  22457. +{
  22458. + struct squashfs_sb_info *msblk = s->s_fs_info;
  22459. + unsigned int *block_listp;
  22460. + int block = 0;
  22461. +
  22462. + if (msblk->swap) {
  22463. + char sblock_list[blocks << 2];
  22464. +
  22465. + if (!squashfs_get_cached_block(s, sblock_list, *start_block,
  22466. + *offset, blocks << 2, start_block, offset)) {
  22467. + ERROR("Unable to read block list [%llx:%x]\n",
  22468. + *start_block, *offset);
  22469. + goto failure;
  22470. + }
  22471. + SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
  22472. + ((unsigned int *)sblock_list), blocks);
  22473. + } else
  22474. + if (!squashfs_get_cached_block(s, block_list, *start_block,
  22475. + *offset, blocks << 2, start_block, offset)) {
  22476. + ERROR("Unable to read block list [%llx:%x]\n",
  22477. + *start_block, *offset);
  22478. + goto failure;
  22479. + }
  22480. +
  22481. + for (block_listp = (unsigned int *) block_list; blocks;
  22482. + block_listp++, blocks --)
  22483. + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
  22484. +
  22485. + return block;
  22486. +
  22487. +failure:
  22488. + return -1;
  22489. +}
  22490. +
  22491. +
  22492. +#define SIZE 256
  22493. +
  22494. +static inline int calculate_skip(int blocks) {
  22495. + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
  22496. + return skip >= 7 ? 7 : skip + 1;
  22497. +}
  22498. +
  22499. +
  22500. +static int get_meta_index(struct inode *inode, int index,
  22501. + long long *index_block, int *index_offset,
  22502. + long long *data_block, char *block_list)
  22503. +{
  22504. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22505. + struct squashfs_super_block *sblk = &msblk->sblk;
  22506. + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
  22507. + int offset = 0;
  22508. + struct meta_index *meta;
  22509. + struct meta_entry *meta_entry;
  22510. + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
  22511. + int cur_offset = SQUASHFS_I(inode)->offset;
  22512. + long long cur_data_block = SQUASHFS_I(inode)->start_block;
  22513. + int i;
  22514. +
  22515. + index /= SQUASHFS_META_INDEXES * skip;
  22516. +
  22517. + while ( offset < index ) {
  22518. + meta = locate_meta_index(inode, index, offset + 1);
  22519. +
  22520. + if (meta == NULL) {
  22521. + if ((meta = empty_meta_index(inode, offset + 1,
  22522. + skip)) == NULL)
  22523. + goto all_done;
  22524. + } else {
  22525. + if(meta->entries == 0)
  22526. + goto failed;
  22527. + offset = index < meta->offset + meta->entries ? index :
  22528. + meta->offset + meta->entries - 1;
  22529. + meta_entry = &meta->meta_entry[offset - meta->offset];
  22530. + cur_index_block = meta_entry->index_block + sblk->inode_table_start;
  22531. + cur_offset = meta_entry->offset;
  22532. + cur_data_block = meta_entry->data_block;
  22533. + TRACE("get_meta_index: offset %d, meta->offset %d, "
  22534. + "meta->entries %d\n", offset, meta->offset,
  22535. + meta->entries);
  22536. + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
  22537. + " data_block 0x%llx\n", cur_index_block,
  22538. + cur_offset, cur_data_block);
  22539. + }
  22540. +
  22541. + for (i = meta->offset + meta->entries; i <= index &&
  22542. + i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
  22543. + int blocks = skip * SQUASHFS_META_INDEXES;
  22544. +
  22545. + while (blocks) {
  22546. + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
  22547. + blocks;
  22548. + int res = read_block_index(inode->i_sb, block,
  22549. + block_list, &cur_index_block,
  22550. + &cur_offset);
  22551. +
  22552. + if (res == -1)
  22553. + goto failed;
  22554. +
  22555. + cur_data_block += res;
  22556. + blocks -= block;
  22557. + }
  22558. +
  22559. + meta_entry = &meta->meta_entry[i - meta->offset];
  22560. + meta_entry->index_block = cur_index_block - sblk->inode_table_start;
  22561. + meta_entry->offset = cur_offset;
  22562. + meta_entry->data_block = cur_data_block;
  22563. + meta->entries ++;
  22564. + offset ++;
  22565. + }
  22566. +
  22567. + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
  22568. + meta->offset, meta->entries);
  22569. +
  22570. + release_meta_index(inode, meta);
  22571. + }
  22572. +
  22573. +all_done:
  22574. + *index_block = cur_index_block;
  22575. + *index_offset = cur_offset;
  22576. + *data_block = cur_data_block;
  22577. +
  22578. + return offset * SQUASHFS_META_INDEXES * skip;
  22579. +
  22580. +failed:
  22581. + release_meta_index(inode, meta);
  22582. + return -1;
  22583. +}
  22584. +
  22585. +
  22586. +static long long read_blocklist(struct inode *inode, int index,
  22587. + int readahead_blks, char *block_list,
  22588. + unsigned short **block_p, unsigned int *bsize)
  22589. +{
  22590. + long long block_ptr;
  22591. + int offset;
  22592. + long long block;
  22593. + int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
  22594. + block_list);
  22595. +
  22596. + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
  22597. + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
  22598. + block);
  22599. +
  22600. + if(res == -1)
  22601. + goto failure;
  22602. +
  22603. + index -= res;
  22604. +
  22605. + while ( index ) {
  22606. + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
  22607. + int res = read_block_index(inode->i_sb, blocks, block_list,
  22608. + &block_ptr, &offset);
  22609. + if (res == -1)
  22610. + goto failure;
  22611. + block += res;
  22612. + index -= blocks;
  22613. + }
  22614. +
  22615. + if (read_block_index(inode->i_sb, 1, block_list,
  22616. + &block_ptr, &offset) == -1)
  22617. + goto failure;
  22618. + *bsize = *((unsigned int *) block_list);
  22619. +
  22620. + return block;
  22621. +
  22622. +failure:
  22623. + return 0;
  22624. +}
  22625. +
  22626. +
  22627. +static int squashfs_readpage(struct file *file, struct page *page)
  22628. +{
  22629. + struct inode *inode = page->mapping->host;
  22630. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22631. + struct squashfs_super_block *sblk = &msblk->sblk;
  22632. + unsigned char *block_list;
  22633. + long long block;
  22634. + unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
  22635. + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
  22636. + void *pageaddr;
  22637. + struct squashfs_fragment_cache *fragment = NULL;
  22638. + char *data_ptr = msblk->read_page;
  22639. +
  22640. + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
  22641. + int start_index = page->index & ~mask;
  22642. + int end_index = start_index | mask;
  22643. +
  22644. + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
  22645. + page->index,
  22646. + SQUASHFS_I(inode)->start_block);
  22647. +
  22648. + if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
  22649. + ERROR("Failed to allocate block_list\n");
  22650. + goto skip_read;
  22651. + }
  22652. +
  22653. + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
  22654. + PAGE_CACHE_SHIFT))
  22655. + goto skip_read;
  22656. +
  22657. + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
  22658. + || index < (i_size_read(inode) >>
  22659. + sblk->block_log)) {
  22660. + if ((block = (msblk->read_blocklist)(inode, index, 1,
  22661. + block_list, NULL, &bsize)) == 0)
  22662. + goto skip_read;
  22663. +
  22664. + mutex_lock(&msblk->read_page_mutex);
  22665. +
  22666. + if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
  22667. + block, bsize, NULL, sblk->block_size))) {
  22668. + ERROR("Unable to read page, block %llx, size %x\n", block,
  22669. + bsize);
  22670. + mutex_unlock(&msblk->read_page_mutex);
  22671. + goto skip_read;
  22672. + }
  22673. + } else {
  22674. + if ((fragment = get_cached_fragment(inode->i_sb,
  22675. + SQUASHFS_I(inode)->
  22676. + u.s1.fragment_start_block,
  22677. + SQUASHFS_I(inode)->u.s1.fragment_size))
  22678. + == NULL) {
  22679. + ERROR("Unable to read page, block %llx, size %x\n",
  22680. + SQUASHFS_I(inode)->
  22681. + u.s1.fragment_start_block,
  22682. + (int) SQUASHFS_I(inode)->
  22683. + u.s1.fragment_size);
  22684. + goto skip_read;
  22685. + }
  22686. + bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
  22687. + (i_size_read(inode) & (sblk->block_size
  22688. + - 1));
  22689. + byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
  22690. + data_ptr = fragment->data;
  22691. + }
  22692. +
  22693. + for (i = start_index; i <= end_index && byte_offset < bytes;
  22694. + i++, byte_offset += PAGE_CACHE_SIZE) {
  22695. + struct page *push_page;
  22696. + int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
  22697. + PAGE_CACHE_SIZE : bytes - byte_offset;
  22698. +
  22699. + TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
  22700. + bytes, i, byte_offset, avail);
  22701. +
  22702. + push_page = (i == page->index) ? page :
  22703. + grab_cache_page_nowait(page->mapping, i);
  22704. +
  22705. + if (!push_page)
  22706. + continue;
  22707. +
  22708. + if (PageUptodate(push_page))
  22709. + goto skip_page;
  22710. +
  22711. + pageaddr = kmap_atomic(push_page, KM_USER0);
  22712. + memcpy(pageaddr, data_ptr + byte_offset, avail);
  22713. + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
  22714. + kunmap_atomic(pageaddr, KM_USER0);
  22715. + flush_dcache_page(push_page);
  22716. + SetPageUptodate(push_page);
  22717. +skip_page:
  22718. + unlock_page(push_page);
  22719. + if(i != page->index)
  22720. + page_cache_release(push_page);
  22721. + }
  22722. +
  22723. + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
  22724. + || index < (i_size_read(inode) >>
  22725. + sblk->block_log))
  22726. + mutex_unlock(&msblk->read_page_mutex);
  22727. + else
  22728. + release_cached_fragment(msblk, fragment);
  22729. +
  22730. + kfree(block_list);
  22731. + return 0;
  22732. +
  22733. +skip_read:
  22734. + pageaddr = kmap_atomic(page, KM_USER0);
  22735. + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
  22736. + kunmap_atomic(pageaddr, KM_USER0);
  22737. + flush_dcache_page(page);
  22738. + SetPageUptodate(page);
  22739. + unlock_page(page);
  22740. +
  22741. + kfree(block_list);
  22742. + return 0;
  22743. +}
  22744. +
  22745. +
  22746. +static int squashfs_readpage4K(struct file *file, struct page *page)
  22747. +{
  22748. + struct inode *inode = page->mapping->host;
  22749. + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  22750. + struct squashfs_super_block *sblk = &msblk->sblk;
  22751. + unsigned char *block_list;
  22752. + long long block;
  22753. + unsigned int bsize, bytes = 0;
  22754. + void *pageaddr;
  22755. +
  22756. + TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
  22757. + page->index,
  22758. + SQUASHFS_I(inode)->start_block);
  22759. +
  22760. + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
  22761. + PAGE_CACHE_SHIFT)) {
  22762. + block_list = NULL;
  22763. + goto skip_read;
  22764. + }
  22765. +
  22766. + if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
  22767. + ERROR("Failed to allocate block_list\n");
  22768. + goto skip_read;
  22769. + }
  22770. +
  22771. + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
  22772. + || page->index < (i_size_read(inode) >>
  22773. + sblk->block_log)) {
  22774. + block = (msblk->read_blocklist)(inode, page->index, 1,
  22775. + block_list, NULL, &bsize);
  22776. + if(block == 0)
  22777. + goto skip_read;
  22778. +
  22779. + mutex_lock(&msblk->read_page_mutex);
  22780. + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
  22781. + bsize, NULL, sblk->block_size);
  22782. + if (bytes) {
  22783. + pageaddr = kmap_atomic(page, KM_USER0);
  22784. + memcpy(pageaddr, msblk->read_page, bytes);
  22785. + kunmap_atomic(pageaddr, KM_USER0);
  22786. + } else
  22787. + ERROR("Unable to read page, block %llx, size %x\n",
  22788. + block, bsize);
  22789. + mutex_unlock(&msblk->read_page_mutex);
  22790. + } else {
  22791. + struct squashfs_fragment_cache *fragment =
  22792. + get_cached_fragment(inode->i_sb,
  22793. + SQUASHFS_I(inode)->
  22794. + u.s1.fragment_start_block,
  22795. + SQUASHFS_I(inode)-> u.s1.fragment_size);
  22796. + if (fragment) {
  22797. + bytes = i_size_read(inode) & (sblk->block_size - 1);
  22798. + pageaddr = kmap_atomic(page, KM_USER0);
  22799. + memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
  22800. + u.s1.fragment_offset, bytes);
  22801. + kunmap_atomic(pageaddr, KM_USER0);
  22802. + release_cached_fragment(msblk, fragment);
  22803. + } else
  22804. + ERROR("Unable to read page, block %llx, size %x\n",
  22805. + SQUASHFS_I(inode)->
  22806. + u.s1.fragment_start_block, (int)
  22807. + SQUASHFS_I(inode)-> u.s1.fragment_size);
  22808. + }
  22809. +
  22810. +skip_read:
  22811. + pageaddr = kmap_atomic(page, KM_USER0);
  22812. + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
  22813. + kunmap_atomic(pageaddr, KM_USER0);
  22814. + flush_dcache_page(page);
  22815. + SetPageUptodate(page);
  22816. + unlock_page(page);
  22817. +
  22818. + kfree(block_list);
  22819. + return 0;
  22820. +}
  22821. +
  22822. +
  22823. +static int get_dir_index_using_offset(struct super_block *s, long long
  22824. + *next_block, unsigned int *next_offset,
  22825. + long long index_start,
  22826. + unsigned int index_offset, int i_count,
  22827. + long long f_pos)
  22828. +{
  22829. + struct squashfs_sb_info *msblk = s->s_fs_info;
  22830. + struct squashfs_super_block *sblk = &msblk->sblk;
  22831. + int i, length = 0;
  22832. + struct squashfs_dir_index index;
  22833. +
  22834. + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
  22835. + i_count, (unsigned int) f_pos);
  22836. +
  22837. + f_pos =- 3;
  22838. + if (f_pos == 0)
  22839. + goto finish;
  22840. +
  22841. + for (i = 0; i < i_count; i++) {
  22842. + if (msblk->swap) {
  22843. + struct squashfs_dir_index sindex;
  22844. + squashfs_get_cached_block(s, (char *) &sindex,
  22845. + index_start, index_offset,
  22846. + sizeof(sindex), &index_start,
  22847. + &index_offset);
  22848. + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
  22849. + } else
  22850. + squashfs_get_cached_block(s, (char *) &index,
  22851. + index_start, index_offset,
  22852. + sizeof(index), &index_start,
  22853. + &index_offset);
  22854. +
  22855. + if (index.index > f_pos)
  22856. + break;
  22857. +
  22858. + squashfs_get_cached_block(s, NULL, index_start, index_offset,
  22859. + index.size + 1, &index_start,
  22860. + &index_offset);
  22861. +
  22862. + length = index.index;
  22863. + *next_block = index.start_block + sblk->directory_table_start;
  22864. + }
  22865. +
  22866. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  22867. +
  22868. +finish:
  22869. + return length + 3;
  22870. +}
  22871. +
  22872. +
  22873. +static int get_dir_index_using_name(struct super_block *s, long long
  22874. + *next_block, unsigned int *next_offset,
  22875. + long long index_start,
  22876. + unsigned int index_offset, int i_count,
  22877. + const char *name, int size)
  22878. +{
  22879. + struct squashfs_sb_info *msblk = s->s_fs_info;
  22880. + struct squashfs_super_block *sblk = &msblk->sblk;
  22881. + int i, length = 0;
  22882. + struct squashfs_dir_index *index;
  22883. + char *str;
  22884. +
  22885. + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
  22886. +
  22887. + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
  22888. + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
  22889. + ERROR("Failed to allocate squashfs_dir_index\n");
  22890. + goto failure;
  22891. + }
  22892. +
  22893. + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);
  22894. + strncpy(str, name, size);
  22895. + str[size] = '\0';
  22896. +
  22897. + for (i = 0; i < i_count; i++) {
  22898. + if (msblk->swap) {
  22899. + struct squashfs_dir_index sindex;
  22900. + squashfs_get_cached_block(s, (char *) &sindex,
  22901. + index_start, index_offset,
  22902. + sizeof(sindex), &index_start,
  22903. + &index_offset);
  22904. + SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
  22905. + } else
  22906. + squashfs_get_cached_block(s, (char *) index,
  22907. + index_start, index_offset,
  22908. + sizeof(struct squashfs_dir_index),
  22909. + &index_start, &index_offset);
  22910. +
  22911. + squashfs_get_cached_block(s, index->name, index_start,
  22912. + index_offset, index->size + 1,
  22913. + &index_start, &index_offset);
  22914. +
  22915. + index->name[index->size + 1] = '\0';
  22916. +
  22917. + if (strcmp(index->name, str) > 0)
  22918. + break;
  22919. +
  22920. + length = index->index;
  22921. + *next_block = index->start_block + sblk->directory_table_start;
  22922. + }
  22923. +
  22924. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  22925. + kfree(str);
  22926. +failure:
  22927. + return length + 3;
  22928. +}
  22929. +
  22930. +
  22931. +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
  22932. +{
  22933. + struct inode *i = file->f_dentry->d_inode;
  22934. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  22935. + struct squashfs_super_block *sblk = &msblk->sblk;
  22936. + long long next_block = SQUASHFS_I(i)->start_block +
  22937. + sblk->directory_table_start;
  22938. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  22939. + dir_count;
  22940. + struct squashfs_dir_header dirh;
  22941. + struct squashfs_dir_entry *dire;
  22942. +
  22943. + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
  22944. +
  22945. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  22946. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  22947. + ERROR("Failed to allocate squashfs_dir_entry\n");
  22948. + goto finish;
  22949. + }
  22950. +
  22951. + while(file->f_pos < 3) {
  22952. + char *name;
  22953. + int size, i_ino;
  22954. +
  22955. + if(file->f_pos == 0) {
  22956. + name = ".";
  22957. + size = 1;
  22958. + i_ino = i->i_ino;
  22959. + } else {
  22960. + name = "..";
  22961. + size = 2;
  22962. + i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
  22963. + }
  22964. + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
  22965. + (unsigned int) dirent, name, size, (int)
  22966. + file->f_pos, i_ino,
  22967. + squashfs_filetype_table[1]);
  22968. +
  22969. + if (filldir(dirent, name, size,
  22970. + file->f_pos, i_ino,
  22971. + squashfs_filetype_table[1]) < 0) {
  22972. + TRACE("Filldir returned less than 0\n");
  22973. + goto finish;
  22974. + }
  22975. + file->f_pos += size;
  22976. + }
  22977. +
  22978. + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
  22979. + SQUASHFS_I(i)->u.s2.directory_index_start,
  22980. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  22981. + SQUASHFS_I(i)->u.s2.directory_index_count,
  22982. + file->f_pos);
  22983. +
  22984. + while (length < i_size_read(i)) {
  22985. + /* read directory header */
  22986. + if (msblk->swap) {
  22987. + struct squashfs_dir_header sdirh;
  22988. +
  22989. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  22990. + next_block, next_offset, sizeof(sdirh),
  22991. + &next_block, &next_offset))
  22992. + goto failed_read;
  22993. +
  22994. + length += sizeof(sdirh);
  22995. + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
  22996. + } else {
  22997. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  22998. + next_block, next_offset, sizeof(dirh),
  22999. + &next_block, &next_offset))
  23000. + goto failed_read;
  23001. +
  23002. + length += sizeof(dirh);
  23003. + }
  23004. +
  23005. + dir_count = dirh.count + 1;
  23006. + while (dir_count--) {
  23007. + if (msblk->swap) {
  23008. + struct squashfs_dir_entry sdire;
  23009. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23010. + &sdire, next_block, next_offset,
  23011. + sizeof(sdire), &next_block,
  23012. + &next_offset))
  23013. + goto failed_read;
  23014. +
  23015. + length += sizeof(sdire);
  23016. + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
  23017. + } else {
  23018. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23019. + dire, next_block, next_offset,
  23020. + sizeof(*dire), &next_block,
  23021. + &next_offset))
  23022. + goto failed_read;
  23023. +
  23024. + length += sizeof(*dire);
  23025. + }
  23026. +
  23027. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  23028. + next_block, next_offset,
  23029. + dire->size + 1, &next_block,
  23030. + &next_offset))
  23031. + goto failed_read;
  23032. +
  23033. + length += dire->size + 1;
  23034. +
  23035. + if (file->f_pos >= length)
  23036. + continue;
  23037. +
  23038. + dire->name[dire->size + 1] = '\0';
  23039. +
  23040. + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
  23041. + (unsigned int) dirent, dire->name,
  23042. + dire->size + 1, (int) file->f_pos,
  23043. + dirh.start_block, dire->offset,
  23044. + dirh.inode_number + dire->inode_number,
  23045. + squashfs_filetype_table[dire->type]);
  23046. +
  23047. + if (filldir(dirent, dire->name, dire->size + 1,
  23048. + file->f_pos,
  23049. + dirh.inode_number + dire->inode_number,
  23050. + squashfs_filetype_table[dire->type])
  23051. + < 0) {
  23052. + TRACE("Filldir returned less than 0\n");
  23053. + goto finish;
  23054. + }
  23055. + file->f_pos = length;
  23056. + }
  23057. + }
  23058. +
  23059. +finish:
  23060. + kfree(dire);
  23061. + return 0;
  23062. +
  23063. +failed_read:
  23064. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  23065. + next_offset);
  23066. + kfree(dire);
  23067. + return 0;
  23068. +}
  23069. +
  23070. +
  23071. +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
  23072. + struct nameidata *nd)
  23073. +{
  23074. + const unsigned char *name = dentry->d_name.name;
  23075. + int len = dentry->d_name.len;
  23076. + struct inode *inode = NULL;
  23077. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  23078. + struct squashfs_super_block *sblk = &msblk->sblk;
  23079. + long long next_block = SQUASHFS_I(i)->start_block +
  23080. + sblk->directory_table_start;
  23081. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  23082. + dir_count;
  23083. + struct squashfs_dir_header dirh;
  23084. + struct squashfs_dir_entry *dire;
  23085. +
  23086. + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
  23087. +
  23088. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  23089. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  23090. + ERROR("Failed to allocate squashfs_dir_entry\n");
  23091. + goto exit_lookup;
  23092. + }
  23093. +
  23094. + if (len > SQUASHFS_NAME_LEN)
  23095. + goto exit_lookup;
  23096. +
  23097. + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
  23098. + SQUASHFS_I(i)->u.s2.directory_index_start,
  23099. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  23100. + SQUASHFS_I(i)->u.s2.directory_index_count, name,
  23101. + len);
  23102. +
  23103. + while (length < i_size_read(i)) {
  23104. + /* read directory header */
  23105. + if (msblk->swap) {
  23106. + struct squashfs_dir_header sdirh;
  23107. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  23108. + next_block, next_offset, sizeof(sdirh),
  23109. + &next_block, &next_offset))
  23110. + goto failed_read;
  23111. +
  23112. + length += sizeof(sdirh);
  23113. + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
  23114. + } else {
  23115. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  23116. + next_block, next_offset, sizeof(dirh),
  23117. + &next_block, &next_offset))
  23118. + goto failed_read;
  23119. +
  23120. + length += sizeof(dirh);
  23121. + }
  23122. +
  23123. + dir_count = dirh.count + 1;
  23124. + while (dir_count--) {
  23125. + if (msblk->swap) {
  23126. + struct squashfs_dir_entry sdire;
  23127. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23128. + &sdire, next_block,next_offset,
  23129. + sizeof(sdire), &next_block,
  23130. + &next_offset))
  23131. + goto failed_read;
  23132. +
  23133. + length += sizeof(sdire);
  23134. + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
  23135. + } else {
  23136. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23137. + dire, next_block,next_offset,
  23138. + sizeof(*dire), &next_block,
  23139. + &next_offset))
  23140. + goto failed_read;
  23141. +
  23142. + length += sizeof(*dire);
  23143. + }
  23144. +
  23145. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  23146. + next_block, next_offset, dire->size + 1,
  23147. + &next_block, &next_offset))
  23148. + goto failed_read;
  23149. +
  23150. + length += dire->size + 1;
  23151. +
  23152. + if (name[0] < dire->name[0])
  23153. + goto exit_lookup;
  23154. +
  23155. + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
  23156. + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,
  23157. + dire->offset);
  23158. +
  23159. + TRACE("calling squashfs_iget for directory "
  23160. + "entry %s, inode %x:%x, %d\n", name,
  23161. + dirh.start_block, dire->offset,
  23162. + dirh.inode_number + dire->inode_number);
  23163. +
  23164. + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);
  23165. +
  23166. + goto exit_lookup;
  23167. + }
  23168. + }
  23169. + }
  23170. +
  23171. +exit_lookup:
  23172. + kfree(dire);
  23173. + if (inode)
  23174. + return d_splice_alias(inode, dentry);
  23175. + d_add(dentry, inode);
  23176. + return ERR_PTR(0);
  23177. +
  23178. +failed_read:
  23179. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  23180. + next_offset);
  23181. + goto exit_lookup;
  23182. +}
  23183. +
  23184. +
  23185. +static int squashfs_remount(struct super_block *s, int *flags, char *data)
  23186. +{
  23187. + *flags |= MS_RDONLY;
  23188. + return 0;
  23189. +}
  23190. +
  23191. +
  23192. +static void squashfs_put_super(struct super_block *s)
  23193. +{
  23194. + int i;
  23195. +
  23196. + if (s->s_fs_info) {
  23197. + struct squashfs_sb_info *sbi = s->s_fs_info;
  23198. + if (sbi->block_cache)
  23199. + for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
  23200. + if (sbi->block_cache[i].block !=
  23201. + SQUASHFS_INVALID_BLK)
  23202. + kfree(sbi->block_cache[i].data);
  23203. + if (sbi->fragment)
  23204. + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
  23205. + SQUASHFS_FREE(sbi->fragment[i].data);
  23206. + kfree(sbi->fragment);
  23207. + kfree(sbi->block_cache);
  23208. + kfree(sbi->read_page);
  23209. + kfree(sbi->uid);
  23210. + kfree(sbi->fragment_index);
  23211. + kfree(sbi->fragment_index_2);
  23212. + kfree(sbi->meta_index);
  23213. + vfree(sbi->stream.workspace);
  23214. + kfree(s->s_fs_info);
  23215. + s->s_fs_info = NULL;
  23216. + }
  23217. +}
  23218. +
  23219. +
  23220. +static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
  23221. + const char *dev_name, void *data,
  23222. + struct vfsmount *mnt)
  23223. +{
  23224. + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
  23225. + mnt);
  23226. +}
  23227. +
  23228. +
  23229. +static int __init init_squashfs_fs(void)
  23230. +{
  23231. + int err = init_inodecache();
  23232. + if (err)
  23233. + goto out;
  23234. +
  23235. + printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "
  23236. + "Phillip Lougher\n");
  23237. +
  23238. + if ((err = register_filesystem(&squashfs_fs_type)))
  23239. + destroy_inodecache();
  23240. +
  23241. +out:
  23242. + return err;
  23243. +}
  23244. +
  23245. +
  23246. +static void __exit exit_squashfs_fs(void)
  23247. +{
  23248. + unregister_filesystem(&squashfs_fs_type);
  23249. + destroy_inodecache();
  23250. +}
  23251. +
  23252. +
  23253. +static struct kmem_cache * squashfs_inode_cachep;
  23254. +
  23255. +
  23256. +static struct inode *squashfs_alloc_inode(struct super_block *sb)
  23257. +{
  23258. + struct squashfs_inode_info *ei;
  23259. + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
  23260. + if (!ei)
  23261. + return NULL;
  23262. + return &ei->vfs_inode;
  23263. +}
  23264. +
  23265. +
  23266. +static void squashfs_destroy_inode(struct inode *inode)
  23267. +{
  23268. + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
  23269. +}
  23270. +
  23271. +
  23272. +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
  23273. +{
  23274. + struct squashfs_inode_info *ei = foo;
  23275. +
  23276. + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
  23277. + SLAB_CTOR_CONSTRUCTOR)
  23278. + inode_init_once(&ei->vfs_inode);
  23279. +}
  23280. +
  23281. +
  23282. +static int __init init_inodecache(void)
  23283. +{
  23284. + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
  23285. + sizeof(struct squashfs_inode_info),
  23286. + 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
  23287. + init_once, NULL);
  23288. + if (squashfs_inode_cachep == NULL)
  23289. + return -ENOMEM;
  23290. + return 0;
  23291. +}
  23292. +
  23293. +
  23294. +static void destroy_inodecache(void)
  23295. +{
  23296. + kmem_cache_destroy(squashfs_inode_cachep);
  23297. +}
  23298. +
  23299. +
  23300. +module_init(init_squashfs_fs);
  23301. +module_exit(exit_squashfs_fs);
  23302. +MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem");
  23303. +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
  23304. +MODULE_LICENSE("GPL");
  23305. diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
  23306. new file mode 100644
  23307. index 0000000..6f863f0
  23308. --- /dev/null
  23309. +++ b/fs/squashfs/squashfs.h
  23310. @@ -0,0 +1,87 @@
  23311. +/*
  23312. + * Squashfs - a compressed read only filesystem for Linux
  23313. + *
  23314. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  23315. + * Phillip Lougher <phillip@lougher.org.uk>
  23316. + *
  23317. + * This program is free software; you can redistribute it and/or
  23318. + * modify it under the terms of the GNU General Public License
  23319. + * as published by the Free Software Foundation; either version 2,
  23320. + * or (at your option) any later version.
  23321. + *
  23322. + * This program is distributed in the hope that it will be useful,
  23323. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23324. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23325. + * GNU General Public License for more details.
  23326. + *
  23327. + * You should have received a copy of the GNU General Public License
  23328. + * along with this program; if not, write to the Free Software
  23329. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23330. + *
  23331. + * squashfs.h
  23332. + */
  23333. +
  23334. +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  23335. +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  23336. +#endif
  23337. +
  23338. +#ifdef SQUASHFS_TRACE
  23339. +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
  23340. +#else
  23341. +#define TRACE(s, args...) {}
  23342. +#endif
  23343. +
  23344. +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
  23345. +
  23346. +#define SERROR(s, args...) do { \
  23347. + if (!silent) \
  23348. + printk(KERN_ERR "SQUASHFS error: "s, ## args);\
  23349. + } while(0)
  23350. +
  23351. +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
  23352. +
  23353. +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
  23354. +{
  23355. + return list_entry(inode, struct squashfs_inode_info, vfs_inode);
  23356. +}
  23357. +
  23358. +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
  23359. +#define SQSH_EXTERN
  23360. +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
  23361. + long long index, unsigned int length,
  23362. + long long *next_index, int srclength);
  23363. +extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
  23364. + long long block, unsigned int offset,
  23365. + int length, long long *next_block,
  23366. + unsigned int *next_offset);
  23367. +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
  23368. + squashfs_fragment_cache *fragment);
  23369. +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
  23370. + *s, long long start_block,
  23371. + int length);
  23372. +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);
  23373. +extern const struct address_space_operations squashfs_symlink_aops;
  23374. +extern const struct address_space_operations squashfs_aops;
  23375. +extern const struct address_space_operations squashfs_aops_4K;
  23376. +extern struct inode_operations squashfs_dir_inode_ops;
  23377. +#else
  23378. +#define SQSH_EXTERN static
  23379. +#endif
  23380. +
  23381. +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  23382. +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
  23383. +#else
  23384. +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
  23385. +{
  23386. + return 0;
  23387. +}
  23388. +#endif
  23389. +
  23390. +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
  23391. +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
  23392. +#else
  23393. +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
  23394. +{
  23395. + return 0;
  23396. +}
  23397. +#endif
  23398. diff --git a/fs/squashfs/squashfs2_0.c b/fs/squashfs/squashfs2_0.c
  23399. new file mode 100644
  23400. index 0000000..d8d9d55
  23401. --- /dev/null
  23402. +++ b/fs/squashfs/squashfs2_0.c
  23403. @@ -0,0 +1,742 @@
  23404. +/*
  23405. + * Squashfs - a compressed read only filesystem for Linux
  23406. + *
  23407. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  23408. + * Phillip Lougher <phillip@lougher.org.uk>
  23409. + *
  23410. + * This program is free software; you can redistribute it and/or
  23411. + * modify it under the terms of the GNU General Public License
  23412. + * as published by the Free Software Foundation; either version 2,
  23413. + * or (at your option) any later version.
  23414. + *
  23415. + * This program is distributed in the hope that it will be useful,
  23416. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23417. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23418. + * GNU General Public License for more details.
  23419. + *
  23420. + * You should have received a copy of the GNU General Public License
  23421. + * along with this program; if not, write to the Free Software
  23422. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23423. + *
  23424. + * squashfs2_0.c
  23425. + */
  23426. +
  23427. +#include <linux/squashfs_fs.h>
  23428. +#include <linux/module.h>
  23429. +#include <linux/zlib.h>
  23430. +#include <linux/fs.h>
  23431. +#include <linux/squashfs_fs_sb.h>
  23432. +#include <linux/squashfs_fs_i.h>
  23433. +
  23434. +#include "squashfs.h"
  23435. +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
  23436. +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
  23437. + struct nameidata *);
  23438. +
  23439. +static struct file_operations squashfs_dir_ops_2 = {
  23440. + .read = generic_read_dir,
  23441. + .readdir = squashfs_readdir_2
  23442. +};
  23443. +
  23444. +static struct inode_operations squashfs_dir_inode_ops_2 = {
  23445. + .lookup = squashfs_lookup_2
  23446. +};
  23447. +
  23448. +static unsigned char squashfs_filetype_table[] = {
  23449. + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
  23450. +};
  23451. +
  23452. +static int read_fragment_index_table_2(struct super_block *s)
  23453. +{
  23454. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23455. + struct squashfs_super_block *sblk = &msblk->sblk;
  23456. +
  23457. + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
  23458. + (sblk->fragments), GFP_KERNEL))) {
  23459. + ERROR("Failed to allocate uid/gid table\n");
  23460. + return 0;
  23461. + }
  23462. +
  23463. + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
  23464. + !squashfs_read_data(s, (char *)
  23465. + msblk->fragment_index_2,
  23466. + sblk->fragment_table_start,
  23467. + SQUASHFS_FRAGMENT_INDEX_BYTES_2
  23468. + (sblk->fragments) |
  23469. + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
  23470. + ERROR("unable to read fragment index table\n");
  23471. + return 0;
  23472. + }
  23473. +
  23474. + if (msblk->swap) {
  23475. + int i;
  23476. + unsigned int fragment;
  23477. +
  23478. + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
  23479. + i++) {
  23480. + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
  23481. + &msblk->fragment_index_2[i], 1);
  23482. + msblk->fragment_index_2[i] = fragment;
  23483. + }
  23484. + }
  23485. +
  23486. + return 1;
  23487. +}
  23488. +
  23489. +
  23490. +static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
  23491. + long long *fragment_start_block,
  23492. + unsigned int *fragment_size)
  23493. +{
  23494. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23495. + long long start_block =
  23496. + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
  23497. + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
  23498. + struct squashfs_fragment_entry_2 fragment_entry;
  23499. +
  23500. + if (msblk->swap) {
  23501. + struct squashfs_fragment_entry_2 sfragment_entry;
  23502. +
  23503. + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
  23504. + start_block, offset,
  23505. + sizeof(sfragment_entry), &start_block,
  23506. + &offset))
  23507. + goto out;
  23508. + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
  23509. + } else
  23510. + if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
  23511. + start_block, offset,
  23512. + sizeof(fragment_entry), &start_block,
  23513. + &offset))
  23514. + goto out;
  23515. +
  23516. + *fragment_start_block = fragment_entry.start_block;
  23517. + *fragment_size = fragment_entry.size;
  23518. +
  23519. + return 1;
  23520. +
  23521. +out:
  23522. + return 0;
  23523. +}
  23524. +
  23525. +
  23526. +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
  23527. + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
  23528. +{
  23529. + struct squashfs_super_block *sblk = &msblk->sblk;
  23530. +
  23531. + i->i_ino = ino;
  23532. + i->i_mtime.tv_sec = sblk->mkfs_time;
  23533. + i->i_atime.tv_sec = sblk->mkfs_time;
  23534. + i->i_ctime.tv_sec = sblk->mkfs_time;
  23535. + i->i_uid = msblk->uid[inodeb->uid];
  23536. + i->i_mode = inodeb->mode;
  23537. + i->i_nlink = 1;
  23538. + i->i_size = 0;
  23539. + if (inodeb->guid == SQUASHFS_GUIDS)
  23540. + i->i_gid = i->i_uid;
  23541. + else
  23542. + i->i_gid = msblk->guid[inodeb->guid];
  23543. +}
  23544. +
  23545. +
  23546. +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
  23547. +{
  23548. + struct super_block *s = i->i_sb;
  23549. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23550. + struct squashfs_super_block *sblk = &msblk->sblk;
  23551. + unsigned int block = SQUASHFS_INODE_BLK(inode) +
  23552. + sblk->inode_table_start;
  23553. + unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
  23554. + unsigned int ino = i->i_ino;
  23555. + long long next_block;
  23556. + unsigned int next_offset;
  23557. + union squashfs_inode_header_2 id, sid;
  23558. + struct squashfs_base_inode_header_2 *inodeb = &id.base,
  23559. + *sinodeb = &sid.base;
  23560. +
  23561. + TRACE("Entered squashfs_iget\n");
  23562. +
  23563. + if (msblk->swap) {
  23564. + if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
  23565. + offset, sizeof(*sinodeb), &next_block,
  23566. + &next_offset))
  23567. + goto failed_read;
  23568. + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
  23569. + sizeof(*sinodeb));
  23570. + } else
  23571. + if (!squashfs_get_cached_block(s, (char *) inodeb, block,
  23572. + offset, sizeof(*inodeb), &next_block,
  23573. + &next_offset))
  23574. + goto failed_read;
  23575. +
  23576. + squashfs_new_inode(msblk, i, inodeb, ino);
  23577. +
  23578. + switch(inodeb->inode_type) {
  23579. + case SQUASHFS_FILE_TYPE: {
  23580. + struct squashfs_reg_inode_header_2 *inodep = &id.reg;
  23581. + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
  23582. + long long frag_blk;
  23583. + unsigned int frag_size = 0;
  23584. +
  23585. + if (msblk->swap) {
  23586. + if (!squashfs_get_cached_block(s, (char *)
  23587. + sinodep, block, offset,
  23588. + sizeof(*sinodep), &next_block,
  23589. + &next_offset))
  23590. + goto failed_read;
  23591. + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
  23592. + } else
  23593. + if (!squashfs_get_cached_block(s, (char *)
  23594. + inodep, block, offset,
  23595. + sizeof(*inodep), &next_block,
  23596. + &next_offset))
  23597. + goto failed_read;
  23598. +
  23599. + frag_blk = SQUASHFS_INVALID_BLK;
  23600. + if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
  23601. + !get_fragment_location_2(s,
  23602. + inodep->fragment, &frag_blk, &frag_size))
  23603. + goto failed_read;
  23604. +
  23605. + i->i_size = inodep->file_size;
  23606. + i->i_fop = &generic_ro_fops;
  23607. + i->i_mode |= S_IFREG;
  23608. + i->i_mtime.tv_sec = inodep->mtime;
  23609. + i->i_atime.tv_sec = inodep->mtime;
  23610. + i->i_ctime.tv_sec = inodep->mtime;
  23611. + i->i_blocks = ((i->i_size - 1) >> 9) + 1;
  23612. + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
  23613. + SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
  23614. + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
  23615. + SQUASHFS_I(i)->start_block = inodep->start_block;
  23616. + SQUASHFS_I(i)->u.s1.block_list_start = next_block;
  23617. + SQUASHFS_I(i)->offset = next_offset;
  23618. + if (sblk->block_size > 4096)
  23619. + i->i_data.a_ops = &squashfs_aops;
  23620. + else
  23621. + i->i_data.a_ops = &squashfs_aops_4K;
  23622. +
  23623. + TRACE("File inode %x:%x, start_block %x, "
  23624. + "block_list_start %llx, offset %x\n",
  23625. + SQUASHFS_INODE_BLK(inode), offset,
  23626. + inodep->start_block, next_block,
  23627. + next_offset);
  23628. + break;
  23629. + }
  23630. + case SQUASHFS_DIR_TYPE: {
  23631. + struct squashfs_dir_inode_header_2 *inodep = &id.dir;
  23632. + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
  23633. +
  23634. + if (msblk->swap) {
  23635. + if (!squashfs_get_cached_block(s, (char *)
  23636. + sinodep, block, offset,
  23637. + sizeof(*sinodep), &next_block,
  23638. + &next_offset))
  23639. + goto failed_read;
  23640. + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
  23641. + } else
  23642. + if (!squashfs_get_cached_block(s, (char *)
  23643. + inodep, block, offset,
  23644. + sizeof(*inodep), &next_block,
  23645. + &next_offset))
  23646. + goto failed_read;
  23647. +
  23648. + i->i_size = inodep->file_size;
  23649. + i->i_op = &squashfs_dir_inode_ops_2;
  23650. + i->i_fop = &squashfs_dir_ops_2;
  23651. + i->i_mode |= S_IFDIR;
  23652. + i->i_mtime.tv_sec = inodep->mtime;
  23653. + i->i_atime.tv_sec = inodep->mtime;
  23654. + i->i_ctime.tv_sec = inodep->mtime;
  23655. + SQUASHFS_I(i)->start_block = inodep->start_block;
  23656. + SQUASHFS_I(i)->offset = inodep->offset;
  23657. + SQUASHFS_I(i)->u.s2.directory_index_count = 0;
  23658. + SQUASHFS_I(i)->u.s2.parent_inode = 0;
  23659. +
  23660. + TRACE("Directory inode %x:%x, start_block %x, offset "
  23661. + "%x\n", SQUASHFS_INODE_BLK(inode),
  23662. + offset, inodep->start_block,
  23663. + inodep->offset);
  23664. + break;
  23665. + }
  23666. + case SQUASHFS_LDIR_TYPE: {
  23667. + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
  23668. + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
  23669. +
  23670. + if (msblk->swap) {
  23671. + if (!squashfs_get_cached_block(s, (char *)
  23672. + sinodep, block, offset,
  23673. + sizeof(*sinodep), &next_block,
  23674. + &next_offset))
  23675. + goto failed_read;
  23676. + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
  23677. + sinodep);
  23678. + } else
  23679. + if (!squashfs_get_cached_block(s, (char *)
  23680. + inodep, block, offset,
  23681. + sizeof(*inodep), &next_block,
  23682. + &next_offset))
  23683. + goto failed_read;
  23684. +
  23685. + i->i_size = inodep->file_size;
  23686. + i->i_op = &squashfs_dir_inode_ops_2;
  23687. + i->i_fop = &squashfs_dir_ops_2;
  23688. + i->i_mode |= S_IFDIR;
  23689. + i->i_mtime.tv_sec = inodep->mtime;
  23690. + i->i_atime.tv_sec = inodep->mtime;
  23691. + i->i_ctime.tv_sec = inodep->mtime;
  23692. + SQUASHFS_I(i)->start_block = inodep->start_block;
  23693. + SQUASHFS_I(i)->offset = inodep->offset;
  23694. + SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
  23695. + SQUASHFS_I(i)->u.s2.directory_index_offset =
  23696. + next_offset;
  23697. + SQUASHFS_I(i)->u.s2.directory_index_count =
  23698. + inodep->i_count;
  23699. + SQUASHFS_I(i)->u.s2.parent_inode = 0;
  23700. +
  23701. + TRACE("Long directory inode %x:%x, start_block %x, "
  23702. + "offset %x\n",
  23703. + SQUASHFS_INODE_BLK(inode), offset,
  23704. + inodep->start_block, inodep->offset);
  23705. + break;
  23706. + }
  23707. + case SQUASHFS_SYMLINK_TYPE: {
  23708. + struct squashfs_symlink_inode_header_2 *inodep =
  23709. + &id.symlink;
  23710. + struct squashfs_symlink_inode_header_2 *sinodep =
  23711. + &sid.symlink;
  23712. +
  23713. + if (msblk->swap) {
  23714. + if (!squashfs_get_cached_block(s, (char *)
  23715. + sinodep, block, offset,
  23716. + sizeof(*sinodep), &next_block,
  23717. + &next_offset))
  23718. + goto failed_read;
  23719. + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
  23720. + sinodep);
  23721. + } else
  23722. + if (!squashfs_get_cached_block(s, (char *)
  23723. + inodep, block, offset,
  23724. + sizeof(*inodep), &next_block,
  23725. + &next_offset))
  23726. + goto failed_read;
  23727. +
  23728. + i->i_size = inodep->symlink_size;
  23729. + i->i_op = &page_symlink_inode_operations;
  23730. + i->i_data.a_ops = &squashfs_symlink_aops;
  23731. + i->i_mode |= S_IFLNK;
  23732. + SQUASHFS_I(i)->start_block = next_block;
  23733. + SQUASHFS_I(i)->offset = next_offset;
  23734. +
  23735. + TRACE("Symbolic link inode %x:%x, start_block %llx, "
  23736. + "offset %x\n",
  23737. + SQUASHFS_INODE_BLK(inode), offset,
  23738. + next_block, next_offset);
  23739. + break;
  23740. + }
  23741. + case SQUASHFS_BLKDEV_TYPE:
  23742. + case SQUASHFS_CHRDEV_TYPE: {
  23743. + struct squashfs_dev_inode_header_2 *inodep = &id.dev;
  23744. + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
  23745. +
  23746. + if (msblk->swap) {
  23747. + if (!squashfs_get_cached_block(s, (char *)
  23748. + sinodep, block, offset,
  23749. + sizeof(*sinodep), &next_block,
  23750. + &next_offset))
  23751. + goto failed_read;
  23752. + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
  23753. + } else
  23754. + if (!squashfs_get_cached_block(s, (char *)
  23755. + inodep, block, offset,
  23756. + sizeof(*inodep), &next_block,
  23757. + &next_offset))
  23758. + goto failed_read;
  23759. +
  23760. + i->i_mode |= (inodeb->inode_type ==
  23761. + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
  23762. + S_IFBLK;
  23763. + init_special_inode(i, i->i_mode,
  23764. + old_decode_dev(inodep->rdev));
  23765. +
  23766. + TRACE("Device inode %x:%x, rdev %x\n",
  23767. + SQUASHFS_INODE_BLK(inode), offset,
  23768. + inodep->rdev);
  23769. + break;
  23770. + }
  23771. + case SQUASHFS_FIFO_TYPE:
  23772. + case SQUASHFS_SOCKET_TYPE: {
  23773. +
  23774. + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
  23775. + ? S_IFIFO : S_IFSOCK;
  23776. + init_special_inode(i, i->i_mode, 0);
  23777. + break;
  23778. + }
  23779. + default:
  23780. + ERROR("Unknown inode type %d in squashfs_iget!\n",
  23781. + inodeb->inode_type);
  23782. + goto failed_read1;
  23783. + }
  23784. +
  23785. + return 1;
  23786. +
  23787. +failed_read:
  23788. + ERROR("Unable to read inode [%x:%x]\n", block, offset);
  23789. +
  23790. +failed_read1:
  23791. + return 0;
  23792. +}
  23793. +
  23794. +
  23795. +static int get_dir_index_using_offset(struct super_block *s, long long
  23796. + *next_block, unsigned int *next_offset,
  23797. + long long index_start,
  23798. + unsigned int index_offset, int i_count,
  23799. + long long f_pos)
  23800. +{
  23801. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23802. + struct squashfs_super_block *sblk = &msblk->sblk;
  23803. + int i, length = 0;
  23804. + struct squashfs_dir_index_2 index;
  23805. +
  23806. + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
  23807. + i_count, (unsigned int) f_pos);
  23808. +
  23809. + if (f_pos == 0)
  23810. + goto finish;
  23811. +
  23812. + for (i = 0; i < i_count; i++) {
  23813. + if (msblk->swap) {
  23814. + struct squashfs_dir_index_2 sindex;
  23815. + squashfs_get_cached_block(s, (char *) &sindex,
  23816. + index_start, index_offset,
  23817. + sizeof(sindex), &index_start,
  23818. + &index_offset);
  23819. + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
  23820. + } else
  23821. + squashfs_get_cached_block(s, (char *) &index,
  23822. + index_start, index_offset,
  23823. + sizeof(index), &index_start,
  23824. + &index_offset);
  23825. +
  23826. + if (index.index > f_pos)
  23827. + break;
  23828. +
  23829. + squashfs_get_cached_block(s, NULL, index_start, index_offset,
  23830. + index.size + 1, &index_start,
  23831. + &index_offset);
  23832. +
  23833. + length = index.index;
  23834. + *next_block = index.start_block + sblk->directory_table_start;
  23835. + }
  23836. +
  23837. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  23838. +
  23839. +finish:
  23840. + return length;
  23841. +}
  23842. +
  23843. +
  23844. +static int get_dir_index_using_name(struct super_block *s, long long
  23845. + *next_block, unsigned int *next_offset,
  23846. + long long index_start,
  23847. + unsigned int index_offset, int i_count,
  23848. + const char *name, int size)
  23849. +{
  23850. + struct squashfs_sb_info *msblk = s->s_fs_info;
  23851. + struct squashfs_super_block *sblk = &msblk->sblk;
  23852. + int i, length = 0;
  23853. + struct squashfs_dir_index_2 *index;
  23854. + char *str;
  23855. +
  23856. + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
  23857. +
  23858. + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
  23859. + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
  23860. + ERROR("Failed to allocate squashfs_dir_index\n");
  23861. + goto failure;
  23862. + }
  23863. +
  23864. + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
  23865. + strncpy(str, name, size);
  23866. + str[size] = '\0';
  23867. +
  23868. + for (i = 0; i < i_count; i++) {
  23869. + if (msblk->swap) {
  23870. + struct squashfs_dir_index_2 sindex;
  23871. + squashfs_get_cached_block(s, (char *) &sindex,
  23872. + index_start, index_offset,
  23873. + sizeof(sindex), &index_start,
  23874. + &index_offset);
  23875. + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
  23876. + } else
  23877. + squashfs_get_cached_block(s, (char *) index,
  23878. + index_start, index_offset,
  23879. + sizeof(struct squashfs_dir_index_2),
  23880. + &index_start, &index_offset);
  23881. +
  23882. + squashfs_get_cached_block(s, index->name, index_start,
  23883. + index_offset, index->size + 1,
  23884. + &index_start, &index_offset);
  23885. +
  23886. + index->name[index->size + 1] = '\0';
  23887. +
  23888. + if (strcmp(index->name, str) > 0)
  23889. + break;
  23890. +
  23891. + length = index->index;
  23892. + *next_block = index->start_block + sblk->directory_table_start;
  23893. + }
  23894. +
  23895. + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  23896. + kfree(str);
  23897. +failure:
  23898. + return length;
  23899. +}
  23900. +
  23901. +
  23902. +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
  23903. +{
  23904. + struct inode *i = file->f_dentry->d_inode;
  23905. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  23906. + struct squashfs_super_block *sblk = &msblk->sblk;
  23907. + long long next_block = SQUASHFS_I(i)->start_block +
  23908. + sblk->directory_table_start;
  23909. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  23910. + dir_count;
  23911. + struct squashfs_dir_header_2 dirh;
  23912. + struct squashfs_dir_entry_2 *dire;
  23913. +
  23914. + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
  23915. +
  23916. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  23917. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  23918. + ERROR("Failed to allocate squashfs_dir_entry\n");
  23919. + goto finish;
  23920. + }
  23921. +
  23922. + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
  23923. + SQUASHFS_I(i)->u.s2.directory_index_start,
  23924. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  23925. + SQUASHFS_I(i)->u.s2.directory_index_count,
  23926. + file->f_pos);
  23927. +
  23928. + while (length < i_size_read(i)) {
  23929. + /* read directory header */
  23930. + if (msblk->swap) {
  23931. + struct squashfs_dir_header_2 sdirh;
  23932. +
  23933. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  23934. + next_block, next_offset, sizeof(sdirh),
  23935. + &next_block, &next_offset))
  23936. + goto failed_read;
  23937. +
  23938. + length += sizeof(sdirh);
  23939. + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
  23940. + } else {
  23941. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  23942. + next_block, next_offset, sizeof(dirh),
  23943. + &next_block, &next_offset))
  23944. + goto failed_read;
  23945. +
  23946. + length += sizeof(dirh);
  23947. + }
  23948. +
  23949. + dir_count = dirh.count + 1;
  23950. + while (dir_count--) {
  23951. + if (msblk->swap) {
  23952. + struct squashfs_dir_entry_2 sdire;
  23953. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23954. + &sdire, next_block, next_offset,
  23955. + sizeof(sdire), &next_block,
  23956. + &next_offset))
  23957. + goto failed_read;
  23958. +
  23959. + length += sizeof(sdire);
  23960. + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
  23961. + } else {
  23962. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  23963. + dire, next_block, next_offset,
  23964. + sizeof(*dire), &next_block,
  23965. + &next_offset))
  23966. + goto failed_read;
  23967. +
  23968. + length += sizeof(*dire);
  23969. + }
  23970. +
  23971. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  23972. + next_block, next_offset,
  23973. + dire->size + 1, &next_block,
  23974. + &next_offset))
  23975. + goto failed_read;
  23976. +
  23977. + length += dire->size + 1;
  23978. +
  23979. + if (file->f_pos >= length)
  23980. + continue;
  23981. +
  23982. + dire->name[dire->size + 1] = '\0';
  23983. +
  23984. + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
  23985. + (unsigned int) dirent, dire->name,
  23986. + dire->size + 1, (int) file->f_pos,
  23987. + dirh.start_block, dire->offset,
  23988. + squashfs_filetype_table[dire->type]);
  23989. +
  23990. + if (filldir(dirent, dire->name, dire->size + 1,
  23991. + file->f_pos, SQUASHFS_MK_VFS_INODE(
  23992. + dirh.start_block, dire->offset),
  23993. + squashfs_filetype_table[dire->type])
  23994. + < 0) {
  23995. + TRACE("Filldir returned less than 0\n");
  23996. + goto finish;
  23997. + }
  23998. + file->f_pos = length;
  23999. + }
  24000. + }
  24001. +
  24002. +finish:
  24003. + kfree(dire);
  24004. + return 0;
  24005. +
  24006. +failed_read:
  24007. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  24008. + next_offset);
  24009. + kfree(dire);
  24010. + return 0;
  24011. +}
  24012. +
  24013. +
  24014. +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
  24015. + struct nameidata *nd)
  24016. +{
  24017. + const unsigned char *name = dentry->d_name.name;
  24018. + int len = dentry->d_name.len;
  24019. + struct inode *inode = NULL;
  24020. + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
  24021. + struct squashfs_super_block *sblk = &msblk->sblk;
  24022. + long long next_block = SQUASHFS_I(i)->start_block +
  24023. + sblk->directory_table_start;
  24024. + int next_offset = SQUASHFS_I(i)->offset, length = 0,
  24025. + dir_count;
  24026. + struct squashfs_dir_header_2 dirh;
  24027. + struct squashfs_dir_entry_2 *dire;
  24028. + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
  24029. +
  24030. + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
  24031. +
  24032. + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
  24033. + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
  24034. + ERROR("Failed to allocate squashfs_dir_entry\n");
  24035. + goto exit_loop;
  24036. + }
  24037. +
  24038. + if (len > SQUASHFS_NAME_LEN)
  24039. + goto exit_loop;
  24040. +
  24041. + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
  24042. + SQUASHFS_I(i)->u.s2.directory_index_start,
  24043. + SQUASHFS_I(i)->u.s2.directory_index_offset,
  24044. + SQUASHFS_I(i)->u.s2.directory_index_count, name,
  24045. + len);
  24046. +
  24047. + while (length < i_size_read(i)) {
  24048. + /* read directory header */
  24049. + if (msblk->swap) {
  24050. + struct squashfs_dir_header_2 sdirh;
  24051. + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
  24052. + next_block, next_offset, sizeof(sdirh),
  24053. + &next_block, &next_offset))
  24054. + goto failed_read;
  24055. +
  24056. + length += sizeof(sdirh);
  24057. + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
  24058. + } else {
  24059. + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
  24060. + next_block, next_offset, sizeof(dirh),
  24061. + &next_block, &next_offset))
  24062. + goto failed_read;
  24063. +
  24064. + length += sizeof(dirh);
  24065. + }
  24066. +
  24067. + dir_count = dirh.count + 1;
  24068. + while (dir_count--) {
  24069. + if (msblk->swap) {
  24070. + struct squashfs_dir_entry_2 sdire;
  24071. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  24072. + &sdire, next_block,next_offset,
  24073. + sizeof(sdire), &next_block,
  24074. + &next_offset))
  24075. + goto failed_read;
  24076. +
  24077. + length += sizeof(sdire);
  24078. + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
  24079. + } else {
  24080. + if (!squashfs_get_cached_block(i->i_sb, (char *)
  24081. + dire, next_block,next_offset,
  24082. + sizeof(*dire), &next_block,
  24083. + &next_offset))
  24084. + goto failed_read;
  24085. +
  24086. + length += sizeof(*dire);
  24087. + }
  24088. +
  24089. + if (!squashfs_get_cached_block(i->i_sb, dire->name,
  24090. + next_block, next_offset, dire->size + 1,
  24091. + &next_block, &next_offset))
  24092. + goto failed_read;
  24093. +
  24094. + length += dire->size + 1;
  24095. +
  24096. + if (sorted && name[0] < dire->name[0])
  24097. + goto exit_loop;
  24098. +
  24099. + if ((len == dire->size + 1) && !strncmp(name,
  24100. + dire->name, len)) {
  24101. + squashfs_inode_t ino =
  24102. + SQUASHFS_MKINODE(dirh.start_block,
  24103. + dire->offset);
  24104. + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
  24105. + dire->offset);
  24106. +
  24107. + TRACE("calling squashfs_iget for directory "
  24108. + "entry %s, inode %x:%x, %lld\n", name,
  24109. + dirh.start_block, dire->offset, ino);
  24110. +
  24111. + inode = squashfs_iget(i->i_sb, ino, inode_number);
  24112. +
  24113. + goto exit_loop;
  24114. + }
  24115. + }
  24116. + }
  24117. +
  24118. +exit_loop:
  24119. + kfree(dire);
  24120. + d_add(dentry, inode);
  24121. + return ERR_PTR(0);
  24122. +
  24123. +failed_read:
  24124. + ERROR("Unable to read directory block [%llx:%x]\n", next_block,
  24125. + next_offset);
  24126. + goto exit_loop;
  24127. +}
  24128. +
  24129. +
  24130. +int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
  24131. +{
  24132. + struct squashfs_super_block *sblk = &msblk->sblk;
  24133. +
  24134. + msblk->read_inode = squashfs_read_inode_2;
  24135. + msblk->read_fragment_index_table = read_fragment_index_table_2;
  24136. +
  24137. + sblk->bytes_used = sblk->bytes_used_2;
  24138. + sblk->uid_start = sblk->uid_start_2;
  24139. + sblk->guid_start = sblk->guid_start_2;
  24140. + sblk->inode_table_start = sblk->inode_table_start_2;
  24141. + sblk->directory_table_start = sblk->directory_table_start_2;
  24142. + sblk->fragment_table_start = sblk->fragment_table_start_2;
  24143. +
  24144. + return 1;
  24145. +}
  24146. diff --git a/include/linux/aufs_type.h b/include/linux/aufs_type.h
  24147. new file mode 100755
  24148. index 0000000..8b4629e
  24149. --- /dev/null
  24150. +++ b/include/linux/aufs_type.h
  24151. @@ -0,0 +1,97 @@
  24152. +/*
  24153. + * Copyright (C) 2005, 2006, 2007 Junjiro Okajima
  24154. + *
  24155. + * This program, aufs is free software; you can redistribute it and/or modify
  24156. + * it under the terms of the GNU General Public License as published by
  24157. + * the Free Software Foundation; either version 2 of the License, or
  24158. + * (at your option) any later version.
  24159. + *
  24160. + * This program is distributed in the hope that it will be useful,
  24161. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24162. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24163. + * GNU General Public License for more details.
  24164. + *
  24165. + * You should have received a copy of the GNU General Public License
  24166. + * along with this program; if not, write to the Free Software
  24167. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  24168. + */
  24169. +
  24170. +/* $Id: aufs_type.h,v 1.55 2007/05/14 03:40:57 sfjro Exp $ */
  24171. +
  24172. +#include <linux/ioctl.h>
  24173. +
  24174. +#ifndef __AUFS_TYPE_H__
  24175. +#define __AUFS_TYPE_H__
  24176. +
  24177. +#define AUFS_VERSION "20070514"
  24178. +
  24179. +/* ---------------------------------------------------------------------- */
  24180. +
  24181. +#ifdef CONFIG_AUFS_BRANCH_MAX_127
  24182. +typedef char aufs_bindex_t;
  24183. +#define AUFS_BRANCH_MAX 127
  24184. +#else
  24185. +typedef short aufs_bindex_t;
  24186. +#ifdef CONFIG_AUFS_BRANCH_MAX_511
  24187. +#define AUFS_BRANCH_MAX 511
  24188. +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
  24189. +#define AUFS_BRANCH_MAX 1023
  24190. +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
  24191. +#define AUFS_BRANCH_MAX 32767
  24192. +#else
  24193. +#error unknown CONFIG_AUFS_BRANCH_MAX value
  24194. +#endif
  24195. +#endif
  24196. +
  24197. +#define AUFS_NAME "aufs"
  24198. +#define AUFS_FSTYPE AUFS_NAME
  24199. +
  24200. +#define AUFS_ROOT_INO 2
  24201. +#define AUFS_FIRST_INO 11
  24202. +
  24203. +#define AUFS_WH_PFX ".wh."
  24204. +#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
  24205. +#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
  24206. +#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
  24207. +#define AUFS_DIRWH_DEF 3
  24208. +#define AUFS_RDCACHE_DEF 10 /* seconds */
  24209. +#define AUFS_WKQ_NAME AUFS_NAME "d"
  24210. +#define AUFS_NWKQ_DEF 4
  24211. +
  24212. +#ifdef CONFIG_AUFS_COMPAT
  24213. +#define AUFS_DIROPQ_NAME "__dir_opaque"
  24214. +#else
  24215. +#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
  24216. +#endif
  24217. +#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
  24218. +
  24219. +/* will be whiteouted doubly */
  24220. +#define AUFS_WH_BASENAME AUFS_WH_PFX AUFS_NAME
  24221. +#define AUFS_WH_PLINKDIR AUFS_WH_PFX "plink"
  24222. +
  24223. +/* ---------------------------------------------------------------------- */
  24224. +
  24225. +/* ioctl */
  24226. +enum {AuCtlErr, AuCtlErr_Last};
  24227. +enum {
  24228. + AuCtl_REFRESH, //AuCtl_REFRESHV,
  24229. + //AuCtl_FLUSH_PLINK,
  24230. + //AuCtl_CPUP,
  24231. + AuCtl_CPDOWN, AuCtl_MVDOWN
  24232. +};
  24233. +
  24234. +struct aufs_ctl_cp {
  24235. + int bsrc, bdst;
  24236. + int err;
  24237. +};
  24238. +
  24239. +#define Type 'A'
  24240. +#define AUFS_CTL_REFRESH _IO(Type, AuCtl_REFRESH)
  24241. +//#define AUFS_CTL_REFRESHV _IO(Type, AuCtl_REFRESHV)
  24242. +//#define AUFS_CTL_FLUSH_PLINK _IOR(Type, AuCtl_FLUSH_PLINK)
  24243. +//#define AUFS_CTL_CPUP _IOWR(Type, AuCtl_CPUP, struct aufs_ctl_cp)
  24244. +#define AUFS_CTL_CPDOWN _IOWR(Type, AuCtl_CPDOWN, struct aufs_ctl_cp)
  24245. +#define AUFS_CTL_MVDOWN _IOWR(Type, AuCtl_MVDOWN, struct aufs_ctl_cp)
  24246. +#undef Type
  24247. +
  24248. +#endif /* __AUFS_TYPE_H__ */
  24249. diff --git a/include/linux/squashfs_fs.h b/include/linux/squashfs_fs.h
  24250. new file mode 100644
  24251. index 0000000..a9380ad
  24252. --- /dev/null
  24253. +++ b/include/linux/squashfs_fs.h
  24254. @@ -0,0 +1,934 @@
  24255. +#ifndef SQUASHFS_FS
  24256. +#define SQUASHFS_FS
  24257. +
  24258. +/*
  24259. + * Squashfs
  24260. + *
  24261. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  24262. + * Phillip Lougher <phillip@lougher.org.uk>
  24263. + *
  24264. + * This program is free software; you can redistribute it and/or
  24265. + * modify it under the terms of the GNU General Public License
  24266. + * as published by the Free Software Foundation; either version 2,
  24267. + * or (at your option) any later version.
  24268. + *
  24269. + * This program is distributed in the hope that it will be useful,
  24270. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24271. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24272. + * GNU General Public License for more details.
  24273. + *
  24274. + * You should have received a copy of the GNU General Public License
  24275. + * along with this program; if not, write to the Free Software
  24276. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24277. + *
  24278. + * squashfs_fs.h
  24279. + */
  24280. +
  24281. +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
  24282. +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
  24283. +#endif
  24284. +
  24285. +#ifdef CONFIG_SQUASHFS_VMALLOC
  24286. +#define SQUASHFS_ALLOC(a) vmalloc(a)
  24287. +#define SQUASHFS_FREE(a) vfree(a)
  24288. +#else
  24289. +#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
  24290. +#define SQUASHFS_FREE(a) kfree(a)
  24291. +#endif
  24292. +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
  24293. +#define SQUASHFS_MAJOR 3
  24294. +#define SQUASHFS_MINOR 0
  24295. +#define SQUASHFS_MAGIC 0x73717368
  24296. +#define SQUASHFS_MAGIC_SWAP 0x68737173
  24297. +#define SQUASHFS_START 0
  24298. +
  24299. +/* size of metadata (inode and directory) blocks */
  24300. +#define SQUASHFS_METADATA_SIZE 8192
  24301. +#define SQUASHFS_METADATA_LOG 13
  24302. +
  24303. +/* default size of data blocks */
  24304. +#define SQUASHFS_FILE_SIZE 65536
  24305. +#define SQUASHFS_FILE_LOG 16
  24306. +
  24307. +#define SQUASHFS_FILE_MAX_SIZE 65536
  24308. +
  24309. +/* Max number of uids and gids */
  24310. +#define SQUASHFS_UIDS 256
  24311. +#define SQUASHFS_GUIDS 255
  24312. +
  24313. +/* Max length of filename (not 255) */
  24314. +#define SQUASHFS_NAME_LEN 256
  24315. +
  24316. +#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
  24317. +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
  24318. +#define SQUASHFS_INVALID_BLK ((long long) -1)
  24319. +#define SQUASHFS_USED_BLK ((long long) -2)
  24320. +
  24321. +/* Filesystem flags */
  24322. +#define SQUASHFS_NOI 0
  24323. +#define SQUASHFS_NOD 1
  24324. +#define SQUASHFS_CHECK 2
  24325. +#define SQUASHFS_NOF 3
  24326. +#define SQUASHFS_NO_FRAG 4
  24327. +#define SQUASHFS_ALWAYS_FRAG 5
  24328. +#define SQUASHFS_DUPLICATE 6
  24329. +#define SQUASHFS_EXPORT 7
  24330. +
  24331. +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
  24332. +
  24333. +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
  24334. + SQUASHFS_NOI)
  24335. +
  24336. +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
  24337. + SQUASHFS_NOD)
  24338. +
  24339. +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  24340. + SQUASHFS_NOF)
  24341. +
  24342. +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  24343. + SQUASHFS_NO_FRAG)
  24344. +
  24345. +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  24346. + SQUASHFS_ALWAYS_FRAG)
  24347. +
  24348. +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
  24349. + SQUASHFS_DUPLICATE)
  24350. +
  24351. +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
  24352. + SQUASHFS_EXPORT)
  24353. +
  24354. +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
  24355. + SQUASHFS_CHECK)
  24356. +
  24357. +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
  24358. + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \
  24359. + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
  24360. + (duplicate_checking << 6) | (exportable << 7))
  24361. +
  24362. +/* Max number of types and file types */
  24363. +#define SQUASHFS_DIR_TYPE 1
  24364. +#define SQUASHFS_FILE_TYPE 2
  24365. +#define SQUASHFS_SYMLINK_TYPE 3
  24366. +#define SQUASHFS_BLKDEV_TYPE 4
  24367. +#define SQUASHFS_CHRDEV_TYPE 5
  24368. +#define SQUASHFS_FIFO_TYPE 6
  24369. +#define SQUASHFS_SOCKET_TYPE 7
  24370. +#define SQUASHFS_LDIR_TYPE 8
  24371. +#define SQUASHFS_LREG_TYPE 9
  24372. +
  24373. +/* 1.0 filesystem type definitions */
  24374. +#define SQUASHFS_TYPES 5
  24375. +#define SQUASHFS_IPC_TYPE 0
  24376. +
  24377. +/* Flag whether block is compressed or uncompressed, bit is set if block is
  24378. + * uncompressed */
  24379. +#define SQUASHFS_COMPRESSED_BIT (1 << 15)
  24380. +
  24381. +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
  24382. + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
  24383. +
  24384. +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
  24385. +
  24386. +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
  24387. +
  24388. +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
  24389. + ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
  24390. + ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
  24391. +
  24392. +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
  24393. +
  24394. +/*
  24395. + * Inode number ops. Inodes consist of a compressed block number, and an
  24396. + * uncompressed offset within that block
  24397. + */
  24398. +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
  24399. +
  24400. +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
  24401. +
  24402. +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
  24403. + << 16) + (B)))
  24404. +
  24405. +/* Compute 32 bit VFS inode number from squashfs inode number */
  24406. +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
  24407. + ((b) >> 2) + 1))
  24408. +/* XXX */
  24409. +
  24410. +/* Translate between VFS mode and squashfs mode */
  24411. +#define SQUASHFS_MODE(a) ((a) & 0xfff)
  24412. +
  24413. +/* fragment and fragment table defines */
  24414. +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry))
  24415. +
  24416. +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
  24417. + SQUASHFS_METADATA_SIZE)
  24418. +
  24419. +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
  24420. + SQUASHFS_METADATA_SIZE)
  24421. +
  24422. +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
  24423. + SQUASHFS_METADATA_SIZE - 1) / \
  24424. + SQUASHFS_METADATA_SIZE)
  24425. +
  24426. +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
  24427. + sizeof(long long))
  24428. +
  24429. +/* inode lookup table defines */
  24430. +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t))
  24431. +
  24432. +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
  24433. + SQUASHFS_METADATA_SIZE)
  24434. +
  24435. +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
  24436. + SQUASHFS_METADATA_SIZE)
  24437. +
  24438. +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
  24439. + SQUASHFS_METADATA_SIZE - 1) / \
  24440. + SQUASHFS_METADATA_SIZE)
  24441. +
  24442. +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
  24443. + sizeof(long long))
  24444. +
  24445. +/* cached data constants for filesystem */
  24446. +#define SQUASHFS_CACHED_BLKS 8
  24447. +
  24448. +#define SQUASHFS_MAX_FILE_SIZE_LOG 64
  24449. +
  24450. +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
  24451. + (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
  24452. +
  24453. +#define SQUASHFS_MARKER_BYTE 0xff
  24454. +
  24455. +/* meta index cache */
  24456. +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
  24457. +#define SQUASHFS_META_ENTRIES 31
  24458. +#define SQUASHFS_META_NUMBER 8
  24459. +#define SQUASHFS_SLOTS 4
  24460. +
  24461. +struct meta_entry {
  24462. + long long data_block;
  24463. + unsigned int index_block;
  24464. + unsigned short offset;
  24465. + unsigned short pad;
  24466. +};
  24467. +
  24468. +struct meta_index {
  24469. + unsigned int inode_number;
  24470. + unsigned int offset;
  24471. + unsigned short entries;
  24472. + unsigned short skip;
  24473. + unsigned short locked;
  24474. + unsigned short pad;
  24475. + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
  24476. +};
  24477. +
  24478. +
  24479. +/*
  24480. + * definitions for structures on disk
  24481. + */
  24482. +
  24483. +typedef long long squashfs_block_t;
  24484. +typedef long long squashfs_inode_t;
  24485. +
  24486. +struct squashfs_super_block {
  24487. + unsigned int s_magic;
  24488. + unsigned int inodes;
  24489. + unsigned int bytes_used_2;
  24490. + unsigned int uid_start_2;
  24491. + unsigned int guid_start_2;
  24492. + unsigned int inode_table_start_2;
  24493. + unsigned int directory_table_start_2;
  24494. + unsigned int s_major:16;
  24495. + unsigned int s_minor:16;
  24496. + unsigned int block_size_1:16;
  24497. + unsigned int block_log:16;
  24498. + unsigned int flags:8;
  24499. + unsigned int no_uids:8;
  24500. + unsigned int no_guids:8;
  24501. + unsigned int mkfs_time /* time of filesystem creation */;
  24502. + squashfs_inode_t root_inode;
  24503. + unsigned int block_size;
  24504. + unsigned int fragments;
  24505. + unsigned int fragment_table_start_2;
  24506. + long long bytes_used;
  24507. + long long uid_start;
  24508. + long long guid_start;
  24509. + long long inode_table_start;
  24510. + long long directory_table_start;
  24511. + long long fragment_table_start;
  24512. + long long lookup_table_start;
  24513. +} __attribute__ ((packed));
  24514. +
  24515. +struct squashfs_dir_index {
  24516. + unsigned int index;
  24517. + unsigned int start_block;
  24518. + unsigned char size;
  24519. + unsigned char name[0];
  24520. +} __attribute__ ((packed));
  24521. +
  24522. +#define SQUASHFS_BASE_INODE_HEADER \
  24523. + unsigned int inode_type:4; \
  24524. + unsigned int mode:12; \
  24525. + unsigned int uid:8; \
  24526. + unsigned int guid:8; \
  24527. + unsigned int mtime; \
  24528. + unsigned int inode_number;
  24529. +
  24530. +struct squashfs_base_inode_header {
  24531. + SQUASHFS_BASE_INODE_HEADER;
  24532. +} __attribute__ ((packed));
  24533. +
  24534. +struct squashfs_ipc_inode_header {
  24535. + SQUASHFS_BASE_INODE_HEADER;
  24536. + unsigned int nlink;
  24537. +} __attribute__ ((packed));
  24538. +
  24539. +struct squashfs_dev_inode_header {
  24540. + SQUASHFS_BASE_INODE_HEADER;
  24541. + unsigned int nlink;
  24542. + unsigned short rdev;
  24543. +} __attribute__ ((packed));
  24544. +
  24545. +struct squashfs_symlink_inode_header {
  24546. + SQUASHFS_BASE_INODE_HEADER;
  24547. + unsigned int nlink;
  24548. + unsigned short symlink_size;
  24549. + char symlink[0];
  24550. +} __attribute__ ((packed));
  24551. +
  24552. +struct squashfs_reg_inode_header {
  24553. + SQUASHFS_BASE_INODE_HEADER;
  24554. + squashfs_block_t start_block;
  24555. + unsigned int fragment;
  24556. + unsigned int offset;
  24557. + unsigned int file_size;
  24558. + unsigned short block_list[0];
  24559. +} __attribute__ ((packed));
  24560. +
  24561. +struct squashfs_lreg_inode_header {
  24562. + SQUASHFS_BASE_INODE_HEADER;
  24563. + unsigned int nlink;
  24564. + squashfs_block_t start_block;
  24565. + unsigned int fragment;
  24566. + unsigned int offset;
  24567. + long long file_size;
  24568. + unsigned short block_list[0];
  24569. +} __attribute__ ((packed));
  24570. +
  24571. +struct squashfs_dir_inode_header {
  24572. + SQUASHFS_BASE_INODE_HEADER;
  24573. + unsigned int nlink;
  24574. + unsigned int file_size:19;
  24575. + unsigned int offset:13;
  24576. + unsigned int start_block;
  24577. + unsigned int parent_inode;
  24578. +} __attribute__ ((packed));
  24579. +
  24580. +struct squashfs_ldir_inode_header {
  24581. + SQUASHFS_BASE_INODE_HEADER;
  24582. + unsigned int nlink;
  24583. + unsigned int file_size:27;
  24584. + unsigned int offset:13;
  24585. + unsigned int start_block;
  24586. + unsigned int i_count:16;
  24587. + unsigned int parent_inode;
  24588. + struct squashfs_dir_index index[0];
  24589. +} __attribute__ ((packed));
  24590. +
  24591. +union squashfs_inode_header {
  24592. + struct squashfs_base_inode_header base;
  24593. + struct squashfs_dev_inode_header dev;
  24594. + struct squashfs_symlink_inode_header symlink;
  24595. + struct squashfs_reg_inode_header reg;
  24596. + struct squashfs_lreg_inode_header lreg;
  24597. + struct squashfs_dir_inode_header dir;
  24598. + struct squashfs_ldir_inode_header ldir;
  24599. + struct squashfs_ipc_inode_header ipc;
  24600. +};
  24601. +
  24602. +struct squashfs_dir_entry {
  24603. + unsigned int offset:13;
  24604. + unsigned int type:3;
  24605. + unsigned int size:8;
  24606. + int inode_number:16;
  24607. + char name[0];
  24608. +} __attribute__ ((packed));
  24609. +
  24610. +struct squashfs_dir_header {
  24611. + unsigned int count:8;
  24612. + unsigned int start_block;
  24613. + unsigned int inode_number;
  24614. +} __attribute__ ((packed));
  24615. +
  24616. +struct squashfs_fragment_entry {
  24617. + long long start_block;
  24618. + unsigned int size;
  24619. + unsigned int pending;
  24620. +} __attribute__ ((packed));
  24621. +
  24622. +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
  24623. +extern int squashfs_uncompress_init(void);
  24624. +extern int squashfs_uncompress_exit(void);
  24625. +
  24626. +/*
  24627. + * macros to convert each packed bitfield structure from little endian to big
  24628. + * endian and vice versa. These are needed when creating or using a filesystem
  24629. + * on a machine with different byte ordering to the target architecture.
  24630. + *
  24631. + */
  24632. +
  24633. +#define SQUASHFS_SWAP_START \
  24634. + int bits;\
  24635. + int b_pos;\
  24636. + unsigned long long val;\
  24637. + unsigned char *s;\
  24638. + unsigned char *d;
  24639. +
  24640. +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
  24641. + SQUASHFS_SWAP_START\
  24642. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
  24643. + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
  24644. + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
  24645. + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
  24646. + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
  24647. + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
  24648. + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
  24649. + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
  24650. + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
  24651. + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
  24652. + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
  24653. + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
  24654. + SQUASHFS_SWAP((s)->flags, d, 288, 8);\
  24655. + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
  24656. + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
  24657. + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
  24658. + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
  24659. + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
  24660. + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
  24661. + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
  24662. + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
  24663. + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
  24664. + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
  24665. + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
  24666. + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
  24667. + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
  24668. + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\
  24669. +}
  24670. +
  24671. +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
  24672. + SQUASHFS_MEMSET(s, d, n);\
  24673. + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
  24674. + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
  24675. + SQUASHFS_SWAP((s)->uid, d, 16, 8);\
  24676. + SQUASHFS_SWAP((s)->guid, d, 24, 8);\
  24677. + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
  24678. + SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
  24679. +
  24680. +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
  24681. + SQUASHFS_SWAP_START\
  24682. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
  24683. +}
  24684. +
  24685. +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
  24686. + SQUASHFS_SWAP_START\
  24687. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24688. + sizeof(struct squashfs_ipc_inode_header))\
  24689. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24690. +}
  24691. +
  24692. +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
  24693. + SQUASHFS_SWAP_START\
  24694. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24695. + sizeof(struct squashfs_dev_inode_header)); \
  24696. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24697. + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
  24698. +}
  24699. +
  24700. +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
  24701. + SQUASHFS_SWAP_START\
  24702. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24703. + sizeof(struct squashfs_symlink_inode_header));\
  24704. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24705. + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
  24706. +}
  24707. +
  24708. +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
  24709. + SQUASHFS_SWAP_START\
  24710. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24711. + sizeof(struct squashfs_reg_inode_header));\
  24712. + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
  24713. + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
  24714. + SQUASHFS_SWAP((s)->offset, d, 192, 32);\
  24715. + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
  24716. +}
  24717. +
  24718. +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
  24719. + SQUASHFS_SWAP_START\
  24720. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24721. + sizeof(struct squashfs_lreg_inode_header));\
  24722. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24723. + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
  24724. + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
  24725. + SQUASHFS_SWAP((s)->offset, d, 224, 32);\
  24726. + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
  24727. +}
  24728. +
  24729. +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
  24730. + SQUASHFS_SWAP_START\
  24731. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24732. + sizeof(struct squashfs_dir_inode_header));\
  24733. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24734. + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
  24735. + SQUASHFS_SWAP((s)->offset, d, 147, 13);\
  24736. + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
  24737. + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
  24738. +}
  24739. +
  24740. +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
  24741. + SQUASHFS_SWAP_START\
  24742. + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
  24743. + sizeof(struct squashfs_ldir_inode_header));\
  24744. + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
  24745. + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
  24746. + SQUASHFS_SWAP((s)->offset, d, 155, 13);\
  24747. + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
  24748. + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
  24749. + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
  24750. +}
  24751. +
  24752. +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
  24753. + SQUASHFS_SWAP_START\
  24754. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
  24755. + SQUASHFS_SWAP((s)->index, d, 0, 32);\
  24756. + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
  24757. + SQUASHFS_SWAP((s)->size, d, 64, 8);\
  24758. +}
  24759. +
  24760. +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
  24761. + SQUASHFS_SWAP_START\
  24762. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
  24763. + SQUASHFS_SWAP((s)->count, d, 0, 8);\
  24764. + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
  24765. + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
  24766. +}
  24767. +
  24768. +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
  24769. + SQUASHFS_SWAP_START\
  24770. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
  24771. + SQUASHFS_SWAP((s)->offset, d, 0, 13);\
  24772. + SQUASHFS_SWAP((s)->type, d, 13, 3);\
  24773. + SQUASHFS_SWAP((s)->size, d, 16, 8);\
  24774. + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
  24775. +}
  24776. +
  24777. +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
  24778. + SQUASHFS_SWAP_START\
  24779. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
  24780. + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
  24781. + SQUASHFS_SWAP((s)->size, d, 64, 32);\
  24782. +}
  24783. +
  24784. +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)
  24785. +
  24786. +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
  24787. + int entry;\
  24788. + int bit_position;\
  24789. + SQUASHFS_SWAP_START\
  24790. + SQUASHFS_MEMSET(s, d, n * 2);\
  24791. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24792. + 16)\
  24793. + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
  24794. +}
  24795. +
  24796. +#define SQUASHFS_SWAP_INTS(s, d, n) {\
  24797. + int entry;\
  24798. + int bit_position;\
  24799. + SQUASHFS_SWAP_START\
  24800. + SQUASHFS_MEMSET(s, d, n * 4);\
  24801. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24802. + 32)\
  24803. + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
  24804. +}
  24805. +
  24806. +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
  24807. + int entry;\
  24808. + int bit_position;\
  24809. + SQUASHFS_SWAP_START\
  24810. + SQUASHFS_MEMSET(s, d, n * 8);\
  24811. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24812. + 64)\
  24813. + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
  24814. +}
  24815. +
  24816. +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
  24817. + int entry;\
  24818. + int bit_position;\
  24819. + SQUASHFS_SWAP_START\
  24820. + SQUASHFS_MEMSET(s, d, n * bits / 8);\
  24821. + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
  24822. + bits)\
  24823. + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
  24824. +}
  24825. +
  24826. +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
  24827. +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
  24828. +
  24829. +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
  24830. +
  24831. +struct squashfs_base_inode_header_1 {
  24832. + unsigned int inode_type:4;
  24833. + unsigned int mode:12; /* protection */
  24834. + unsigned int uid:4; /* index into uid table */
  24835. + unsigned int guid:4; /* index into guid table */
  24836. +} __attribute__ ((packed));
  24837. +
  24838. +struct squashfs_ipc_inode_header_1 {
  24839. + unsigned int inode_type:4;
  24840. + unsigned int mode:12; /* protection */
  24841. + unsigned int uid:4; /* index into uid table */
  24842. + unsigned int guid:4; /* index into guid table */
  24843. + unsigned int type:4;
  24844. + unsigned int offset:4;
  24845. +} __attribute__ ((packed));
  24846. +
  24847. +struct squashfs_dev_inode_header_1 {
  24848. + unsigned int inode_type:4;
  24849. + unsigned int mode:12; /* protection */
  24850. + unsigned int uid:4; /* index into uid table */
  24851. + unsigned int guid:4; /* index into guid table */
  24852. + unsigned short rdev;
  24853. +} __attribute__ ((packed));
  24854. +
  24855. +struct squashfs_symlink_inode_header_1 {
  24856. + unsigned int inode_type:4;
  24857. + unsigned int mode:12; /* protection */
  24858. + unsigned int uid:4; /* index into uid table */
  24859. + unsigned int guid:4; /* index into guid table */
  24860. + unsigned short symlink_size;
  24861. + char symlink[0];
  24862. +} __attribute__ ((packed));
  24863. +
  24864. +struct squashfs_reg_inode_header_1 {
  24865. + unsigned int inode_type:4;
  24866. + unsigned int mode:12; /* protection */
  24867. + unsigned int uid:4; /* index into uid table */
  24868. + unsigned int guid:4; /* index into guid table */
  24869. + unsigned int mtime;
  24870. + unsigned int start_block;
  24871. + unsigned int file_size:32;
  24872. + unsigned short block_list[0];
  24873. +} __attribute__ ((packed));
  24874. +
  24875. +struct squashfs_dir_inode_header_1 {
  24876. + unsigned int inode_type:4;
  24877. + unsigned int mode:12; /* protection */
  24878. + unsigned int uid:4; /* index into uid table */
  24879. + unsigned int guid:4; /* index into guid table */
  24880. + unsigned int file_size:19;
  24881. + unsigned int offset:13;
  24882. + unsigned int mtime;
  24883. + unsigned int start_block:24;
  24884. +} __attribute__ ((packed));
  24885. +
  24886. +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
  24887. + SQUASHFS_MEMSET(s, d, n);\
  24888. + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
  24889. + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
  24890. + SQUASHFS_SWAP((s)->uid, d, 16, 4);\
  24891. + SQUASHFS_SWAP((s)->guid, d, 20, 4);
  24892. +
  24893. +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
  24894. + SQUASHFS_SWAP_START\
  24895. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
  24896. +}
  24897. +
  24898. +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
  24899. + SQUASHFS_SWAP_START\
  24900. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24901. + sizeof(struct squashfs_ipc_inode_header_1));\
  24902. + SQUASHFS_SWAP((s)->type, d, 24, 4);\
  24903. + SQUASHFS_SWAP((s)->offset, d, 28, 4);\
  24904. +}
  24905. +
  24906. +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
  24907. + SQUASHFS_SWAP_START\
  24908. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24909. + sizeof(struct squashfs_dev_inode_header_1));\
  24910. + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
  24911. +}
  24912. +
  24913. +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
  24914. + SQUASHFS_SWAP_START\
  24915. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24916. + sizeof(struct squashfs_symlink_inode_header_1));\
  24917. + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
  24918. +}
  24919. +
  24920. +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
  24921. + SQUASHFS_SWAP_START\
  24922. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24923. + sizeof(struct squashfs_reg_inode_header_1));\
  24924. + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
  24925. + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
  24926. + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
  24927. +}
  24928. +
  24929. +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
  24930. + SQUASHFS_SWAP_START\
  24931. + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
  24932. + sizeof(struct squashfs_dir_inode_header_1));\
  24933. + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
  24934. + SQUASHFS_SWAP((s)->offset, d, 43, 13);\
  24935. + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
  24936. + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
  24937. +}
  24938. +
  24939. +#endif
  24940. +
  24941. +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
  24942. +
  24943. +struct squashfs_dir_index_2 {
  24944. + unsigned int index:27;
  24945. + unsigned int start_block:29;
  24946. + unsigned char size;
  24947. + unsigned char name[0];
  24948. +} __attribute__ ((packed));
  24949. +
  24950. +struct squashfs_base_inode_header_2 {
  24951. + unsigned int inode_type:4;
  24952. + unsigned int mode:12; /* protection */
  24953. + unsigned int uid:8; /* index into uid table */
  24954. + unsigned int guid:8; /* index into guid table */
  24955. +} __attribute__ ((packed));
  24956. +
  24957. +struct squashfs_ipc_inode_header_2 {
  24958. + unsigned int inode_type:4;
  24959. + unsigned int mode:12; /* protection */
  24960. + unsigned int uid:8; /* index into uid table */
  24961. + unsigned int guid:8; /* index into guid table */
  24962. +} __attribute__ ((packed));
  24963. +
  24964. +struct squashfs_dev_inode_header_2 {
  24965. + unsigned int inode_type:4;
  24966. + unsigned int mode:12; /* protection */
  24967. + unsigned int uid:8; /* index into uid table */
  24968. + unsigned int guid:8; /* index into guid table */
  24969. + unsigned short rdev;
  24970. +} __attribute__ ((packed));
  24971. +
  24972. +struct squashfs_symlink_inode_header_2 {
  24973. + unsigned int inode_type:4;
  24974. + unsigned int mode:12; /* protection */
  24975. + unsigned int uid:8; /* index into uid table */
  24976. + unsigned int guid:8; /* index into guid table */
  24977. + unsigned short symlink_size;
  24978. + char symlink[0];
  24979. +} __attribute__ ((packed));
  24980. +
  24981. +struct squashfs_reg_inode_header_2 {
  24982. + unsigned int inode_type:4;
  24983. + unsigned int mode:12; /* protection */
  24984. + unsigned int uid:8; /* index into uid table */
  24985. + unsigned int guid:8; /* index into guid table */
  24986. + unsigned int mtime;
  24987. + unsigned int start_block;
  24988. + unsigned int fragment;
  24989. + unsigned int offset;
  24990. + unsigned int file_size:32;
  24991. + unsigned short block_list[0];
  24992. +} __attribute__ ((packed));
  24993. +
  24994. +struct squashfs_dir_inode_header_2 {
  24995. + unsigned int inode_type:4;
  24996. + unsigned int mode:12; /* protection */
  24997. + unsigned int uid:8; /* index into uid table */
  24998. + unsigned int guid:8; /* index into guid table */
  24999. + unsigned int file_size:19;
  25000. + unsigned int offset:13;
  25001. + unsigned int mtime;
  25002. + unsigned int start_block:24;
  25003. +} __attribute__ ((packed));
  25004. +
  25005. +struct squashfs_ldir_inode_header_2 {
  25006. + unsigned int inode_type:4;
  25007. + unsigned int mode:12; /* protection */
  25008. + unsigned int uid:8; /* index into uid table */
  25009. + unsigned int guid:8; /* index into guid table */
  25010. + unsigned int file_size:27;
  25011. + unsigned int offset:13;
  25012. + unsigned int mtime;
  25013. + unsigned int start_block:24;
  25014. + unsigned int i_count:16;
  25015. + struct squashfs_dir_index_2 index[0];
  25016. +} __attribute__ ((packed));
  25017. +
  25018. +union squashfs_inode_header_2 {
  25019. + struct squashfs_base_inode_header_2 base;
  25020. + struct squashfs_dev_inode_header_2 dev;
  25021. + struct squashfs_symlink_inode_header_2 symlink;
  25022. + struct squashfs_reg_inode_header_2 reg;
  25023. + struct squashfs_dir_inode_header_2 dir;
  25024. + struct squashfs_ldir_inode_header_2 ldir;
  25025. + struct squashfs_ipc_inode_header_2 ipc;
  25026. +};
  25027. +
  25028. +struct squashfs_dir_header_2 {
  25029. + unsigned int count:8;
  25030. + unsigned int start_block:24;
  25031. +} __attribute__ ((packed));
  25032. +
  25033. +struct squashfs_dir_entry_2 {
  25034. + unsigned int offset:13;
  25035. + unsigned int type:3;
  25036. + unsigned int size:8;
  25037. + char name[0];
  25038. +} __attribute__ ((packed));
  25039. +
  25040. +struct squashfs_fragment_entry_2 {
  25041. + unsigned int start_block;
  25042. + unsigned int size;
  25043. +} __attribute__ ((packed));
  25044. +
  25045. +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
  25046. + SQUASHFS_MEMSET(s, d, n);\
  25047. + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
  25048. + SQUASHFS_SWAP((s)->mode, d, 4, 12);\
  25049. + SQUASHFS_SWAP((s)->uid, d, 16, 8);\
  25050. + SQUASHFS_SWAP((s)->guid, d, 24, 8);\
  25051. +
  25052. +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
  25053. + SQUASHFS_SWAP_START\
  25054. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
  25055. +}
  25056. +
  25057. +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
  25058. + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
  25059. +
  25060. +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
  25061. + SQUASHFS_SWAP_START\
  25062. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  25063. + sizeof(struct squashfs_dev_inode_header_2)); \
  25064. + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
  25065. +}
  25066. +
  25067. +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
  25068. + SQUASHFS_SWAP_START\
  25069. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  25070. + sizeof(struct squashfs_symlink_inode_header_2));\
  25071. + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
  25072. +}
  25073. +
  25074. +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
  25075. + SQUASHFS_SWAP_START\
  25076. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  25077. + sizeof(struct squashfs_reg_inode_header_2));\
  25078. + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
  25079. + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
  25080. + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
  25081. + SQUASHFS_SWAP((s)->offset, d, 128, 32);\
  25082. + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
  25083. +}
  25084. +
  25085. +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
  25086. + SQUASHFS_SWAP_START\
  25087. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  25088. + sizeof(struct squashfs_dir_inode_header_2));\
  25089. + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
  25090. + SQUASHFS_SWAP((s)->offset, d, 51, 13);\
  25091. + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
  25092. + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
  25093. +}
  25094. +
  25095. +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
  25096. + SQUASHFS_SWAP_START\
  25097. + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
  25098. + sizeof(struct squashfs_ldir_inode_header_2));\
  25099. + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
  25100. + SQUASHFS_SWAP((s)->offset, d, 59, 13);\
  25101. + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
  25102. + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
  25103. + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
  25104. +}
  25105. +
  25106. +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
  25107. + SQUASHFS_SWAP_START\
  25108. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
  25109. + SQUASHFS_SWAP((s)->index, d, 0, 27);\
  25110. + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
  25111. + SQUASHFS_SWAP((s)->size, d, 56, 8);\
  25112. +}
  25113. +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
  25114. + SQUASHFS_SWAP_START\
  25115. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
  25116. + SQUASHFS_SWAP((s)->count, d, 0, 8);\
  25117. + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
  25118. +}
  25119. +
  25120. +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
  25121. + SQUASHFS_SWAP_START\
  25122. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
  25123. + SQUASHFS_SWAP((s)->offset, d, 0, 13);\
  25124. + SQUASHFS_SWAP((s)->type, d, 13, 3);\
  25125. + SQUASHFS_SWAP((s)->size, d, 16, 8);\
  25126. +}
  25127. +
  25128. +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
  25129. + SQUASHFS_SWAP_START\
  25130. + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
  25131. + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
  25132. + SQUASHFS_SWAP((s)->size, d, 32, 32);\
  25133. +}
  25134. +
  25135. +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
  25136. +
  25137. +/* fragment and fragment table defines */
  25138. +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
  25139. +
  25140. +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
  25141. + SQUASHFS_METADATA_SIZE)
  25142. +
  25143. +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
  25144. + SQUASHFS_METADATA_SIZE)
  25145. +
  25146. +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
  25147. + SQUASHFS_METADATA_SIZE - 1) / \
  25148. + SQUASHFS_METADATA_SIZE)
  25149. +
  25150. +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
  25151. + sizeof(int))
  25152. +
  25153. +#endif
  25154. +
  25155. +#ifdef __KERNEL__
  25156. +
  25157. +/*
  25158. + * macros used to swap each structure entry, taking into account
  25159. + * bitfields and different bitfield placing conventions on differing
  25160. + * architectures
  25161. + */
  25162. +
  25163. +#include <asm/byteorder.h>
  25164. +
  25165. +#ifdef __BIG_ENDIAN
  25166. + /* convert from little endian to big endian */
  25167. +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
  25168. + tbits, b_pos)
  25169. +#else
  25170. + /* convert from big endian to little endian */
  25171. +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
  25172. + tbits, 64 - tbits - b_pos)
  25173. +#endif
  25174. +
  25175. +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
  25176. + b_pos = pos % 8;\
  25177. + val = 0;\
  25178. + s = (unsigned char *)p + (pos / 8);\
  25179. + d = ((unsigned char *) &val) + 7;\
  25180. + for(bits = 0; bits < (tbits + b_pos); bits += 8) \
  25181. + *d-- = *s++;\
  25182. + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
  25183. +}
  25184. +
  25185. +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
  25186. +
  25187. +#endif
  25188. +#endif
  25189. diff --git a/include/linux/squashfs_fs_i.h b/include/linux/squashfs_fs_i.h
  25190. new file mode 100644
  25191. index 0000000..798891a
  25192. --- /dev/null
  25193. +++ b/include/linux/squashfs_fs_i.h
  25194. @@ -0,0 +1,45 @@
  25195. +#ifndef SQUASHFS_FS_I
  25196. +#define SQUASHFS_FS_I
  25197. +/*
  25198. + * Squashfs
  25199. + *
  25200. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  25201. + * Phillip Lougher <phillip@lougher.org.uk>
  25202. + *
  25203. + * This program is free software; you can redistribute it and/or
  25204. + * modify it under the terms of the GNU General Public License
  25205. + * as published by the Free Software Foundation; either version 2,
  25206. + * or (at your option) any later version.
  25207. + *
  25208. + * This program is distributed in the hope that it will be useful,
  25209. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25210. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25211. + * GNU General Public License for more details.
  25212. + *
  25213. + * You should have received a copy of the GNU General Public License
  25214. + * along with this program; if not, write to the Free Software
  25215. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25216. + *
  25217. + * squashfs_fs_i.h
  25218. + */
  25219. +
  25220. +struct squashfs_inode_info {
  25221. + long long start_block;
  25222. + unsigned int offset;
  25223. + union {
  25224. + struct {
  25225. + long long fragment_start_block;
  25226. + unsigned int fragment_size;
  25227. + unsigned int fragment_offset;
  25228. + long long block_list_start;
  25229. + } s1;
  25230. + struct {
  25231. + long long directory_index_start;
  25232. + unsigned int directory_index_offset;
  25233. + unsigned int directory_index_count;
  25234. + unsigned int parent_inode;
  25235. + } s2;
  25236. + } u;
  25237. + struct inode vfs_inode;
  25238. +};
  25239. +#endif
  25240. diff --git a/include/linux/squashfs_fs_sb.h b/include/linux/squashfs_fs_sb.h
  25241. new file mode 100644
  25242. index 0000000..8f3bf99
  25243. --- /dev/null
  25244. +++ b/include/linux/squashfs_fs_sb.h
  25245. @@ -0,0 +1,74 @@
  25246. +#ifndef SQUASHFS_FS_SB
  25247. +#define SQUASHFS_FS_SB
  25248. +/*
  25249. + * Squashfs
  25250. + *
  25251. + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
  25252. + * Phillip Lougher <phillip@lougher.org.uk>
  25253. + *
  25254. + * This program is free software; you can redistribute it and/or
  25255. + * modify it under the terms of the GNU General Public License
  25256. + * as published by the Free Software Foundation; either version 2,
  25257. + * or (at your option) any later version.
  25258. + *
  25259. + * This program is distributed in the hope that it will be useful,
  25260. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25261. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25262. + * GNU General Public License for more details.
  25263. + *
  25264. + * You should have received a copy of the GNU General Public License
  25265. + * along with this program; if not, write to the Free Software
  25266. + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25267. + *
  25268. + * squashfs_fs_sb.h
  25269. + */
  25270. +
  25271. +#include <linux/squashfs_fs.h>
  25272. +
  25273. +struct squashfs_cache {
  25274. + long long block;
  25275. + int length;
  25276. + long long next_index;
  25277. + char *data;
  25278. +};
  25279. +
  25280. +struct squashfs_fragment_cache {
  25281. + long long block;
  25282. + int length;
  25283. + unsigned int locked;
  25284. + char *data;
  25285. +};
  25286. +
  25287. +struct squashfs_sb_info {
  25288. + struct squashfs_super_block sblk;
  25289. + int devblksize;
  25290. + int devblksize_log2;
  25291. + int swap;
  25292. + struct squashfs_cache *block_cache;
  25293. + struct squashfs_fragment_cache *fragment;
  25294. + int next_cache;
  25295. + int next_fragment;
  25296. + int next_meta_index;
  25297. + unsigned int *uid;
  25298. + unsigned int *guid;
  25299. + long long *fragment_index;
  25300. + unsigned int *fragment_index_2;
  25301. + char *read_page;
  25302. + struct mutex read_data_mutex;
  25303. + struct mutex read_page_mutex;
  25304. + struct mutex block_cache_mutex;
  25305. + struct mutex fragment_mutex;
  25306. + struct mutex meta_index_mutex;
  25307. + wait_queue_head_t waitq;
  25308. + wait_queue_head_t fragment_wait_queue;
  25309. + struct meta_index *meta_index;
  25310. + z_stream stream;
  25311. + long long *inode_lookup_table;
  25312. + int (*read_inode)(struct inode *i, squashfs_inode_t \
  25313. + inode);
  25314. + long long (*read_blocklist)(struct inode *inode, int \
  25315. + index, int readahead_blks, char *block_list, \
  25316. + unsigned short **block_p, unsigned int *bsize);
  25317. + int (*read_fragment_index_table)(struct super_block *s);
  25318. +};
  25319. +#endif
  25320. diff --git a/init/Kconfig b/init/Kconfig
  25321. index b170aa1..bcfc3b4 100644
  25322. --- a/init/Kconfig
  25323. +++ b/init/Kconfig
  25324. @@ -244,23 +244,21 @@ config AUDITSYSCALL
  25325. ensure that INOTIFY is configured.
  25326. config IKCONFIG
  25327. - tristate "Kernel .config support"
  25328. + tristate "Kernel .miniconfig support"
  25329. ---help---
  25330. - This option enables the complete Linux kernel ".config" file
  25331. + This option enables the mini Linux kernel ".miniconfig" file
  25332. contents to be saved in the kernel. It provides documentation
  25333. of which kernel options are used in a running kernel or in an
  25334. - on-disk kernel. This information can be extracted from the kernel
  25335. - image file with the script scripts/extract-ikconfig and used as
  25336. - input to rebuild the current kernel or to build another kernel.
  25337. - It can also be extracted from a running kernel by reading
  25338. - /proc/config.gz if enabled (below).
  25339. + on-disk kernel.
  25340. + It can be extracted from a running kernel by reading
  25341. + /proc/miniconfig.gz if enabled (below).
  25342. config IKCONFIG_PROC
  25343. - bool "Enable access to .config through /proc/config.gz"
  25344. + bool "Enable access to .miniconfig through /proc/miniconfig.gz"
  25345. depends on IKCONFIG && PROC_FS
  25346. ---help---
  25347. This option enables access to the kernel configuration file
  25348. - through /proc/config.gz.
  25349. + through /proc/miniconfig.gz.
  25350. config CPUSETS
  25351. bool "Cpuset support"
  25352. diff --git a/init/LzmaDecode.c b/init/LzmaDecode.c
  25353. new file mode 100644
  25354. index 0000000..21bf40b
  25355. --- /dev/null
  25356. +++ b/init/LzmaDecode.c
  25357. @@ -0,0 +1,588 @@
  25358. +/*
  25359. + LzmaDecode.c
  25360. + LZMA Decoder (optimized for Speed version)
  25361. +
  25362. + LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
  25363. + http://www.7-zip.org/
  25364. +
  25365. + LZMA SDK is licensed under two licenses:
  25366. + 1) GNU Lesser General Public License (GNU LGPL)
  25367. + 2) Common Public License (CPL)
  25368. + It means that you can select one of these two licenses and
  25369. + follow rules of that license.
  25370. +
  25371. + SPECIAL EXCEPTION:
  25372. + Igor Pavlov, as the author of this Code, expressly permits you to
  25373. + statically or dynamically link your Code (or bind by name) to the
  25374. + interfaces of this file without subjecting your linked Code to the
  25375. + terms of the CPL or GNU LGPL. Any modifications or additions
  25376. + to this file, however, are subject to the LGPL or CPL terms.
  25377. +*/
  25378. +
  25379. +#include "LzmaDecode.h"
  25380. +
  25381. +#ifndef Byte
  25382. +#define Byte unsigned char
  25383. +#endif
  25384. +
  25385. +#define kNumTopBits 24
  25386. +#define kTopValue ((UInt32)1 << kNumTopBits)
  25387. +
  25388. +#define kNumBitModelTotalBits 11
  25389. +#define kBitModelTotal (1 << kNumBitModelTotalBits)
  25390. +#define kNumMoveBits 5
  25391. +
  25392. +#define RC_READ_BYTE (*Buffer++)
  25393. +
  25394. +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
  25395. + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
  25396. +
  25397. +#ifdef _LZMA_IN_CB
  25398. +
  25399. +#define RC_TEST { if (Buffer == BufferLim) \
  25400. + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
  25401. + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
  25402. +
  25403. +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
  25404. +
  25405. +#else
  25406. +
  25407. +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
  25408. +
  25409. +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
  25410. +
  25411. +#endif
  25412. +
  25413. +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
  25414. +
  25415. +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
  25416. +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
  25417. +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
  25418. +
  25419. +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
  25420. + { UpdateBit0(p); mi <<= 1; A0; } else \
  25421. + { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
  25422. +
  25423. +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
  25424. +
  25425. +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
  25426. + { int i = numLevels; res = 1; \
  25427. + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
  25428. + res -= (1 << numLevels); }
  25429. +
  25430. +
  25431. +#define kNumPosBitsMax 4
  25432. +#define kNumPosStatesMax (1 << kNumPosBitsMax)
  25433. +
  25434. +#define kLenNumLowBits 3
  25435. +#define kLenNumLowSymbols (1 << kLenNumLowBits)
  25436. +#define kLenNumMidBits 3
  25437. +#define kLenNumMidSymbols (1 << kLenNumMidBits)
  25438. +#define kLenNumHighBits 8
  25439. +#define kLenNumHighSymbols (1 << kLenNumHighBits)
  25440. +
  25441. +#define LenChoice 0
  25442. +#define LenChoice2 (LenChoice + 1)
  25443. +#define LenLow (LenChoice2 + 1)
  25444. +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
  25445. +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
  25446. +#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
  25447. +
  25448. +
  25449. +#define kNumStates 12
  25450. +#define kNumLitStates 7
  25451. +
  25452. +#define kStartPosModelIndex 4
  25453. +#define kEndPosModelIndex 14
  25454. +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
  25455. +
  25456. +#define kNumPosSlotBits 6
  25457. +#define kNumLenToPosStates 4
  25458. +
  25459. +#define kNumAlignBits 4
  25460. +#define kAlignTableSize (1 << kNumAlignBits)
  25461. +
  25462. +#define kMatchMinLen 2
  25463. +
  25464. +#define IsMatch 0
  25465. +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
  25466. +#define IsRepG0 (IsRep + kNumStates)
  25467. +#define IsRepG1 (IsRepG0 + kNumStates)
  25468. +#define IsRepG2 (IsRepG1 + kNumStates)
  25469. +#define IsRep0Long (IsRepG2 + kNumStates)
  25470. +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
  25471. +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
  25472. +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
  25473. +#define LenCoder (Align + kAlignTableSize)
  25474. +#define RepLenCoder (LenCoder + kNumLenProbs)
  25475. +#define Literal (RepLenCoder + kNumLenProbs)
  25476. +
  25477. +#if Literal != LZMA_BASE_SIZE
  25478. +StopCompilingDueBUG
  25479. +#endif
  25480. +
  25481. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
  25482. +{
  25483. + unsigned char prop0;
  25484. + if (size < LZMA_PROPERTIES_SIZE)
  25485. + return LZMA_RESULT_DATA_ERROR;
  25486. + prop0 = propsData[0];
  25487. + if (prop0 >= (9 * 5 * 5))
  25488. + return LZMA_RESULT_DATA_ERROR;
  25489. + {
  25490. + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
  25491. + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
  25492. + propsRes->lc = prop0;
  25493. + /*
  25494. + unsigned char remainder = (unsigned char)(prop0 / 9);
  25495. + propsRes->lc = prop0 % 9;
  25496. + propsRes->pb = remainder / 5;
  25497. + propsRes->lp = remainder % 5;
  25498. + */
  25499. + }
  25500. +
  25501. + #ifdef _LZMA_OUT_READ
  25502. + {
  25503. + int i;
  25504. + propsRes->DictionarySize = 0;
  25505. + for (i = 0; i < 4; i++)
  25506. + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
  25507. + if (propsRes->DictionarySize == 0)
  25508. + propsRes->DictionarySize = 1;
  25509. + }
  25510. + #endif
  25511. + return LZMA_RESULT_OK;
  25512. +}
  25513. +
  25514. +#define kLzmaStreamWasFinishedId (-1)
  25515. +
  25516. +int LzmaDecode(CLzmaDecoderState *vs,
  25517. + #ifdef _LZMA_IN_CB
  25518. + ILzmaInCallback *InCallback,
  25519. + #else
  25520. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  25521. + #endif
  25522. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
  25523. +{
  25524. + CProb *p = vs->Probs;
  25525. + SizeT nowPos = 0;
  25526. + Byte previousByte = 0;
  25527. + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
  25528. + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
  25529. + int lc = vs->Properties.lc;
  25530. +
  25531. + #ifdef _LZMA_OUT_READ
  25532. +
  25533. + UInt32 Range = vs->Range;
  25534. + UInt32 Code = vs->Code;
  25535. + #ifdef _LZMA_IN_CB
  25536. + const Byte *Buffer = vs->Buffer;
  25537. + const Byte *BufferLim = vs->BufferLim;
  25538. + #else
  25539. + const Byte *Buffer = inStream;
  25540. + const Byte *BufferLim = inStream + inSize;
  25541. + #endif
  25542. + int state = vs->State;
  25543. + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
  25544. + int len = vs->RemainLen;
  25545. + UInt32 globalPos = vs->GlobalPos;
  25546. + UInt32 distanceLimit = vs->DistanceLimit;
  25547. +
  25548. + Byte *dictionary = vs->Dictionary;
  25549. + UInt32 dictionarySize = vs->Properties.DictionarySize;
  25550. + UInt32 dictionaryPos = vs->DictionaryPos;
  25551. +
  25552. + Byte tempDictionary[4];
  25553. +
  25554. + #ifndef _LZMA_IN_CB
  25555. + *inSizeProcessed = 0;
  25556. + #endif
  25557. + *outSizeProcessed = 0;
  25558. + if (len == kLzmaStreamWasFinishedId)
  25559. + return LZMA_RESULT_OK;
  25560. +
  25561. + if (dictionarySize == 0)
  25562. + {
  25563. + dictionary = tempDictionary;
  25564. + dictionarySize = 1;
  25565. + tempDictionary[0] = vs->TempDictionary[0];
  25566. + }
  25567. +
  25568. + if (len == kLzmaNeedInitId)
  25569. + {
  25570. + {
  25571. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  25572. + UInt32 i;
  25573. + for (i = 0; i < numProbs; i++)
  25574. + p[i] = kBitModelTotal >> 1;
  25575. + rep0 = rep1 = rep2 = rep3 = 1;
  25576. + state = 0;
  25577. + globalPos = 0;
  25578. + distanceLimit = 0;
  25579. + dictionaryPos = 0;
  25580. + dictionary[dictionarySize - 1] = 0;
  25581. + #ifdef _LZMA_IN_CB
  25582. + RC_INIT;
  25583. + #else
  25584. + RC_INIT(inStream, inSize);
  25585. + #endif
  25586. + }
  25587. + len = 0;
  25588. + }
  25589. + while(len != 0 && nowPos < outSize)
  25590. + {
  25591. + UInt32 pos = dictionaryPos - rep0;
  25592. + if (pos >= dictionarySize)
  25593. + pos += dictionarySize;
  25594. + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
  25595. + if (++dictionaryPos == dictionarySize)
  25596. + dictionaryPos = 0;
  25597. + len--;
  25598. + }
  25599. + if (dictionaryPos == 0)
  25600. + previousByte = dictionary[dictionarySize - 1];
  25601. + else
  25602. + previousByte = dictionary[dictionaryPos - 1];
  25603. +
  25604. + #else /* if !_LZMA_OUT_READ */
  25605. +
  25606. + int state = 0;
  25607. + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
  25608. + int len = 0;
  25609. + const Byte *Buffer;
  25610. + const Byte *BufferLim;
  25611. + UInt32 Range;
  25612. + UInt32 Code;
  25613. +
  25614. + #ifndef _LZMA_IN_CB
  25615. + *inSizeProcessed = 0;
  25616. + #endif
  25617. + *outSizeProcessed = 0;
  25618. +
  25619. + {
  25620. + UInt32 i;
  25621. + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
  25622. + for (i = 0; i < numProbs; i++)
  25623. + p[i] = kBitModelTotal >> 1;
  25624. + }
  25625. +
  25626. + #ifdef _LZMA_IN_CB
  25627. + RC_INIT;
  25628. + #else
  25629. + RC_INIT(inStream, inSize);
  25630. + #endif
  25631. +
  25632. + #endif /* _LZMA_OUT_READ */
  25633. +
  25634. + while(nowPos < outSize)
  25635. + {
  25636. + CProb *prob;
  25637. + UInt32 bound;
  25638. + int posState = (int)(
  25639. + (nowPos
  25640. + #ifdef _LZMA_OUT_READ
  25641. + + globalPos
  25642. + #endif
  25643. + )
  25644. + & posStateMask);
  25645. +
  25646. + prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
  25647. + IfBit0(prob)
  25648. + {
  25649. + int symbol = 1;
  25650. + UpdateBit0(prob)
  25651. + prob = p + Literal + (LZMA_LIT_SIZE *
  25652. + (((
  25653. + (nowPos
  25654. + #ifdef _LZMA_OUT_READ
  25655. + + globalPos
  25656. + #endif
  25657. + )
  25658. + & literalPosMask) << lc) + (previousByte >> (8 - lc))));
  25659. +
  25660. + if (state >= kNumLitStates)
  25661. + {
  25662. + int matchByte;
  25663. + #ifdef _LZMA_OUT_READ
  25664. + UInt32 pos = dictionaryPos - rep0;
  25665. + if (pos >= dictionarySize)
  25666. + pos += dictionarySize;
  25667. + matchByte = dictionary[pos];
  25668. + #else
  25669. + matchByte = outStream[nowPos - rep0];
  25670. + #endif
  25671. + do
  25672. + {
  25673. + int bit;
  25674. + CProb *probLit;
  25675. + matchByte <<= 1;
  25676. + bit = (matchByte & 0x100);
  25677. + probLit = prob + 0x100 + bit + symbol;
  25678. + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
  25679. + }
  25680. + while (symbol < 0x100);
  25681. + }
  25682. + while (symbol < 0x100)
  25683. + {
  25684. + CProb *probLit = prob + symbol;
  25685. + RC_GET_BIT(probLit, symbol)
  25686. + }
  25687. + previousByte = (Byte)symbol;
  25688. +
  25689. + outStream[nowPos++] = previousByte;
  25690. + #ifdef _LZMA_OUT_READ
  25691. + if (distanceLimit < dictionarySize)
  25692. + distanceLimit++;
  25693. +
  25694. + dictionary[dictionaryPos] = previousByte;
  25695. + if (++dictionaryPos == dictionarySize)
  25696. + dictionaryPos = 0;
  25697. + #endif
  25698. + if (state < 4) state = 0;
  25699. + else if (state < 10) state -= 3;
  25700. + else state -= 6;
  25701. + }
  25702. + else
  25703. + {
  25704. + UpdateBit1(prob);
  25705. + prob = p + IsRep + state;
  25706. + IfBit0(prob)
  25707. + {
  25708. + UpdateBit0(prob);
  25709. + rep3 = rep2;
  25710. + rep2 = rep1;
  25711. + rep1 = rep0;
  25712. + state = state < kNumLitStates ? 0 : 3;
  25713. + prob = p + LenCoder;
  25714. + }
  25715. + else
  25716. + {
  25717. + UpdateBit1(prob);
  25718. + prob = p + IsRepG0 + state;
  25719. + IfBit0(prob)
  25720. + {
  25721. + UpdateBit0(prob);
  25722. + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
  25723. + IfBit0(prob)
  25724. + {
  25725. + #ifdef _LZMA_OUT_READ
  25726. + UInt32 pos;
  25727. + #endif
  25728. + UpdateBit0(prob);
  25729. +
  25730. + #ifdef _LZMA_OUT_READ
  25731. + if (distanceLimit == 0)
  25732. + #else
  25733. + if (nowPos == 0)
  25734. + #endif
  25735. + return LZMA_RESULT_DATA_ERROR;
  25736. +
  25737. + state = state < kNumLitStates ? 9 : 11;
  25738. + #ifdef _LZMA_OUT_READ
  25739. + pos = dictionaryPos - rep0;
  25740. + if (pos >= dictionarySize)
  25741. + pos += dictionarySize;
  25742. + previousByte = dictionary[pos];
  25743. + dictionary[dictionaryPos] = previousByte;
  25744. + if (++dictionaryPos == dictionarySize)
  25745. + dictionaryPos = 0;
  25746. + #else
  25747. + previousByte = outStream[nowPos - rep0];
  25748. + #endif
  25749. + outStream[nowPos++] = previousByte;
  25750. + #ifdef _LZMA_OUT_READ
  25751. + if (distanceLimit < dictionarySize)
  25752. + distanceLimit++;
  25753. + #endif
  25754. +
  25755. + continue;
  25756. + }
  25757. + else
  25758. + {
  25759. + UpdateBit1(prob);
  25760. + }
  25761. + }
  25762. + else
  25763. + {
  25764. + UInt32 distance;
  25765. + UpdateBit1(prob);
  25766. + prob = p + IsRepG1 + state;
  25767. + IfBit0(prob)
  25768. + {
  25769. + UpdateBit0(prob);
  25770. + distance = rep1;
  25771. + }
  25772. + else
  25773. + {
  25774. + UpdateBit1(prob);
  25775. + prob = p + IsRepG2 + state;
  25776. + IfBit0(prob)
  25777. + {
  25778. + UpdateBit0(prob);
  25779. + distance = rep2;
  25780. + }
  25781. + else
  25782. + {
  25783. + UpdateBit1(prob);
  25784. + distance = rep3;
  25785. + rep3 = rep2;
  25786. + }
  25787. + rep2 = rep1;
  25788. + }
  25789. + rep1 = rep0;
  25790. + rep0 = distance;
  25791. + }
  25792. + state = state < kNumLitStates ? 8 : 11;
  25793. + prob = p + RepLenCoder;
  25794. + }
  25795. + {
  25796. + int numBits, offset;
  25797. + CProb *probLen = prob + LenChoice;
  25798. + IfBit0(probLen)
  25799. + {
  25800. + UpdateBit0(probLen);
  25801. + probLen = prob + LenLow + (posState << kLenNumLowBits);
  25802. + offset = 0;
  25803. + numBits = kLenNumLowBits;
  25804. + }
  25805. + else
  25806. + {
  25807. + UpdateBit1(probLen);
  25808. + probLen = prob + LenChoice2;
  25809. + IfBit0(probLen)
  25810. + {
  25811. + UpdateBit0(probLen);
  25812. + probLen = prob + LenMid + (posState << kLenNumMidBits);
  25813. + offset = kLenNumLowSymbols;
  25814. + numBits = kLenNumMidBits;
  25815. + }
  25816. + else
  25817. + {
  25818. + UpdateBit1(probLen);
  25819. + probLen = prob + LenHigh;
  25820. + offset = kLenNumLowSymbols + kLenNumMidSymbols;
  25821. + numBits = kLenNumHighBits;
  25822. + }
  25823. + }
  25824. + RangeDecoderBitTreeDecode(probLen, numBits, len);
  25825. + len += offset;
  25826. + }
  25827. +
  25828. + if (state < 4)
  25829. + {
  25830. + int posSlot;
  25831. + state += kNumLitStates;
  25832. + prob = p + PosSlot +
  25833. + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
  25834. + kNumPosSlotBits);
  25835. + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
  25836. + if (posSlot >= kStartPosModelIndex)
  25837. + {
  25838. + int numDirectBits = ((posSlot >> 1) - 1);
  25839. + rep0 = (2 | ((UInt32)posSlot & 1));
  25840. + if (posSlot < kEndPosModelIndex)
  25841. + {
  25842. + rep0 <<= numDirectBits;
  25843. + prob = p + SpecPos + rep0 - posSlot - 1;
  25844. + }
  25845. + else
  25846. + {
  25847. + numDirectBits -= kNumAlignBits;
  25848. + do
  25849. + {
  25850. + RC_NORMALIZE
  25851. + Range >>= 1;
  25852. + rep0 <<= 1;
  25853. + if (Code >= Range)
  25854. + {
  25855. + Code -= Range;
  25856. + rep0 |= 1;
  25857. + }
  25858. + }
  25859. + while (--numDirectBits != 0);
  25860. + prob = p + Align;
  25861. + rep0 <<= kNumAlignBits;
  25862. + numDirectBits = kNumAlignBits;
  25863. + }
  25864. + {
  25865. + int i = 1;
  25866. + int mi = 1;
  25867. + do
  25868. + {
  25869. + CProb *prob3 = prob + mi;
  25870. + RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
  25871. + i <<= 1;
  25872. + }
  25873. + while(--numDirectBits != 0);
  25874. + }
  25875. + }
  25876. + else
  25877. + rep0 = posSlot;
  25878. + if (++rep0 == (UInt32)(0))
  25879. + {
  25880. + /* it's for stream version */
  25881. + len = kLzmaStreamWasFinishedId;
  25882. + break;
  25883. + }
  25884. + }
  25885. +
  25886. + len += kMatchMinLen;
  25887. + #ifdef _LZMA_OUT_READ
  25888. + if (rep0 > distanceLimit)
  25889. + #else
  25890. + if (rep0 > nowPos)
  25891. + #endif
  25892. + return LZMA_RESULT_DATA_ERROR;
  25893. +
  25894. + #ifdef _LZMA_OUT_READ
  25895. + if (dictionarySize - distanceLimit > (UInt32)len)
  25896. + distanceLimit += len;
  25897. + else
  25898. + distanceLimit = dictionarySize;
  25899. + #endif
  25900. +
  25901. + do
  25902. + {
  25903. + #ifdef _LZMA_OUT_READ
  25904. + UInt32 pos = dictionaryPos - rep0;
  25905. + if (pos >= dictionarySize)
  25906. + pos += dictionarySize;
  25907. + previousByte = dictionary[pos];
  25908. + dictionary[dictionaryPos] = previousByte;
  25909. + if (++dictionaryPos == dictionarySize)
  25910. + dictionaryPos = 0;
  25911. + #else
  25912. + previousByte = outStream[nowPos - rep0];
  25913. + #endif
  25914. + len--;
  25915. + outStream[nowPos++] = previousByte;
  25916. + }
  25917. + while(len != 0 && nowPos < outSize);
  25918. + }
  25919. + }
  25920. + RC_NORMALIZE;
  25921. +
  25922. + #ifdef _LZMA_OUT_READ
  25923. + vs->Range = Range;
  25924. + vs->Code = Code;
  25925. + vs->DictionaryPos = dictionaryPos;
  25926. + vs->GlobalPos = globalPos + (UInt32)nowPos;
  25927. + vs->DistanceLimit = distanceLimit;
  25928. + vs->Reps[0] = rep0;
  25929. + vs->Reps[1] = rep1;
  25930. + vs->Reps[2] = rep2;
  25931. + vs->Reps[3] = rep3;
  25932. + vs->State = state;
  25933. + vs->RemainLen = len;
  25934. + vs->TempDictionary[0] = tempDictionary[0];
  25935. + #endif
  25936. +
  25937. + #ifdef _LZMA_IN_CB
  25938. + vs->Buffer = Buffer;
  25939. + vs->BufferLim = BufferLim;
  25940. + #else
  25941. + *inSizeProcessed = (SizeT)(Buffer - inStream);
  25942. + #endif
  25943. + *outSizeProcessed = nowPos;
  25944. + return LZMA_RESULT_OK;
  25945. +}
  25946. diff --git a/init/LzmaDecode.h b/init/LzmaDecode.h
  25947. new file mode 100644
  25948. index 0000000..213062a
  25949. --- /dev/null
  25950. +++ b/init/LzmaDecode.h
  25951. @@ -0,0 +1,131 @@
  25952. +/*
  25953. + LzmaDecode.h
  25954. + LZMA Decoder interface
  25955. +
  25956. + LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
  25957. + http://www.7-zip.org/
  25958. +
  25959. + LZMA SDK is licensed under two licenses:
  25960. + 1) GNU Lesser General Public License (GNU LGPL)
  25961. + 2) Common Public License (CPL)
  25962. + It means that you can select one of these two licenses and
  25963. + follow rules of that license.
  25964. +
  25965. + SPECIAL EXCEPTION:
  25966. + Igor Pavlov, as the author of this code, expressly permits you to
  25967. + statically or dynamically link your code (or bind by name) to the
  25968. + interfaces of this file without subjecting your linked code to the
  25969. + terms of the CPL or GNU LGPL. Any modifications or additions
  25970. + to this file, however, are subject to the LGPL or CPL terms.
  25971. +*/
  25972. +
  25973. +#ifndef __LZMADECODE_H
  25974. +#define __LZMADECODE_H
  25975. +
  25976. +/* #define _LZMA_IN_CB */
  25977. +/* Use callback for input data */
  25978. +
  25979. +/* #define _LZMA_OUT_READ */
  25980. +/* Use read function for output data */
  25981. +
  25982. +/* #define _LZMA_PROB32 */
  25983. +/* It can increase speed on some 32-bit CPUs,
  25984. + but memory usage will be doubled in that case */
  25985. +
  25986. +/* #define _LZMA_LOC_OPT */
  25987. +/* Enable local speed optimizations inside code */
  25988. +
  25989. +/* #define _LZMA_SYSTEM_SIZE_T */
  25990. +/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
  25991. +
  25992. +#ifndef UInt32
  25993. +#ifdef _LZMA_UINT32_IS_ULONG
  25994. +#define UInt32 unsigned long
  25995. +#else
  25996. +#define UInt32 unsigned int
  25997. +#endif
  25998. +#endif
  25999. +
  26000. +#ifndef SizeT
  26001. +#ifdef _LZMA_SYSTEM_SIZE_T
  26002. +#include <stddef.h>
  26003. +#define SizeT size_t
  26004. +#else
  26005. +#define SizeT UInt32
  26006. +#endif
  26007. +#endif
  26008. +
  26009. +#ifdef _LZMA_PROB32
  26010. +#define CProb UInt32
  26011. +#else
  26012. +#define CProb unsigned short
  26013. +#endif
  26014. +
  26015. +#define LZMA_RESULT_OK 0
  26016. +#define LZMA_RESULT_DATA_ERROR 1
  26017. +
  26018. +#ifdef _LZMA_IN_CB
  26019. +typedef struct _ILzmaInCallback
  26020. +{
  26021. + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
  26022. +} ILzmaInCallback;
  26023. +#endif
  26024. +
  26025. +#define LZMA_BASE_SIZE 1846
  26026. +#define LZMA_LIT_SIZE 768
  26027. +
  26028. +#define LZMA_PROPERTIES_SIZE 5
  26029. +
  26030. +typedef struct _CLzmaProperties
  26031. +{
  26032. + int lc;
  26033. + int lp;
  26034. + int pb;
  26035. + #ifdef _LZMA_OUT_READ
  26036. + UInt32 DictionarySize;
  26037. + #endif
  26038. +}CLzmaProperties;
  26039. +
  26040. +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
  26041. +
  26042. +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
  26043. +
  26044. +#define kLzmaNeedInitId (-2)
  26045. +
  26046. +typedef struct _CLzmaDecoderState
  26047. +{
  26048. + CLzmaProperties Properties;
  26049. + CProb *Probs;
  26050. +
  26051. + #ifdef _LZMA_IN_CB
  26052. + const unsigned char *Buffer;
  26053. + const unsigned char *BufferLim;
  26054. + #endif
  26055. +
  26056. + #ifdef _LZMA_OUT_READ
  26057. + unsigned char *Dictionary;
  26058. + UInt32 Range;
  26059. + UInt32 Code;
  26060. + UInt32 DictionaryPos;
  26061. + UInt32 GlobalPos;
  26062. + UInt32 DistanceLimit;
  26063. + UInt32 Reps[4];
  26064. + int State;
  26065. + int RemainLen;
  26066. + unsigned char TempDictionary[4];
  26067. + #endif
  26068. +} CLzmaDecoderState;
  26069. +
  26070. +#ifdef _LZMA_OUT_READ
  26071. +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
  26072. +#endif
  26073. +
  26074. +int LzmaDecode(CLzmaDecoderState *vs,
  26075. + #ifdef _LZMA_IN_CB
  26076. + ILzmaInCallback *inCallback,
  26077. + #else
  26078. + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
  26079. + #endif
  26080. + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
  26081. +
  26082. +#endif
  26083. diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
  26084. index ed652f4..5fd1ec5 100644
  26085. --- a/init/do_mounts_rd.c
  26086. +++ b/init/do_mounts_rd.c
  26087. @@ -5,7 +5,9 @@
  26088. #include <linux/ext2_fs.h>
  26089. #include <linux/romfs_fs.h>
  26090. #include <linux/cramfs_fs.h>
  26091. +#include <linux/squashfs_fs.h>
  26092. #include <linux/initrd.h>
  26093. +#include <linux/vmalloc.h>
  26094. #include <linux/string.h>
  26095. #include "do_mounts.h"
  26096. @@ -31,6 +33,9 @@ static int __init ramdisk_start_setup(char *str)
  26097. __setup("ramdisk_start=", ramdisk_start_setup);
  26098. static int __init crd_load(int in_fd, int out_fd);
  26099. +#ifdef CONFIG_LZMA_INITRD
  26100. +static int __init lzma_rd_load(int in_fd, int out_fd);
  26101. +#endif
  26102. /*
  26103. * This routine tries to find a RAM disk image to load, and returns the
  26104. @@ -39,6 +44,7 @@ static int __init crd_load(int in_fd, int out_fd);
  26105. * numbers could not be found.
  26106. *
  26107. * We currently check for the following magic numbers:
  26108. + * squashfs
  26109. * minix
  26110. * ext2
  26111. * romfs
  26112. @@ -53,6 +59,7 @@ identify_ramdisk_image(int fd, int start_block)
  26113. struct ext2_super_block *ext2sb;
  26114. struct romfs_super_block *romfsb;
  26115. struct cramfs_super *cramfsb;
  26116. + struct squashfs_super_block *squashfsb;
  26117. int nblocks = -1;
  26118. unsigned char *buf;
  26119. @@ -64,6 +71,7 @@ identify_ramdisk_image(int fd, int start_block)
  26120. ext2sb = (struct ext2_super_block *) buf;
  26121. romfsb = (struct romfs_super_block *) buf;
  26122. cramfsb = (struct cramfs_super *) buf;
  26123. + squashfsb = (struct squashfs_super_block *) buf;
  26124. memset(buf, 0xe5, size);
  26125. /*
  26126. @@ -82,6 +90,17 @@ identify_ramdisk_image(int fd, int start_block)
  26127. nblocks = 0;
  26128. goto done;
  26129. }
  26130. + /*
  26131. + * handle lzma compressed initrd, returns nblocks=1 as indication
  26132. + */
  26133. + if( buf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0 && buf[11] == 0
  26134. + && buf[12] == 0 )
  26135. + {
  26136. + printk( KERN_NOTICE "RAMDISK: LZMA image found at block %d\n",
  26137. + start_block);
  26138. + nblocks = 1; // just a convenient return flag
  26139. + goto done;
  26140. + }
  26141. /* romfs is at block zero too */
  26142. if (romfsb->word0 == ROMSB_WORD0 &&
  26143. @@ -101,6 +120,18 @@ identify_ramdisk_image(int fd, int start_block)
  26144. goto done;
  26145. }
  26146. + /* squashfs is at block zero too */
  26147. + if (squashfsb->s_magic == SQUASHFS_MAGIC) {
  26148. + printk(KERN_NOTICE
  26149. + "RAMDISK: squashfs filesystem found at block %d\n",
  26150. + start_block);
  26151. + if (squashfsb->s_major < 3)
  26152. + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
  26153. + else
  26154. + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
  26155. + goto done;
  26156. + }
  26157. +
  26158. /*
  26159. * Read block 1 to test for minix and ext2 superblock
  26160. */
  26161. @@ -172,7 +203,22 @@ int __init rd_load_image(char *from)
  26162. #endif
  26163. goto done;
  26164. }
  26165. -
  26166. +#ifdef CONFIG_LZMA_INITRD
  26167. + /*
  26168. + * handle lzma compressed image
  26169. + */
  26170. + if ( nblocks == 1 )
  26171. + {
  26172. + nblocks = 0;
  26173. + if ( lzma_rd_load(in_fd, out_fd) == 0 )
  26174. + {
  26175. + printk("\nLZMA initrd loaded successfully\n");
  26176. + goto successful_load;
  26177. + }
  26178. + printk(KERN_NOTICE "LZMA initrd is not in the correct format\n");
  26179. + goto done;
  26180. + }
  26181. +#endif
  26182. /*
  26183. * NOTE NOTE: nblocks is not actually blocks but
  26184. * the number of kibibytes of data to load into a ramdisk.
  26185. @@ -393,6 +439,134 @@ static void __init error(char *x)
  26186. unzip_error = 1;
  26187. }
  26188. +#ifdef CONFIG_LZMA_INITRD
  26189. +#define _LZMA_IN_CB
  26190. +#define _LZMA_OUT_READ
  26191. +#include "LzmaDecode.h"
  26192. +#include "LzmaDecode.c"
  26193. +
  26194. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize);
  26195. +
  26196. +/*
  26197. + * Do the lzma decompression
  26198. + */
  26199. +static int __init lzma_rd_load(int in_fd, int out_fd)
  26200. +{
  26201. + unsigned int i;
  26202. + CLzmaDecoderState state;
  26203. + unsigned char* outputbuffer;
  26204. + unsigned int uncompressedSize = 0;
  26205. + unsigned char* p;
  26206. + unsigned int kBlockSize = 0x10000;
  26207. + unsigned int nowPos = 0;
  26208. + unsigned int outsizeProcessed = 0;
  26209. + int res;
  26210. + ILzmaInCallback callback;
  26211. +
  26212. + insize = 0; /* valid bytes in inbuf */
  26213. + inptr = 0; /* index of next byte to be processed in inbuf */
  26214. + exit_code = 0;
  26215. + crd_infd = in_fd;
  26216. + inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
  26217. + if (inbuf == 0)
  26218. + {
  26219. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma input buffer\n");
  26220. + return -1;
  26221. + }
  26222. +
  26223. + callback.Read = read_byte;
  26224. +
  26225. + /* lzma args */
  26226. + i = get_byte();
  26227. + state.Properties.lc = i % 9, i = i / 9;
  26228. + state.Properties.lp = i % 5, state.Properties.pb = i / 5;
  26229. +
  26230. + /* read dictionary size */
  26231. + p = (char*)&state.Properties.DictionarySize;
  26232. + for (i = 0; i < 4; i++)
  26233. + *p++ = get_byte();
  26234. +
  26235. + /* get uncompressedSize */
  26236. + p= (char*)&uncompressedSize;
  26237. + for (i = 0; i < 4; i++)
  26238. + *p++ = get_byte();
  26239. +
  26240. + /* skip big file */
  26241. + for (i = 0; i < 4; i++)
  26242. + get_byte();
  26243. +
  26244. + printk( KERN_NOTICE "RAMDISK: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
  26245. + state.Properties.lc, state.Properties.lp, state.Properties.pb, state.Properties.DictionarySize, uncompressedSize);
  26246. + outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
  26247. + if (outputbuffer == 0) {
  26248. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma output buffer\n");
  26249. + return -1;
  26250. + }
  26251. +
  26252. + state.Probs = (CProb*)kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
  26253. + if ( state.Probs == 0) {
  26254. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma workspace\n");
  26255. + return -1;
  26256. + }
  26257. +
  26258. +#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
  26259. + state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
  26260. +#else
  26261. + state.Dictionary = vmalloc( state.Properties.DictionarySize);
  26262. +#endif
  26263. + if ( state.Dictionary == 0) {
  26264. + printk(KERN_ERR "RAMDISK: Couldn't allocate lzma dictionary\n");
  26265. + return -1;
  26266. + }
  26267. +
  26268. + printk( KERN_NOTICE "LZMA initrd by Ming-Ching Tiew <mctiew@yahoo.com> " );
  26269. +
  26270. + LzmaDecoderInit( &state );
  26271. +
  26272. + for( nowPos =0; nowPos < uncompressedSize ; )
  26273. + {
  26274. + UInt32 blockSize = uncompressedSize - nowPos;
  26275. + if( blockSize > kBlockSize)
  26276. + blockSize = kBlockSize;
  26277. + res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
  26278. + if( res != 0 ) {
  26279. + printk( KERN_ERR "RAMDISK: Lzma decode failure\n");
  26280. + return -1;
  26281. + }
  26282. + if( outsizeProcessed == 0 )
  26283. + {
  26284. + uncompressedSize = nowPos;
  26285. + printk( KERN_NOTICE "RAMDISK nowPos=%d, uncompressedSize=%d\n",
  26286. + nowPos, uncompressedSize );
  26287. + break;
  26288. + }
  26289. + sys_write(out_fd, outputbuffer, outsizeProcessed );
  26290. + nowPos += outsizeProcessed;
  26291. + printk( ".");
  26292. + }
  26293. +
  26294. +#ifdef CONFIG_LZMA_INITRD_KMALLOC_ONLY
  26295. + kfree(state.Dictionary);
  26296. +#else
  26297. + vfree(state.Dictionary);
  26298. +#endif
  26299. + kfree(inbuf);
  26300. + kfree(outputbuffer);
  26301. + kfree(state.Probs);
  26302. + return 0;
  26303. +}
  26304. +
  26305. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
  26306. +{
  26307. + static unsigned char val;
  26308. + *bufferSize = 1;
  26309. + val = get_byte();
  26310. + *buffer = &val;
  26311. + return LZMA_RESULT_OK;
  26312. +}
  26313. +
  26314. +#endif /*CONFIG_LZMA_INITRD*/
  26315. +
  26316. static int __init crd_load(int in_fd, int out_fd)
  26317. {
  26318. int result;
  26319. diff --git a/init/initramfs.c b/init/initramfs.c
  26320. index 00eff7a..30d32a2 100644
  26321. --- a/init/initramfs.c
  26322. +++ b/init/initramfs.c
  26323. @@ -6,6 +6,7 @@
  26324. #include <linux/delay.h>
  26325. #include <linux/string.h>
  26326. #include <linux/syscalls.h>
  26327. +#include <linux/vmalloc.h>
  26328. static __initdata char *message;
  26329. static void __init error(char *x)
  26330. @@ -441,6 +442,118 @@ static void __init flush_window(void)
  26331. outcnt = 0;
  26332. }
  26333. +#ifdef CONFIG_LZMA_INITRAM_FS
  26334. +#define _LZMA_IN_CB
  26335. +#define _LZMA_OUT_READ
  26336. +#include "LzmaDecode.h"
  26337. +#ifndef CONFIG_LZMA_INITRD
  26338. + #include "LzmaDecode.c"
  26339. +#endif
  26340. +static int read_byte(void *object, const unsigned char **buffer, SizeT *bufferSize)
  26341. +{
  26342. + static unsigned char val;
  26343. + *bufferSize = 1;
  26344. + val = get_byte();
  26345. + *buffer = &val;
  26346. + return LZMA_RESULT_OK;
  26347. +}
  26348. +
  26349. +static int __init lzma_unzip(void)
  26350. +{
  26351. + unsigned int i;
  26352. + CLzmaDecoderState state;
  26353. + unsigned char* outputbuffer;
  26354. + unsigned int uncompressedSize = 0;
  26355. + unsigned char* p;
  26356. + unsigned int kBlockSize = 0x10000;
  26357. + unsigned int nowPos = 0;
  26358. + unsigned int outsizeProcessed = 0;
  26359. + int res;
  26360. + ILzmaInCallback callback;
  26361. +
  26362. + callback.Read = read_byte;
  26363. +
  26364. + // lzma args
  26365. + i = get_byte();
  26366. + state.Properties.lc = i % 9, i = i / 9;
  26367. + state.Properties.lp = i % 5, state.Properties.pb = i / 5;
  26368. +
  26369. + // read dictionary size
  26370. + p = (char*)&state.Properties.DictionarySize;
  26371. + for (i = 0; i < 4; i++)
  26372. + *p++ = get_byte();
  26373. +
  26374. + // get uncompressedSize
  26375. + p= (char*)&uncompressedSize;
  26376. + for (i = 0; i < 4; i++)
  26377. + *p++ = get_byte();
  26378. +
  26379. + // skip big file
  26380. + for (i = 0; i < 4; i++)
  26381. + get_byte();
  26382. +
  26383. + printk( KERN_NOTICE "initramfs: LZMA lc=%d,lp=%d,pb=%d,dictSize=%d,origSize=%d\n",
  26384. + state.Properties.lc,state.Properties.lp,state.Properties.pb,state.Properties.DictionarySize, uncompressedSize);
  26385. + outputbuffer = kmalloc(kBlockSize, GFP_KERNEL);
  26386. + if (outputbuffer == 0) {
  26387. + printk(KERN_ERR "initramfs: Couldn't allocate lzma output buffer\n");
  26388. + return -1;
  26389. + }
  26390. +
  26391. + state.Probs = (CProb*) kmalloc( LzmaGetNumProbs(&state.Properties)*sizeof(CProb), GFP_KERNEL);
  26392. + if ( state.Probs == 0) {
  26393. + printk(KERN_ERR "initramfs: Couldn't allocate lzma workspace\n");
  26394. + return -1;
  26395. + }
  26396. +
  26397. +#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
  26398. + state.Dictionary = kmalloc( state.Properties.DictionarySize, GFP_KERNEL);
  26399. +#else
  26400. + state.Dictionary = vmalloc( state.Properties.DictionarySize);
  26401. +#endif
  26402. + if ( state.Dictionary == 0) {
  26403. + printk(KERN_ERR "initramfs: Couldn't allocate lzma dictionary\n");
  26404. + return -1;
  26405. + }
  26406. +
  26407. + printk( KERN_NOTICE "LZMA initramfs by Ming-Ching Tiew <mctiew@yahoo.com> " );
  26408. +
  26409. + LzmaDecoderInit( &state );
  26410. +
  26411. + for( nowPos =0; nowPos < uncompressedSize ; )
  26412. + {
  26413. + UInt32 blockSize = uncompressedSize - nowPos;
  26414. + if( blockSize > kBlockSize)
  26415. + blockSize = kBlockSize;
  26416. + res = LzmaDecode( &state, &callback, outputbuffer, blockSize, &outsizeProcessed);
  26417. + if( res != 0 ) {
  26418. + panic( KERN_ERR "initramfs: Lzma decode failure\n");
  26419. + return -1;
  26420. + }
  26421. + if( outsizeProcessed == 0 )
  26422. + {
  26423. + uncompressedSize = nowPos;
  26424. + printk( KERN_NOTICE "initramfs: nowPos=%d, uncompressedSize=%d\n",
  26425. + nowPos, uncompressedSize );
  26426. + break;
  26427. + }
  26428. + flush_buffer(outputbuffer, outsizeProcessed);
  26429. + nowPos += outsizeProcessed;
  26430. + printk( ".");
  26431. + }
  26432. +
  26433. +#ifdef CONFIG_LZMA_INITRAM_FS_KMALLOC_ONLY
  26434. + kfree(state.Dictionary);
  26435. +#else
  26436. + vfree(state.Dictionary);
  26437. +#endif
  26438. + kfree(outputbuffer);
  26439. + kfree(state.Probs);
  26440. + return 0;
  26441. +}
  26442. +
  26443. +#endif /*CONFIG LZMA_INITRAM_FS*/
  26444. +
  26445. static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
  26446. {
  26447. int written;
  26448. @@ -475,12 +588,31 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
  26449. inptr = 0;
  26450. outcnt = 0; /* bytes in output buffer */
  26451. bytes_out = 0;
  26452. - crc = (ulg)0xffffffffL; /* shift register contents */
  26453. - makecrc();
  26454. - gunzip();
  26455. - if (state != Reset)
  26456. + if( inbuf[0] == 037 && ((inbuf[1] == 0213) || (inbuf[1] == 0236)))
  26457. + {
  26458. + printk( KERN_NOTICE "detected gzip initramfs\n");
  26459. + crc = (ulg)0xffffffffL; /* shift register contents */
  26460. + makecrc();
  26461. + gunzip();
  26462. + if (state != Reset)
  26463. error("junk in gzipped archive");
  26464. - this_header = saved_offset + inptr;
  26465. + }
  26466. +#ifdef CONFIG_LZMA_INITRAM_FS
  26467. + else if( inbuf[0] < 9 * 5 * 5 && buf[9] == 0 && buf[10] == 0
  26468. + && buf[11] == 0 && buf[12] == 0 )
  26469. + {
  26470. + printk( KERN_NOTICE "detected lzma initramfs\n");
  26471. + lzma_unzip();
  26472. + }
  26473. +#endif
  26474. + else
  26475. + {
  26476. + // skip forward ?
  26477. + crc = (ulg)0xffffffffL; /* shift register contents */
  26478. + makecrc();
  26479. + gunzip();
  26480. + }
  26481. + this_header = saved_offset + inptr;
  26482. buf += inptr;
  26483. len -= inptr;
  26484. }
  26485. diff --git a/kernel/Makefile b/kernel/Makefile
  26486. index ac6b27a..bd498a2 100644
  26487. --- a/kernel/Makefile
  26488. +++ b/kernel/Makefile
  26489. @@ -66,7 +66,7 @@ $(obj)/configs.o: $(obj)/config_data.h
  26490. # config_data.h contains the same information as ikconfig.h but gzipped.
  26491. # Info from config_data can be extracted from /proc/config*
  26492. targets += config_data.gz
  26493. -$(obj)/config_data.gz: .config FORCE
  26494. +$(obj)/config_data.gz: .miniconfig FORCE
  26495. $(call if_changed,gzip)
  26496. quiet_cmd_ikconfiggz = IKCFG $@
  26497. diff --git a/kernel/configs.c b/kernel/configs.c
  26498. index 8fa1fb2..c8407eb 100644
  26499. --- a/kernel/configs.c
  26500. +++ b/kernel/configs.c
  26501. @@ -88,7 +88,7 @@ static int __init ikconfig_init(void)
  26502. struct proc_dir_entry *entry;
  26503. /* create the current config file */
  26504. - entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
  26505. + entry = create_proc_entry("miniconfig.gz", S_IFREG | S_IRUGO,
  26506. &proc_root);
  26507. if (!entry)
  26508. return -ENOMEM;
  26509. @@ -104,7 +104,7 @@ static int __init ikconfig_init(void)
  26510. static void __exit ikconfig_cleanup(void)
  26511. {
  26512. - remove_proc_entry("config.gz", &proc_root);
  26513. + remove_proc_entry("miniconfig.gz", &proc_root);
  26514. }
  26515. module_init(ikconfig_init);
  26516. diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
  26517. index fe5c7db..a5150e6 100644
  26518. --- a/kernel/time/clocksource.c
  26519. +++ b/kernel/time/clocksource.c
  26520. @@ -85,8 +85,8 @@ static void clocksource_ratewd(struct clocksource *cs, int64_t delta)
  26521. if (delta > -WATCHDOG_TRESHOLD && delta < WATCHDOG_TRESHOLD)
  26522. return;
  26523. - printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
  26524. - cs->name, delta);
  26525. +/* printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
  26526. + cs->name, delta); */
  26527. cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
  26528. clocksource_change_rating(cs, 0);
  26529. cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
  26530. diff --git a/kernel/timer.c b/kernel/timer.c
  26531. index dd6c2c1..3a8f485 100644
  26532. --- a/kernel/timer.c
  26533. +++ b/kernel/timer.c
  26534. @@ -916,8 +916,8 @@ static void change_clocksource(void)
  26535. tick_clock_notify();
  26536. - printk(KERN_INFO "Time: %s clocksource has been installed.\n",
  26537. - clock->name);
  26538. +/* printk(KERN_INFO "Time: %s clocksource has been installed.\n",
  26539. + clock->name); */
  26540. }
  26541. #else
  26542. static inline void change_clocksource(void) { }
  26543. diff --git a/miniconfig.sh b/miniconfig.sh
  26544. new file mode 100755
  26545. index 0000000..28e7433
  26546. --- /dev/null
  26547. +++ b/miniconfig.sh
  26548. @@ -0,0 +1,2 @@
  26549. +#!/bin/sh -f
  26550. +make allnoconfig KCONFIG_ALLCONFIG=.miniconfig
  26551. diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
  26552. index fc498fe..e98172c 100644
  26553. --- a/scripts/Makefile.lib
  26554. +++ b/scripts/Makefile.lib
  26555. @@ -162,4 +162,9 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
  26556. quiet_cmd_gzip = GZIP $@
  26557. cmd_gzip = gzip -f -9 < $< > $@
  26558. +# LZMA
  26559. +#
  26560. +quiet_cmd_lzma = LZMA $@
  26561. +cmd_lzma = lzma e $< $@ -lc7 -lp0 -pb0 2>/dev/null
  26562. +
  26563. diff --git a/scripts/gen_lzma_initramfs_list.sh b/scripts/gen_lzma_initramfs_list.sh
  26564. new file mode 100644
  26565. index 0000000..be3ed6a
  26566. --- /dev/null
  26567. +++ b/scripts/gen_lzma_initramfs_list.sh
  26568. @@ -0,0 +1,292 @@
  26569. +#!/bin/bash
  26570. +# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
  26571. +# Copyright (c) 2006 Sam Ravnborg <sam@ravnborg.org>
  26572. +#
  26573. +# Released under the terms of the GNU GPL
  26574. +#
  26575. +# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
  26576. +# the cpio archive, and gzip to pack it.
  26577. +# The script may also be used to generate the inputfile used for gen_init_cpio
  26578. +# This script assumes that gen_init_cpio is located in usr/ directory
  26579. +
  26580. +# error out on errors
  26581. +set -e
  26582. +
  26583. +usage() {
  26584. +cat << EOF
  26585. +Usage:
  26586. +$0 [-o <file>] [-u <uid>] [-g <gid>] { -s | -d | <cpio_source>} ...
  26587. + -o <file> Create lzma initramfs file named <file> using
  26588. + gen_init_cpio and lzma
  26589. + -u <uid> User ID to map to user ID 0 (root).
  26590. + <uid> is only meaningful if <cpio_source>
  26591. + is a directory.
  26592. + -g <gid> Group ID to map to group ID 0 (root).
  26593. + <gid> is only meaningful if <cpio_source>
  26594. + is a directory.
  26595. + <cpio_source> File list or directory for cpio archive.
  26596. + If <cpio_source> is a .cpio file it will be used
  26597. + as direct input to initramfs.
  26598. + -s Create lzma file with small dictionary size
  26599. + -d Output the default cpio list.
  26600. +
  26601. +All options except -o and -l may be repeated and are interpreted
  26602. +sequentially and immediately. -u and -g states are preserved across
  26603. +<cpio_source> options so an explicit "-u 0 -g 0" is required
  26604. +to reset the root/group mapping.
  26605. +EOF
  26606. +}
  26607. +
  26608. +list_default_initramfs() {
  26609. + # echo usr/kinit/kinit
  26610. + :
  26611. +}
  26612. +
  26613. +default_initramfs() {
  26614. + cat <<-EOF >> ${output}
  26615. + # This is a very simple, default initramfs
  26616. +
  26617. + dir /dev 0755 0 0
  26618. + nod /dev/console 0600 0 0 c 5 1
  26619. + dir /root 0700 0 0
  26620. + # file /kinit usr/kinit/kinit 0755 0 0
  26621. + # slink /init kinit 0755 0 0
  26622. + EOF
  26623. +}
  26624. +
  26625. +filetype() {
  26626. + local argv1="$1"
  26627. +
  26628. + # symlink test must come before file test
  26629. + if [ -L "${argv1}" ]; then
  26630. + echo "slink"
  26631. + elif [ -f "${argv1}" ]; then
  26632. + echo "file"
  26633. + elif [ -d "${argv1}" ]; then
  26634. + echo "dir"
  26635. + elif [ -b "${argv1}" -o -c "${argv1}" ]; then
  26636. + echo "nod"
  26637. + elif [ -p "${argv1}" ]; then
  26638. + echo "pipe"
  26639. + elif [ -S "${argv1}" ]; then
  26640. + echo "sock"
  26641. + else
  26642. + echo "invalid"
  26643. + fi
  26644. + return 0
  26645. +}
  26646. +
  26647. +list_print_mtime() {
  26648. + :
  26649. +}
  26650. +
  26651. +print_mtime() {
  26652. + local my_mtime="0"
  26653. +
  26654. + if [ -e "$1" ]; then
  26655. + my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
  26656. + fi
  26657. +
  26658. + echo "# Last modified: ${my_mtime}" >> ${output}
  26659. + echo "" >> ${output}
  26660. +}
  26661. +
  26662. +list_parse() {
  26663. + echo "$1 \\"
  26664. +}
  26665. +
  26666. +# for each file print a line in following format
  26667. +# <filetype> <name> <path to file> <octal mode> <uid> <gid>
  26668. +# for links, devices etc the format differs. See gen_init_cpio for details
  26669. +parse() {
  26670. + local location="$1"
  26671. + local name="${location/${srcdir}//}"
  26672. + # change '//' into '/'
  26673. + name="${name//\/\///}"
  26674. + local mode="$2"
  26675. + local uid="$3"
  26676. + local gid="$4"
  26677. + local ftype=$(filetype "${location}")
  26678. + # remap uid/gid to 0 if necessary
  26679. + [ "$uid" -eq "$root_uid" ] && uid=0
  26680. + [ "$gid" -eq "$root_gid" ] && gid=0
  26681. + local str="${mode} ${uid} ${gid}"
  26682. +
  26683. + [ "${ftype}" == "invalid" ] && return 0
  26684. + [ "${location}" == "${srcdir}" ] && return 0
  26685. +
  26686. + case "${ftype}" in
  26687. + "file")
  26688. + str="${ftype} ${name} ${location} ${str}"
  26689. + ;;
  26690. + "nod")
  26691. + local dev_type=
  26692. + local maj=$(LC_ALL=C ls -l "${location}" | \
  26693. + gawk '{sub(/,/, "", $5); print $5}')
  26694. + local min=$(LC_ALL=C ls -l "${location}" | \
  26695. + gawk '{print $6}')
  26696. +
  26697. + if [ -b "${location}" ]; then
  26698. + dev_type="b"
  26699. + else
  26700. + dev_type="c"
  26701. + fi
  26702. + str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
  26703. + ;;
  26704. + "slink")
  26705. + local target=$(LC_ALL=C ls -l "${location}" | \
  26706. + gawk '{print $11}')
  26707. + str="${ftype} ${name} ${target} ${str}"
  26708. + ;;
  26709. + *)
  26710. + str="${ftype} ${name} ${str}"
  26711. + ;;
  26712. + esac
  26713. +
  26714. + echo "${str}" >> ${output}
  26715. +
  26716. + return 0
  26717. +}
  26718. +
  26719. +unknown_option() {
  26720. + printf "ERROR: unknown option \"$arg\"\n" >&2
  26721. + printf "If the filename validly begins with '-', " >&2
  26722. + printf "then it must be prefixed\n" >&2
  26723. + printf "by './' so that it won't be interpreted as an option." >&2
  26724. + printf "\n" >&2
  26725. + usage >&2
  26726. + exit 1
  26727. +}
  26728. +
  26729. +list_header() {
  26730. + :
  26731. +}
  26732. +
  26733. +header() {
  26734. + printf "\n#####################\n# $1\n" >> ${output}
  26735. +}
  26736. +
  26737. +# process one directory (incl sub-directories)
  26738. +dir_filelist() {
  26739. + ${dep_list}header "$1"
  26740. +
  26741. + srcdir=$(echo "$1" | sed -e 's://*:/:g')
  26742. + dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
  26743. +
  26744. + # If $dirlist is only one line, then the directory is empty
  26745. + if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
  26746. + ${dep_list}print_mtime "$1"
  26747. +
  26748. + echo "${dirlist}" | \
  26749. + while read x; do
  26750. + ${dep_list}parse ${x}
  26751. + done
  26752. + fi
  26753. +}
  26754. +
  26755. +# if only one file is specified and it is .cpio file then use it direct as fs
  26756. +# if a directory is specified then add all files in given direcotry to fs
  26757. +# if a regular file is specified assume it is in gen_initramfs format
  26758. +input_file() {
  26759. + source="$1"
  26760. + if [ -f "$1" ]; then
  26761. + ${dep_list}header "$1"
  26762. + is_cpio="$(echo "$1" | sed 's/^.*\.cpio/cpio/')"
  26763. + if [ $2 -eq 0 -a ${is_cpio} == "cpio" ]; then
  26764. + cpio_file=$1
  26765. + [ ! -z ${dep_list} ] && echo "$1"
  26766. + return 0
  26767. + fi
  26768. + if [ -z ${dep_list} ]; then
  26769. + print_mtime "$1" >> ${output}
  26770. + cat "$1" >> ${output}
  26771. + else
  26772. + cat "$1" | while read type dir file perm ; do
  26773. + if [ "$type" == "file" ]; then
  26774. + echo "$file \\";
  26775. + fi
  26776. + done
  26777. + fi
  26778. + elif [ -d "$1" ]; then
  26779. + dir_filelist "$1"
  26780. + else
  26781. + echo " ${prog}: Cannot open '$1'" >&2
  26782. + exit 1
  26783. + fi
  26784. +}
  26785. +
  26786. +prog=$0
  26787. +root_uid=0
  26788. +root_gid=0
  26789. +dep_list=
  26790. +cpio_file=
  26791. +cpio_list=
  26792. +output="/dev/stdout"
  26793. +output_file=""
  26794. +opt=""
  26795. +
  26796. +arg="$1"
  26797. +case "$arg" in
  26798. + "-l") # files included in initramfs - used by kbuild
  26799. + dep_list="list_"
  26800. + echo "deps_initramfs := \\"
  26801. + shift
  26802. + ;;
  26803. + "-o") # generate lzma-ed cpio image named $1
  26804. + shift
  26805. + output_file="$1"
  26806. + cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
  26807. + output=${cpio_list}
  26808. + shift
  26809. + ;;
  26810. +esac
  26811. +while [ $# -gt 0 ]; do
  26812. + arg="$1"
  26813. + shift
  26814. + case "$arg" in
  26815. + "-u") # map $1 to uid=0 (root)
  26816. + root_uid="$1"
  26817. + shift
  26818. + ;;
  26819. + "-g") # map $1 to gid=0 (root)
  26820. + root_gid="$1"
  26821. + shift
  26822. + ;;
  26823. + "-s")
  26824. + opt="-d16"
  26825. + ;;
  26826. + "-d") # display default initramfs list
  26827. + default_list="$arg"
  26828. + ${dep_list}default_initramfs
  26829. + ;;
  26830. + "-h")
  26831. + usage
  26832. + exit 0
  26833. + ;;
  26834. + *)
  26835. + case "$arg" in
  26836. + "-"*)
  26837. + unknown_option
  26838. + ;;
  26839. + *) # input file/dir - process it
  26840. + input_file "$arg" "$#"
  26841. + ;;
  26842. + esac
  26843. + ;;
  26844. + esac
  26845. +done
  26846. +
  26847. +# If output_file is set we will generate cpio archive and lzma it
  26848. +# we are carefull to delete tmp files
  26849. +if [ ! -z ${output_file} ]; then
  26850. + if [ -z ${cpio_file} ]; then
  26851. + cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
  26852. + usr/gen_init_cpio ${cpio_list} > ${cpio_tfile}
  26853. + else
  26854. + cpio_tfile=${cpio_file}
  26855. + fi
  26856. + rm ${cpio_list}
  26857. + lzma e ${cpio_tfile} ${output_file} ${opt}
  26858. + [ -z ${cpio_file} ] && rm ${cpio_tfile}
  26859. +fi
  26860. +exit 0
  26861. diff --git a/shrinkconfig.sh b/shrinkconfig.sh
  26862. new file mode 100755
  26863. index 0000000..e7a3df7
  26864. --- /dev/null
  26865. +++ b/shrinkconfig.sh
  26866. @@ -0,0 +1,79 @@
  26867. +#! /bin/bash
  26868. +
  26869. +# shrinkconfig copyright 2006 by Rob Landley <rob@landley.net>
  26870. +# Licensed under the GNU General Public License version 2.
  26871. +
  26872. +if [ $# -ne 1 ]
  26873. +then
  26874. + echo "Turns current .config into a miniconfig file."
  26875. + echo "Usage: shrinkconfig mini.config"
  26876. + exit 1
  26877. +fi
  26878. +
  26879. +if [ ! -f .config ]
  26880. +then
  26881. + echo "Need a .config file to shrink."
  26882. + exit 1
  26883. +fi
  26884. +LENGTH=$(wc -l < .config)
  26885. +
  26886. +OUTPUT="$1"
  26887. +cp .config "$OUTPUT"
  26888. +if [ $? -ne 0 ]
  26889. +then
  26890. + echo "Couldn't create $OUTPUT"
  26891. + exit 1
  26892. +fi
  26893. +
  26894. +# If we get interrupted, clean up the mess
  26895. +
  26896. +KERNELOUTPUT=""
  26897. +
  26898. +function cleanup
  26899. +{
  26900. + echo
  26901. + echo "Interrupted."
  26902. + [ ! -z "$KERNELOUTPUT" ] && rm -rf "$KERNELOUTPUT"
  26903. + rm "$OUTPUT"
  26904. + exit 1
  26905. +}
  26906. +
  26907. +trap cleanup HUP INT QUIT TERM
  26908. +
  26909. +# Since the "O=" argument to make doesn't work recursively, we need to jump
  26910. +# through a few hoops to avoid overwriting the .config that we're shrinking.
  26911. +
  26912. +# If we're building out of tree, we'll have absolute paths to source and build
  26913. +# directories in the Makefile.
  26914. +
  26915. +KERNELSRC=$(sed -n -e 's/KERNELSRC[^/]*:=[^/]*//p' Makefile)
  26916. +[ -z "$KERNELSRC" ] && KERNELSRC=$(pwd)
  26917. +KERNELOUTPUT=`pwd`/.config.minitemp
  26918. +
  26919. +mkdir -p "$KERNELOUTPUT" || exit 1
  26920. +
  26921. +echo "Shrinking .config to $OUTPUT..."
  26922. +
  26923. +for I in $(seq 1 $LENGTH)
  26924. +do
  26925. + echo -n -e "\r"$I/$LENGTH lines $(wc -c < "$OUTPUT") bytes
  26926. +
  26927. + sed -n "${I}!p" "$OUTPUT" > "$KERNELOUTPUT"/.config.test
  26928. + # Do a config with this file
  26929. + make -C "$KERNELSRC" O="$KERNELOUTPUT" allnoconfig KCONFIG_ALLCONFIG="$KERNELOUTPUT"/.config.test > /dev/null
  26930. +
  26931. + # Compare. The date changes, so expect a small difference each time.
  26932. + D=$(diff "$KERNELOUTPUT"/.config .config | wc -l)
  26933. + if [ $D -eq 4 ]
  26934. + then
  26935. + mv "$KERNELOUTPUT"/.config.test "$OUTPUT"
  26936. + LENGTH=$[$LENGTH-1]
  26937. + else
  26938. + I=$[$I + 1]
  26939. + fi
  26940. +done
  26941. +
  26942. +rm -rf "$KERNELOUTPUT"
  26943. +
  26944. +# One extra echo to preserve status line.
  26945. +echo
  26946. diff --git a/usr/Makefile b/usr/Makefile
  26947. index 201f27f..8e1f6ea 100644
  26948. --- a/usr/Makefile
  26949. +++ b/usr/Makefile
  26950. @@ -19,6 +19,7 @@ $(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio.gz FORCE
  26951. hostprogs-y := gen_init_cpio
  26952. initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
  26953. +lzma_initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_lzma_initramfs_list.sh
  26954. ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
  26955. $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
  26956. ramfs-args := \
  26957. @@ -36,6 +37,14 @@ endif
  26958. quiet_cmd_initfs = GEN $@
  26959. cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
  26960. +ifdef CONFIG_LZMA_INITRAM_FS_SMALLMEM
  26961. +quiet_cmd_lzma_initfs = LZRAMFS $@
  26962. + cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) -s $(ramfs-input)
  26963. +else
  26964. +quiet_cmd_lzma_initfs = LZRAMFS $@
  26965. + cmd_lzma_initfs = $(lzma_initramfs) -o $@ $(ramfs-args) $(ramfs-input)
  26966. +endif
  26967. +
  26968. targets := initramfs_data.cpio.gz
  26969. # do not try to update files included in initramfs
  26970. $(deps_initramfs): ;
  26971. @@ -48,5 +57,9 @@ $(deps_initramfs): klibcdirs
  26972. # 4) arguments to gen_initramfs.sh changes
  26973. $(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
  26974. $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.gz.d
  26975. +ifdef CONFIG_LZMA_INITRAM_FS
  26976. + $(call if_changed,lzma_initfs)
  26977. +else
  26978. $(call if_changed,initfs)
  26979. +endif