yaffs2.patch 431 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559
  1. diff -Nur linux-3.18.14.orig/fs/Kconfig linux-3.18.14/fs/Kconfig
  2. --- linux-3.18.14.orig/fs/Kconfig 2015-05-20 17:04:50.000000000 +0200
  3. +++ linux-3.18.14/fs/Kconfig 2015-06-14 21:22:55.000000000 +0200
  4. @@ -191,6 +191,7 @@
  5. source "fs/befs/Kconfig"
  6. source "fs/bfs/Kconfig"
  7. source "fs/efs/Kconfig"
  8. +source "fs/yaffs2/Kconfig"
  9. source "fs/jffs2/Kconfig"
  10. # UBIFS File system configuration
  11. source "fs/ubifs/Kconfig"
  12. diff -Nur linux-3.18.14.orig/fs/Makefile linux-3.18.14/fs/Makefile
  13. --- linux-3.18.14.orig/fs/Makefile 2015-05-20 17:04:50.000000000 +0200
  14. +++ linux-3.18.14/fs/Makefile 2015-06-14 21:22:55.000000000 +0200
  15. @@ -126,3 +126,4 @@
  16. obj-$(CONFIG_CEPH_FS) += ceph/
  17. obj-$(CONFIG_PSTORE) += pstore/
  18. obj-$(CONFIG_EFIVAR_FS) += efivarfs/
  19. +obj-$(CONFIG_YAFFS_FS) += yaffs2/
  20. diff -Nur linux-3.18.14.orig/fs/yaffs2/Kconfig linux-3.18.14/fs/yaffs2/Kconfig
  21. --- linux-3.18.14.orig/fs/yaffs2/Kconfig 1970-01-01 01:00:00.000000000 +0100
  22. +++ linux-3.18.14/fs/yaffs2/Kconfig 2015-06-14 21:23:22.000000000 +0200
  23. @@ -0,0 +1,171 @@
  24. +#
  25. +# yaffs file system configurations
  26. +#
  27. +
  28. +config YAFFS_FS
  29. + tristate "yaffs2 file system support"
  30. + default n
  31. + depends on MTD_BLOCK
  32. + select YAFFS_YAFFS1
  33. + select YAFFS_YAFFS2
  34. + help
  35. + yaffs2, or Yet Another Flash File System, is a file system
  36. + optimised for NAND Flash chips.
  37. +
  38. + To compile the yaffs2 file system support as a module, choose M
  39. + here: the module will be called yaffs2.
  40. +
  41. + If unsure, say N.
  42. +
  43. + Further information on yaffs2 is available at
  44. + <http://www.aleph1.co.uk/yaffs/>.
  45. +
  46. +config YAFFS_YAFFS1
  47. + bool "512 byte / page devices"
  48. + depends on YAFFS_FS
  49. + default y
  50. + help
  51. + Enable yaffs1 support -- yaffs for 512 byte / page devices
  52. +
  53. + Not needed for 2K-page devices.
  54. +
  55. + If unsure, say Y.
  56. +
  57. +config YAFFS_9BYTE_TAGS
  58. + bool "Use older-style on-NAND data format with pageStatus byte"
  59. + depends on YAFFS_YAFFS1
  60. + default n
  61. + help
  62. +
  63. + Older-style on-NAND data format has a "pageStatus" byte to record
  64. + chunk/page state. This byte is zero when the page is discarded.
  65. + Choose this option if you have existing on-NAND data using this
  66. + format that you need to continue to support. New data written
  67. + also uses the older-style format. Note: Use of this option
  68. + generally requires that MTD's oob layout be adjusted to use the
  69. + older-style format. See notes on tags formats and MTD versions
  70. + in yaffs_mtdif1.c.
  71. +
  72. + If unsure, say N.
  73. +
  74. +config YAFFS_DOES_ECC
  75. + bool "Lets yaffs do its own ECC"
  76. + depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS
  77. + default n
  78. + help
  79. + This enables yaffs to use its own ECC functions instead of using
  80. + the ones from the generic MTD-NAND driver.
  81. +
  82. + If unsure, say N.
  83. +
  84. +config YAFFS_ECC_WRONG_ORDER
  85. + bool "Use the same ecc byte order as Steven Hill's nand_ecc.c"
  86. + depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS
  87. + default n
  88. + help
  89. + This makes yaffs_ecc.c use the same ecc byte order as Steven
  90. + Hill's nand_ecc.c. If not set, then you get the same ecc byte
  91. + order as SmartMedia.
  92. +
  93. + If unsure, say N.
  94. +
  95. +config YAFFS_YAFFS2
  96. + bool "2048 byte (or larger) / page devices"
  97. + depends on YAFFS_FS
  98. + default y
  99. + help
  100. + Enable yaffs2 support -- yaffs for >= 2K bytes per page devices
  101. +
  102. + If unsure, say Y.
  103. +
  104. +config YAFFS_AUTO_YAFFS2
  105. + bool "Autoselect yaffs2 format"
  106. + depends on YAFFS_YAFFS2
  107. + default y
  108. + help
  109. + Without this, you need to explicitely use yaffs2 as the file
  110. + system type. With this, you can say "yaffs" and yaffs or yaffs2
  111. + will be used depending on the device page size (yaffs on
  112. + 512-byte page devices, yaffs2 on 2K page devices).
  113. +
  114. + If unsure, say Y.
  115. +
  116. +config YAFFS_DISABLE_TAGS_ECC
  117. + bool "Disable yaffs from doing ECC on tags by default"
  118. + depends on YAFFS_FS && YAFFS_YAFFS2
  119. + default n
  120. + help
  121. + This defaults yaffs to using its own ECC calculations on tags instead of
  122. + just relying on the MTD.
  123. + This behavior can also be overridden with tags_ecc_on and
  124. + tags_ecc_off mount options.
  125. +
  126. + If unsure, say N.
  127. +
  128. +config YAFFS_ALWAYS_CHECK_CHUNK_ERASED
  129. + bool "Force chunk erase check"
  130. + depends on YAFFS_FS
  131. + default n
  132. + help
  133. + Normally yaffs only checks chunks before writing until an erased
  134. + chunk is found. This helps to detect any partially written
  135. + chunks that might have happened due to power loss.
  136. +
  137. + Enabling this forces on the test that chunks are erased in flash
  138. + before writing to them. This takes more time but is potentially
  139. + a bit more secure.
  140. +
  141. + Suggest setting Y during development and ironing out driver
  142. + issues etc. Suggest setting to N if you want faster writing.
  143. +
  144. + If unsure, say Y.
  145. +
  146. +config YAFFS_EMPTY_LOST_AND_FOUND
  147. + bool "Empty lost and found on boot"
  148. + depends on YAFFS_FS
  149. + default n
  150. + help
  151. + If this is enabled then the contents of lost and found is
  152. + automatically dumped at mount.
  153. +
  154. + If unsure, say N.
  155. +
  156. +config YAFFS_DISABLE_BLOCK_REFRESHING
  157. + bool "Disable yaffs2 block refreshing"
  158. + depends on YAFFS_FS
  159. + default n
  160. + help
  161. + If this is set, then block refreshing is disabled.
  162. + Block refreshing infrequently refreshes the oldest block in
  163. + a yaffs2 file system. This mechanism helps to refresh flash to
  164. + mitigate against data loss. This is particularly useful for MLC.
  165. +
  166. + If unsure, say N.
  167. +
  168. +config YAFFS_DISABLE_BACKGROUND
  169. + bool "Disable yaffs2 background processing"
  170. + depends on YAFFS_FS
  171. + default n
  172. + help
  173. + If this is set, then background processing is disabled.
  174. + Background processing makes many foreground activities faster.
  175. +
  176. + If unsure, say N.
  177. +
  178. +config YAFFS_DISABLE_BAD_BLOCK_MARKING
  179. + bool "Disable yaffs2 bad block marking"
  180. + depends on YAFFS_FS
  181. + default n
  182. + help
  183. + Useful during early flash bring up to prevent problems causing
  184. + lots of bad block marking.
  185. +
  186. + If unsure, say N.
  187. +
  188. +config YAFFS_XATTR
  189. + bool "Enable yaffs2 xattr support"
  190. + depends on YAFFS_FS
  191. + default y
  192. + help
  193. + If this is set then yaffs2 will provide xattr support.
  194. + If unsure, say Y.
  195. diff -Nur linux-3.18.14.orig/fs/yaffs2/Makefile linux-3.18.14/fs/yaffs2/Makefile
  196. --- linux-3.18.14.orig/fs/yaffs2/Makefile 1970-01-01 01:00:00.000000000 +0100
  197. +++ linux-3.18.14/fs/yaffs2/Makefile 2015-06-14 21:23:22.000000000 +0200
  198. @@ -0,0 +1,18 @@
  199. +#
  200. +# Makefile for the linux YAFFS filesystem routines.
  201. +#
  202. +
  203. +obj-$(CONFIG_YAFFS_FS) += yaffs.o
  204. +
  205. +yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o
  206. +yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
  207. +yaffs-y += yaffs_tagscompat.o yaffs_tagsmarshall.o
  208. +yaffs-y += yaffs_mtdif.o
  209. +yaffs-y += yaffs_nameval.o yaffs_attribs.o
  210. +yaffs-y += yaffs_allocator.o
  211. +yaffs-y += yaffs_yaffs1.o
  212. +yaffs-y += yaffs_yaffs2.o
  213. +yaffs-y += yaffs_bitmap.o
  214. +yaffs-y += yaffs_summary.o
  215. +yaffs-y += yaffs_verify.o
  216. +
  217. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_allocator.c linux-3.18.14/fs/yaffs2/yaffs_allocator.c
  218. --- linux-3.18.14.orig/fs/yaffs2/yaffs_allocator.c 1970-01-01 01:00:00.000000000 +0100
  219. +++ linux-3.18.14/fs/yaffs2/yaffs_allocator.c 2015-06-14 21:23:22.000000000 +0200
  220. @@ -0,0 +1,357 @@
  221. +/*
  222. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  223. + *
  224. + * Copyright (C) 2002-2011 Aleph One Ltd.
  225. + * for Toby Churchill Ltd and Brightstar Engineering
  226. + *
  227. + * Created by Charles Manning <charles@aleph1.co.uk>
  228. + *
  229. + * This program is free software; you can redistribute it and/or modify
  230. + * it under the terms of the GNU General Public License version 2 as
  231. + * published by the Free Software Foundation.
  232. + */
  233. +
  234. +#include "yaffs_allocator.h"
  235. +#include "yaffs_guts.h"
  236. +#include "yaffs_trace.h"
  237. +#include "yportenv.h"
  238. +
  239. +/*
  240. + * Each entry in yaffs_tnode_list and yaffs_obj_list hold blocks
  241. + * of approx 100 objects that are themn allocated singly.
  242. + * This is basically a simplified slab allocator.
  243. + *
  244. + * We don't use the Linux slab allocator because slab does not allow
  245. + * us to dump all the objects in one hit when we do a umount and tear
  246. + * down all the tnodes and objects. slab requires that we first free
  247. + * the individual objects.
  248. + *
  249. + * Once yaffs has been mainlined I shall try to motivate for a change
  250. + * to slab to provide the extra features we need here.
  251. + */
  252. +
  253. +struct yaffs_tnode_list {
  254. + struct yaffs_tnode_list *next;
  255. + struct yaffs_tnode *tnodes;
  256. +};
  257. +
  258. +struct yaffs_obj_list {
  259. + struct yaffs_obj_list *next;
  260. + struct yaffs_obj *objects;
  261. +};
  262. +
  263. +struct yaffs_allocator {
  264. + int n_tnodes_created;
  265. + struct yaffs_tnode *free_tnodes;
  266. + int n_free_tnodes;
  267. + struct yaffs_tnode_list *alloc_tnode_list;
  268. +
  269. + int n_obj_created;
  270. + struct list_head free_objs;
  271. + int n_free_objects;
  272. +
  273. + struct yaffs_obj_list *allocated_obj_list;
  274. +};
  275. +
  276. +static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
  277. +{
  278. + struct yaffs_allocator *allocator =
  279. + (struct yaffs_allocator *)dev->allocator;
  280. + struct yaffs_tnode_list *tmp;
  281. +
  282. + if (!allocator) {
  283. + BUG();
  284. + return;
  285. + }
  286. +
  287. + while (allocator->alloc_tnode_list) {
  288. + tmp = allocator->alloc_tnode_list->next;
  289. +
  290. + kfree(allocator->alloc_tnode_list->tnodes);
  291. + kfree(allocator->alloc_tnode_list);
  292. + allocator->alloc_tnode_list = tmp;
  293. + }
  294. +
  295. + allocator->free_tnodes = NULL;
  296. + allocator->n_free_tnodes = 0;
  297. + allocator->n_tnodes_created = 0;
  298. +}
  299. +
  300. +static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
  301. +{
  302. + struct yaffs_allocator *allocator = dev->allocator;
  303. +
  304. + if (!allocator) {
  305. + BUG();
  306. + return;
  307. + }
  308. +
  309. + allocator->alloc_tnode_list = NULL;
  310. + allocator->free_tnodes = NULL;
  311. + allocator->n_free_tnodes = 0;
  312. + allocator->n_tnodes_created = 0;
  313. +}
  314. +
  315. +static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
  316. +{
  317. + struct yaffs_allocator *allocator =
  318. + (struct yaffs_allocator *)dev->allocator;
  319. + int i;
  320. + struct yaffs_tnode *new_tnodes;
  321. + u8 *mem;
  322. + struct yaffs_tnode *curr;
  323. + struct yaffs_tnode *next;
  324. + struct yaffs_tnode_list *tnl;
  325. +
  326. + if (!allocator) {
  327. + BUG();
  328. + return YAFFS_FAIL;
  329. + }
  330. +
  331. + if (n_tnodes < 1)
  332. + return YAFFS_OK;
  333. +
  334. + /* make these things */
  335. + new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS);
  336. + mem = (u8 *) new_tnodes;
  337. +
  338. + if (!new_tnodes) {
  339. + yaffs_trace(YAFFS_TRACE_ERROR,
  340. + "yaffs: Could not allocate Tnodes");
  341. + return YAFFS_FAIL;
  342. + }
  343. +
  344. + /* New hookup for wide tnodes */
  345. + for (i = 0; i < n_tnodes - 1; i++) {
  346. + curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size];
  347. + next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size];
  348. + curr->internal[0] = next;
  349. + }
  350. +
  351. + curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size];
  352. + curr->internal[0] = allocator->free_tnodes;
  353. + allocator->free_tnodes = (struct yaffs_tnode *)mem;
  354. +
  355. + allocator->n_free_tnodes += n_tnodes;
  356. + allocator->n_tnodes_created += n_tnodes;
  357. +
  358. + /* Now add this bunch of tnodes to a list for freeing up.
  359. + * NB If we can't add this to the management list it isn't fatal
  360. + * but it just means we can't free this bunch of tnodes later.
  361. + */
  362. + tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS);
  363. + if (!tnl) {
  364. + yaffs_trace(YAFFS_TRACE_ERROR,
  365. + "Could not add tnodes to management list");
  366. + return YAFFS_FAIL;
  367. + } else {
  368. + tnl->tnodes = new_tnodes;
  369. + tnl->next = allocator->alloc_tnode_list;
  370. + allocator->alloc_tnode_list = tnl;
  371. + }
  372. +
  373. + yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added");
  374. +
  375. + return YAFFS_OK;
  376. +}
  377. +
  378. +struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
  379. +{
  380. + struct yaffs_allocator *allocator =
  381. + (struct yaffs_allocator *)dev->allocator;
  382. + struct yaffs_tnode *tn = NULL;
  383. +
  384. + if (!allocator) {
  385. + BUG();
  386. + return NULL;
  387. + }
  388. +
  389. + /* If there are none left make more */
  390. + if (!allocator->free_tnodes)
  391. + yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES);
  392. +
  393. + if (allocator->free_tnodes) {
  394. + tn = allocator->free_tnodes;
  395. + allocator->free_tnodes = allocator->free_tnodes->internal[0];
  396. + allocator->n_free_tnodes--;
  397. + }
  398. +
  399. + return tn;
  400. +}
  401. +
  402. +/* FreeTnode frees up a tnode and puts it back on the free list */
  403. +void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
  404. +{
  405. + struct yaffs_allocator *allocator = dev->allocator;
  406. +
  407. + if (!allocator) {
  408. + BUG();
  409. + return;
  410. + }
  411. +
  412. + if (tn) {
  413. + tn->internal[0] = allocator->free_tnodes;
  414. + allocator->free_tnodes = tn;
  415. + allocator->n_free_tnodes++;
  416. + }
  417. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  418. +}
  419. +
  420. +/*--------------- yaffs_obj alloaction ------------------------
  421. + *
  422. + * Free yaffs_objs are stored in a list using obj->siblings.
  423. + * The blocks of allocated objects are stored in a linked list.
  424. + */
  425. +
  426. +static void yaffs_init_raw_objs(struct yaffs_dev *dev)
  427. +{
  428. + struct yaffs_allocator *allocator = dev->allocator;
  429. +
  430. + if (!allocator) {
  431. + BUG();
  432. + return;
  433. + }
  434. +
  435. + allocator->allocated_obj_list = NULL;
  436. + INIT_LIST_HEAD(&allocator->free_objs);
  437. + allocator->n_free_objects = 0;
  438. +}
  439. +
  440. +static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
  441. +{
  442. + struct yaffs_allocator *allocator = dev->allocator;
  443. + struct yaffs_obj_list *tmp;
  444. +
  445. + if (!allocator) {
  446. + BUG();
  447. + return;
  448. + }
  449. +
  450. + while (allocator->allocated_obj_list) {
  451. + tmp = allocator->allocated_obj_list->next;
  452. + kfree(allocator->allocated_obj_list->objects);
  453. + kfree(allocator->allocated_obj_list);
  454. + allocator->allocated_obj_list = tmp;
  455. + }
  456. +
  457. + INIT_LIST_HEAD(&allocator->free_objs);
  458. + allocator->n_free_objects = 0;
  459. + allocator->n_obj_created = 0;
  460. +}
  461. +
  462. +static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
  463. +{
  464. + struct yaffs_allocator *allocator = dev->allocator;
  465. + int i;
  466. + struct yaffs_obj *new_objs;
  467. + struct yaffs_obj_list *list;
  468. +
  469. + if (!allocator) {
  470. + BUG();
  471. + return YAFFS_FAIL;
  472. + }
  473. +
  474. + if (n_obj < 1)
  475. + return YAFFS_OK;
  476. +
  477. + /* make these things */
  478. + new_objs = kmalloc(n_obj * sizeof(struct yaffs_obj), GFP_NOFS);
  479. + list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS);
  480. +
  481. + if (!new_objs || !list) {
  482. + kfree(new_objs);
  483. + new_objs = NULL;
  484. + kfree(list);
  485. + list = NULL;
  486. + yaffs_trace(YAFFS_TRACE_ALLOCATE,
  487. + "Could not allocate more objects");
  488. + return YAFFS_FAIL;
  489. + }
  490. +
  491. + /* Hook them into the free list */
  492. + for (i = 0; i < n_obj; i++)
  493. + list_add(&new_objs[i].siblings, &allocator->free_objs);
  494. +
  495. + allocator->n_free_objects += n_obj;
  496. + allocator->n_obj_created += n_obj;
  497. +
  498. + /* Now add this bunch of Objects to a list for freeing up. */
  499. +
  500. + list->objects = new_objs;
  501. + list->next = allocator->allocated_obj_list;
  502. + allocator->allocated_obj_list = list;
  503. +
  504. + return YAFFS_OK;
  505. +}
  506. +
  507. +struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
  508. +{
  509. + struct yaffs_obj *obj = NULL;
  510. + struct list_head *lh;
  511. + struct yaffs_allocator *allocator = dev->allocator;
  512. +
  513. + if (!allocator) {
  514. + BUG();
  515. + return obj;
  516. + }
  517. +
  518. + /* If there are none left make more */
  519. + if (list_empty(&allocator->free_objs))
  520. + yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS);
  521. +
  522. + if (!list_empty(&allocator->free_objs)) {
  523. + lh = allocator->free_objs.next;
  524. + obj = list_entry(lh, struct yaffs_obj, siblings);
  525. + list_del_init(lh);
  526. + allocator->n_free_objects--;
  527. + }
  528. +
  529. + return obj;
  530. +}
  531. +
  532. +void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
  533. +{
  534. +
  535. + struct yaffs_allocator *allocator = dev->allocator;
  536. +
  537. + if (!allocator) {
  538. + BUG();
  539. + return;
  540. + }
  541. +
  542. + /* Link into the free list. */
  543. + list_add(&obj->siblings, &allocator->free_objs);
  544. + allocator->n_free_objects++;
  545. +}
  546. +
  547. +void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
  548. +{
  549. +
  550. + if (!dev->allocator) {
  551. + BUG();
  552. + return;
  553. + }
  554. +
  555. + yaffs_deinit_raw_tnodes(dev);
  556. + yaffs_deinit_raw_objs(dev);
  557. + kfree(dev->allocator);
  558. + dev->allocator = NULL;
  559. +}
  560. +
  561. +void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
  562. +{
  563. + struct yaffs_allocator *allocator;
  564. +
  565. + if (dev->allocator) {
  566. + BUG();
  567. + return;
  568. + }
  569. +
  570. + allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS);
  571. + if (allocator) {
  572. + dev->allocator = allocator;
  573. + yaffs_init_raw_tnodes(dev);
  574. + yaffs_init_raw_objs(dev);
  575. + }
  576. +}
  577. +
  578. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_allocator.h linux-3.18.14/fs/yaffs2/yaffs_allocator.h
  579. --- linux-3.18.14.orig/fs/yaffs2/yaffs_allocator.h 1970-01-01 01:00:00.000000000 +0100
  580. +++ linux-3.18.14/fs/yaffs2/yaffs_allocator.h 2015-06-14 21:23:22.000000000 +0200
  581. @@ -0,0 +1,30 @@
  582. +/*
  583. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  584. + *
  585. + * Copyright (C) 2002-2011 Aleph One Ltd.
  586. + * for Toby Churchill Ltd and Brightstar Engineering
  587. + *
  588. + * Created by Charles Manning <charles@aleph1.co.uk>
  589. + *
  590. + * This program is free software; you can redistribute it and/or modify
  591. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  592. + * published by the Free Software Foundation.
  593. + *
  594. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  595. + */
  596. +
  597. +#ifndef __YAFFS_ALLOCATOR_H__
  598. +#define __YAFFS_ALLOCATOR_H__
  599. +
  600. +#include "yaffs_guts.h"
  601. +
  602. +void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev);
  603. +void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev);
  604. +
  605. +struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev);
  606. +void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn);
  607. +
  608. +struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev);
  609. +void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj);
  610. +
  611. +#endif
  612. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_attribs.c linux-3.18.14/fs/yaffs2/yaffs_attribs.c
  613. --- linux-3.18.14.orig/fs/yaffs2/yaffs_attribs.c 1970-01-01 01:00:00.000000000 +0100
  614. +++ linux-3.18.14/fs/yaffs2/yaffs_attribs.c 2015-06-14 21:23:22.000000000 +0200
  615. @@ -0,0 +1,132 @@
  616. +/*
  617. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  618. + *
  619. + * Copyright (C) 2002-2011 Aleph One Ltd.
  620. + * for Toby Churchill Ltd and Brightstar Engineering
  621. + *
  622. + * Created by Charles Manning <charles@aleph1.co.uk>
  623. + *
  624. + * This program is free software; you can redistribute it and/or modify
  625. + * it under the terms of the GNU General Public License version 2 as
  626. + * published by the Free Software Foundation.
  627. + */
  628. +
  629. +#include "yaffs_guts.h"
  630. +#include "yaffs_attribs.h"
  631. +
  632. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  633. +#define IATTR_UID ia_uid
  634. +#define IATTR_GID ia_gid
  635. +#else
  636. +#define IATTR_UID ia_uid.val
  637. +#define IATTR_GID ia_gid.val
  638. +#endif
  639. +
  640. +void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
  641. +{
  642. + obj->yst_uid = oh->yst_uid;
  643. + obj->yst_gid = oh->yst_gid;
  644. + obj->yst_atime = oh->yst_atime;
  645. + obj->yst_mtime = oh->yst_mtime;
  646. + obj->yst_ctime = oh->yst_ctime;
  647. + obj->yst_rdev = oh->yst_rdev;
  648. +}
  649. +
  650. +void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj)
  651. +{
  652. + oh->yst_uid = obj->yst_uid;
  653. + oh->yst_gid = obj->yst_gid;
  654. + oh->yst_atime = obj->yst_atime;
  655. + oh->yst_mtime = obj->yst_mtime;
  656. + oh->yst_ctime = obj->yst_ctime;
  657. + oh->yst_rdev = obj->yst_rdev;
  658. +
  659. +}
  660. +
  661. +void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
  662. +{
  663. + obj->yst_mtime = Y_CURRENT_TIME;
  664. + if (do_a)
  665. + obj->yst_atime = obj->yst_mtime;
  666. + if (do_c)
  667. + obj->yst_ctime = obj->yst_mtime;
  668. +}
  669. +
  670. +void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev)
  671. +{
  672. + yaffs_load_current_time(obj, 1, 1);
  673. + obj->yst_rdev = rdev;
  674. + obj->yst_uid = uid;
  675. + obj->yst_gid = gid;
  676. +}
  677. +
  678. +static loff_t yaffs_get_file_size(struct yaffs_obj *obj)
  679. +{
  680. + YCHAR *alias = NULL;
  681. + obj = yaffs_get_equivalent_obj(obj);
  682. +
  683. + switch (obj->variant_type) {
  684. + case YAFFS_OBJECT_TYPE_FILE:
  685. + return obj->variant.file_variant.file_size;
  686. + case YAFFS_OBJECT_TYPE_SYMLINK:
  687. + alias = obj->variant.symlink_variant.alias;
  688. + if (!alias)
  689. + return 0;
  690. + return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH);
  691. + default:
  692. + return 0;
  693. + }
  694. +}
  695. +
  696. +int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
  697. +{
  698. + unsigned int valid = attr->ia_valid;
  699. +
  700. + if (valid & ATTR_MODE)
  701. + obj->yst_mode = attr->ia_mode;
  702. + if (valid & ATTR_UID)
  703. + obj->yst_uid = attr->IATTR_UID;
  704. + if (valid & ATTR_GID)
  705. + obj->yst_gid = attr->IATTR_GID;
  706. +
  707. + if (valid & ATTR_ATIME)
  708. + obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
  709. + if (valid & ATTR_CTIME)
  710. + obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
  711. + if (valid & ATTR_MTIME)
  712. + obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
  713. +
  714. + if (valid & ATTR_SIZE)
  715. + yaffs_resize_file(obj, attr->ia_size);
  716. +
  717. + yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
  718. +
  719. + return YAFFS_OK;
  720. +
  721. +}
  722. +
  723. +int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
  724. +{
  725. + unsigned int valid = 0;
  726. +
  727. + attr->ia_mode = obj->yst_mode;
  728. + valid |= ATTR_MODE;
  729. + attr->IATTR_UID = obj->yst_uid;
  730. + valid |= ATTR_UID;
  731. + attr->IATTR_GID = obj->yst_gid;
  732. + valid |= ATTR_GID;
  733. +
  734. + Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
  735. + valid |= ATTR_ATIME;
  736. + Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
  737. + valid |= ATTR_CTIME;
  738. + Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
  739. + valid |= ATTR_MTIME;
  740. +
  741. + attr->ia_size = yaffs_get_file_size(obj);
  742. + valid |= ATTR_SIZE;
  743. +
  744. + attr->ia_valid = valid;
  745. +
  746. + return YAFFS_OK;
  747. +}
  748. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_attribs.h linux-3.18.14/fs/yaffs2/yaffs_attribs.h
  749. --- linux-3.18.14.orig/fs/yaffs2/yaffs_attribs.h 1970-01-01 01:00:00.000000000 +0100
  750. +++ linux-3.18.14/fs/yaffs2/yaffs_attribs.h 2015-06-14 21:23:22.000000000 +0200
  751. @@ -0,0 +1,28 @@
  752. +/*
  753. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  754. + *
  755. + * Copyright (C) 2002-2011 Aleph One Ltd.
  756. + * for Toby Churchill Ltd and Brightstar Engineering
  757. + *
  758. + * Created by Charles Manning <charles@aleph1.co.uk>
  759. + *
  760. + * This program is free software; you can redistribute it and/or modify
  761. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  762. + * published by the Free Software Foundation.
  763. + *
  764. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  765. + */
  766. +
  767. +#ifndef __YAFFS_ATTRIBS_H__
  768. +#define __YAFFS_ATTRIBS_H__
  769. +
  770. +#include "yaffs_guts.h"
  771. +
  772. +void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
  773. +void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj);
  774. +void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev);
  775. +void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c);
  776. +int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr);
  777. +int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr);
  778. +
  779. +#endif
  780. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_bitmap.c linux-3.18.14/fs/yaffs2/yaffs_bitmap.c
  781. --- linux-3.18.14.orig/fs/yaffs2/yaffs_bitmap.c 1970-01-01 01:00:00.000000000 +0100
  782. +++ linux-3.18.14/fs/yaffs2/yaffs_bitmap.c 2015-06-14 21:23:22.000000000 +0200
  783. @@ -0,0 +1,97 @@
  784. +/*
  785. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  786. + *
  787. + * Copyright (C) 2002-2011 Aleph One Ltd.
  788. + * for Toby Churchill Ltd and Brightstar Engineering
  789. + *
  790. + * Created by Charles Manning <charles@aleph1.co.uk>
  791. + *
  792. + * This program is free software; you can redistribute it and/or modify
  793. + * it under the terms of the GNU General Public License version 2 as
  794. + * published by the Free Software Foundation.
  795. + */
  796. +
  797. +#include "yaffs_bitmap.h"
  798. +#include "yaffs_trace.h"
  799. +/*
  800. + * Chunk bitmap manipulations
  801. + */
  802. +
  803. +static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk)
  804. +{
  805. + if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
  806. + yaffs_trace(YAFFS_TRACE_ERROR,
  807. + "BlockBits block %d is not valid",
  808. + blk);
  809. + BUG();
  810. + }
  811. + return dev->chunk_bits +
  812. + (dev->chunk_bit_stride * (blk - dev->internal_start_block));
  813. +}
  814. +
  815. +void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk)
  816. +{
  817. + if (blk < dev->internal_start_block || blk > dev->internal_end_block ||
  818. + chunk < 0 || chunk >= dev->param.chunks_per_block) {
  819. + yaffs_trace(YAFFS_TRACE_ERROR,
  820. + "Chunk Id (%d:%d) invalid",
  821. + blk, chunk);
  822. + BUG();
  823. + }
  824. +}
  825. +
  826. +void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk)
  827. +{
  828. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  829. +
  830. + memset(blk_bits, 0, dev->chunk_bit_stride);
  831. +}
  832. +
  833. +void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
  834. +{
  835. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  836. +
  837. + yaffs_verify_chunk_bit_id(dev, blk, chunk);
  838. + blk_bits[chunk / 8] &= ~(1 << (chunk & 7));
  839. +}
  840. +
  841. +void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
  842. +{
  843. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  844. +
  845. + yaffs_verify_chunk_bit_id(dev, blk, chunk);
  846. + blk_bits[chunk / 8] |= (1 << (chunk & 7));
  847. +}
  848. +
  849. +int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
  850. +{
  851. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  852. +
  853. + yaffs_verify_chunk_bit_id(dev, blk, chunk);
  854. + return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
  855. +}
  856. +
  857. +int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk)
  858. +{
  859. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  860. + int i;
  861. +
  862. + for (i = 0; i < dev->chunk_bit_stride; i++) {
  863. + if (*blk_bits)
  864. + return 1;
  865. + blk_bits++;
  866. + }
  867. + return 0;
  868. +}
  869. +
  870. +int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk)
  871. +{
  872. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  873. + int i;
  874. + int n = 0;
  875. +
  876. + for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++)
  877. + n += hweight8(*blk_bits);
  878. +
  879. + return n;
  880. +}
  881. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_bitmap.h linux-3.18.14/fs/yaffs2/yaffs_bitmap.h
  882. --- linux-3.18.14.orig/fs/yaffs2/yaffs_bitmap.h 1970-01-01 01:00:00.000000000 +0100
  883. +++ linux-3.18.14/fs/yaffs2/yaffs_bitmap.h 2015-06-14 21:23:22.000000000 +0200
  884. @@ -0,0 +1,33 @@
  885. +/*
  886. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  887. + *
  888. + * Copyright (C) 2002-2011 Aleph One Ltd.
  889. + * for Toby Churchill Ltd and Brightstar Engineering
  890. + *
  891. + * Created by Charles Manning <charles@aleph1.co.uk>
  892. + *
  893. + * This program is free software; you can redistribute it and/or modify
  894. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  895. + * published by the Free Software Foundation.
  896. + *
  897. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  898. + */
  899. +
  900. +/*
  901. + * Chunk bitmap manipulations
  902. + */
  903. +
  904. +#ifndef __YAFFS_BITMAP_H__
  905. +#define __YAFFS_BITMAP_H__
  906. +
  907. +#include "yaffs_guts.h"
  908. +
  909. +void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk);
  910. +void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk);
  911. +void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
  912. +void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
  913. +int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
  914. +int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk);
  915. +int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk);
  916. +
  917. +#endif
  918. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_checkptrw.c linux-3.18.14/fs/yaffs2/yaffs_checkptrw.c
  919. --- linux-3.18.14.orig/fs/yaffs2/yaffs_checkptrw.c 1970-01-01 01:00:00.000000000 +0100
  920. +++ linux-3.18.14/fs/yaffs2/yaffs_checkptrw.c 2015-06-14 21:23:22.000000000 +0200
  921. @@ -0,0 +1,466 @@
  922. +/*
  923. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  924. + *
  925. + * Copyright (C) 2002-2011 Aleph One Ltd.
  926. + * for Toby Churchill Ltd and Brightstar Engineering
  927. + *
  928. + * Created by Charles Manning <charles@aleph1.co.uk>
  929. + *
  930. + * This program is free software; you can redistribute it and/or modify
  931. + * it under the terms of the GNU General Public License version 2 as
  932. + * published by the Free Software Foundation.
  933. + */
  934. +
  935. +#include "yaffs_checkptrw.h"
  936. +#include "yaffs_getblockinfo.h"
  937. +
  938. +struct yaffs_checkpt_chunk_hdr {
  939. + int version;
  940. + int seq;
  941. + u32 sum;
  942. + u32 xor;
  943. +} ;
  944. +
  945. +
  946. +static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
  947. +{
  948. + return chunk - dev->chunk_offset;
  949. +}
  950. +
  951. +static int apply_block_offset(struct yaffs_dev *dev, int block)
  952. +{
  953. + return block - dev->block_offset;
  954. +}
  955. +
  956. +static void yaffs2_checkpt_init_chunk_hdr(struct yaffs_dev *dev)
  957. +{
  958. + struct yaffs_checkpt_chunk_hdr hdr;
  959. +
  960. + hdr.version = YAFFS_CHECKPOINT_VERSION;
  961. + hdr.seq = dev->checkpt_page_seq;
  962. + hdr.sum = dev->checkpt_sum;
  963. + hdr.xor = dev->checkpt_xor;
  964. +
  965. + dev->checkpt_byte_offs = sizeof(hdr);
  966. +
  967. + memcpy(dev->checkpt_buffer, &hdr, sizeof(hdr));
  968. +}
  969. +
  970. +static int yaffs2_checkpt_check_chunk_hdr(struct yaffs_dev *dev)
  971. +{
  972. + struct yaffs_checkpt_chunk_hdr hdr;
  973. +
  974. + memcpy(&hdr, dev->checkpt_buffer, sizeof(hdr));
  975. +
  976. + dev->checkpt_byte_offs = sizeof(hdr);
  977. +
  978. + return hdr.version == YAFFS_CHECKPOINT_VERSION &&
  979. + hdr.seq == dev->checkpt_page_seq &&
  980. + hdr.sum == dev->checkpt_sum &&
  981. + hdr.xor == dev->checkpt_xor;
  982. +}
  983. +
  984. +static int yaffs2_checkpt_space_ok(struct yaffs_dev *dev)
  985. +{
  986. + int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
  987. +
  988. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  989. + "checkpt blocks_avail = %d", blocks_avail);
  990. +
  991. + return (blocks_avail <= 0) ? 0 : 1;
  992. +}
  993. +
  994. +static int yaffs_checkpt_erase(struct yaffs_dev *dev)
  995. +{
  996. + int i;
  997. +
  998. + if (!dev->drv.drv_erase_fn)
  999. + return 0;
  1000. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1001. + "checking blocks %d to %d",
  1002. + dev->internal_start_block, dev->internal_end_block);
  1003. +
  1004. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  1005. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
  1006. + int offset_i = apply_block_offset(dev, i);
  1007. + int result;
  1008. +
  1009. + if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) {
  1010. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1011. + "erasing checkpt block %d", i);
  1012. +
  1013. + dev->n_erasures++;
  1014. +
  1015. + result = dev->drv.drv_erase_fn(dev, offset_i);
  1016. + if(result) {
  1017. + bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
  1018. + dev->n_erased_blocks++;
  1019. + dev->n_free_chunks +=
  1020. + dev->param.chunks_per_block;
  1021. + } else {
  1022. + dev->drv.drv_mark_bad_fn(dev, offset_i);
  1023. + bi->block_state = YAFFS_BLOCK_STATE_DEAD;
  1024. + }
  1025. + }
  1026. + }
  1027. +
  1028. + dev->blocks_in_checkpt = 0;
  1029. +
  1030. + return 1;
  1031. +}
  1032. +
  1033. +static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev)
  1034. +{
  1035. + int i;
  1036. + int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
  1037. +
  1038. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1039. + "allocating checkpt block: erased %d reserved %d avail %d next %d ",
  1040. + dev->n_erased_blocks, dev->param.n_reserved_blocks,
  1041. + blocks_avail, dev->checkpt_next_block);
  1042. +
  1043. + if (dev->checkpt_next_block >= 0 &&
  1044. + dev->checkpt_next_block <= dev->internal_end_block &&
  1045. + blocks_avail > 0) {
  1046. +
  1047. + for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
  1048. + i++) {
  1049. + struct yaffs_block_info *bi;
  1050. +
  1051. + bi = yaffs_get_block_info(dev, i);
  1052. + if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
  1053. + dev->checkpt_next_block = i + 1;
  1054. + dev->checkpt_cur_block = i;
  1055. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1056. + "allocating checkpt block %d", i);
  1057. + return;
  1058. + }
  1059. + }
  1060. + }
  1061. + yaffs_trace(YAFFS_TRACE_CHECKPOINT, "out of checkpt blocks");
  1062. +
  1063. + dev->checkpt_next_block = -1;
  1064. + dev->checkpt_cur_block = -1;
  1065. +}
  1066. +
  1067. +static void yaffs2_checkpt_find_block(struct yaffs_dev *dev)
  1068. +{
  1069. + int i;
  1070. + struct yaffs_ext_tags tags;
  1071. +
  1072. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1073. + "find next checkpt block: start: blocks %d next %d",
  1074. + dev->blocks_in_checkpt, dev->checkpt_next_block);
  1075. +
  1076. + if (dev->blocks_in_checkpt < dev->checkpt_max_blocks)
  1077. + for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
  1078. + i++) {
  1079. + int chunk = i * dev->param.chunks_per_block;
  1080. + enum yaffs_block_state state;
  1081. + u32 seq;
  1082. +
  1083. + dev->tagger.read_chunk_tags_fn(dev,
  1084. + apply_chunk_offset(dev, chunk),
  1085. + NULL, &tags);
  1086. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1087. + "find next checkpt block: search: block %d state %d oid %d seq %d eccr %d",
  1088. + i, (int) state,
  1089. + tags.obj_id, tags.seq_number,
  1090. + tags.ecc_result);
  1091. +
  1092. + if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
  1093. + continue;
  1094. +
  1095. + dev->tagger.query_block_fn(dev,
  1096. + apply_block_offset(dev, i),
  1097. + &state, &seq);
  1098. + if (state == YAFFS_BLOCK_STATE_DEAD)
  1099. + continue;
  1100. +
  1101. + /* Right kind of block */
  1102. + dev->checkpt_next_block = tags.obj_id;
  1103. + dev->checkpt_cur_block = i;
  1104. + dev->checkpt_block_list[dev->blocks_in_checkpt] = i;
  1105. + dev->blocks_in_checkpt++;
  1106. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1107. + "found checkpt block %d", i);
  1108. + return;
  1109. + }
  1110. +
  1111. + yaffs_trace(YAFFS_TRACE_CHECKPOINT, "found no more checkpt blocks");
  1112. +
  1113. + dev->checkpt_next_block = -1;
  1114. + dev->checkpt_cur_block = -1;
  1115. +}
  1116. +
  1117. +int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing)
  1118. +{
  1119. + int i;
  1120. +
  1121. + dev->checkpt_open_write = writing;
  1122. +
  1123. + /* Got the functions we need? */
  1124. + if (!dev->tagger.write_chunk_tags_fn ||
  1125. + !dev->tagger.read_chunk_tags_fn ||
  1126. + !dev->drv.drv_erase_fn ||
  1127. + !dev->drv.drv_mark_bad_fn)
  1128. + return 0;
  1129. +
  1130. + if (writing && !yaffs2_checkpt_space_ok(dev))
  1131. + return 0;
  1132. +
  1133. + if (!dev->checkpt_buffer)
  1134. + dev->checkpt_buffer =
  1135. + kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
  1136. + if (!dev->checkpt_buffer)
  1137. + return 0;
  1138. +
  1139. + dev->checkpt_page_seq = 0;
  1140. + dev->checkpt_byte_count = 0;
  1141. + dev->checkpt_sum = 0;
  1142. + dev->checkpt_xor = 0;
  1143. + dev->checkpt_cur_block = -1;
  1144. + dev->checkpt_cur_chunk = -1;
  1145. + dev->checkpt_next_block = dev->internal_start_block;
  1146. +
  1147. + if (writing) {
  1148. + memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
  1149. + yaffs2_checkpt_init_chunk_hdr(dev);
  1150. + return yaffs_checkpt_erase(dev);
  1151. + }
  1152. +
  1153. + /* Opening for a read */
  1154. + /* Set to a value that will kick off a read */
  1155. + dev->checkpt_byte_offs = dev->data_bytes_per_chunk;
  1156. + /* A checkpoint block list of 1 checkpoint block per 16 block is
  1157. + * (hopefully) going to be way more than we need */
  1158. + dev->blocks_in_checkpt = 0;
  1159. + dev->checkpt_max_blocks =
  1160. + (dev->internal_end_block - dev->internal_start_block) / 16 + 2;
  1161. + if (!dev->checkpt_block_list)
  1162. + dev->checkpt_block_list =
  1163. + kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS);
  1164. +
  1165. + if (!dev->checkpt_block_list)
  1166. + return 0;
  1167. +
  1168. + for (i = 0; i < dev->checkpt_max_blocks; i++)
  1169. + dev->checkpt_block_list[i] = -1;
  1170. +
  1171. + return 1;
  1172. +}
  1173. +
  1174. +int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum)
  1175. +{
  1176. + u32 composite_sum;
  1177. +
  1178. + composite_sum = (dev->checkpt_sum << 8) | (dev->checkpt_xor & 0xff);
  1179. + *sum = composite_sum;
  1180. + return 1;
  1181. +}
  1182. +
  1183. +static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev)
  1184. +{
  1185. + int chunk;
  1186. + int offset_chunk;
  1187. + struct yaffs_ext_tags tags;
  1188. +
  1189. + if (dev->checkpt_cur_block < 0) {
  1190. + yaffs2_checkpt_find_erased_block(dev);
  1191. + dev->checkpt_cur_chunk = 0;
  1192. + }
  1193. +
  1194. + if (dev->checkpt_cur_block < 0)
  1195. + return 0;
  1196. +
  1197. + tags.is_deleted = 0;
  1198. + tags.obj_id = dev->checkpt_next_block; /* Hint to next place to look */
  1199. + tags.chunk_id = dev->checkpt_page_seq + 1;
  1200. + tags.seq_number = YAFFS_SEQUENCE_CHECKPOINT_DATA;
  1201. + tags.n_bytes = dev->data_bytes_per_chunk;
  1202. + if (dev->checkpt_cur_chunk == 0) {
  1203. + /* First chunk we write for the block? Set block state to
  1204. + checkpoint */
  1205. + struct yaffs_block_info *bi =
  1206. + yaffs_get_block_info(dev, dev->checkpt_cur_block);
  1207. + bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
  1208. + dev->blocks_in_checkpt++;
  1209. + }
  1210. +
  1211. + chunk =
  1212. + dev->checkpt_cur_block * dev->param.chunks_per_block +
  1213. + dev->checkpt_cur_chunk;
  1214. +
  1215. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1216. + "checkpoint wite buffer nand %d(%d:%d) objid %d chId %d",
  1217. + chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk,
  1218. + tags.obj_id, tags.chunk_id);
  1219. +
  1220. + offset_chunk = apply_chunk_offset(dev, chunk);
  1221. +
  1222. + dev->n_page_writes++;
  1223. +
  1224. + dev->tagger.write_chunk_tags_fn(dev, offset_chunk,
  1225. + dev->checkpt_buffer, &tags);
  1226. + dev->checkpt_page_seq++;
  1227. + dev->checkpt_cur_chunk++;
  1228. + if (dev->checkpt_cur_chunk >= dev->param.chunks_per_block) {
  1229. + dev->checkpt_cur_chunk = 0;
  1230. + dev->checkpt_cur_block = -1;
  1231. + }
  1232. + memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
  1233. +
  1234. + yaffs2_checkpt_init_chunk_hdr(dev);
  1235. +
  1236. +
  1237. + return 1;
  1238. +}
  1239. +
  1240. +int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes)
  1241. +{
  1242. + int i = 0;
  1243. + int ok = 1;
  1244. + u8 *data_bytes = (u8 *) data;
  1245. +
  1246. + if (!dev->checkpt_buffer)
  1247. + return 0;
  1248. +
  1249. + if (!dev->checkpt_open_write)
  1250. + return -1;
  1251. +
  1252. + while (i < n_bytes && ok) {
  1253. + dev->checkpt_buffer[dev->checkpt_byte_offs] = *data_bytes;
  1254. + dev->checkpt_sum += *data_bytes;
  1255. + dev->checkpt_xor ^= *data_bytes;
  1256. +
  1257. + dev->checkpt_byte_offs++;
  1258. + i++;
  1259. + data_bytes++;
  1260. + dev->checkpt_byte_count++;
  1261. +
  1262. + if (dev->checkpt_byte_offs < 0 ||
  1263. + dev->checkpt_byte_offs >= dev->data_bytes_per_chunk)
  1264. + ok = yaffs2_checkpt_flush_buffer(dev);
  1265. + }
  1266. +
  1267. + return i;
  1268. +}
  1269. +
  1270. +int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
  1271. +{
  1272. + int i = 0;
  1273. + struct yaffs_ext_tags tags;
  1274. + int chunk;
  1275. + int offset_chunk;
  1276. + u8 *data_bytes = (u8 *) data;
  1277. +
  1278. + if (!dev->checkpt_buffer)
  1279. + return 0;
  1280. +
  1281. + if (dev->checkpt_open_write)
  1282. + return -1;
  1283. +
  1284. + while (i < n_bytes) {
  1285. +
  1286. + if (dev->checkpt_byte_offs < 0 ||
  1287. + dev->checkpt_byte_offs >= dev->data_bytes_per_chunk) {
  1288. +
  1289. + if (dev->checkpt_cur_block < 0) {
  1290. + yaffs2_checkpt_find_block(dev);
  1291. + dev->checkpt_cur_chunk = 0;
  1292. + }
  1293. +
  1294. + /* Bail out if we can't find a checpoint block */
  1295. + if (dev->checkpt_cur_block < 0)
  1296. + break;
  1297. +
  1298. + chunk = dev->checkpt_cur_block *
  1299. + dev->param.chunks_per_block +
  1300. + dev->checkpt_cur_chunk;
  1301. +
  1302. + offset_chunk = apply_chunk_offset(dev, chunk);
  1303. + dev->n_page_reads++;
  1304. +
  1305. + /* Read in the next chunk */
  1306. + dev->tagger.read_chunk_tags_fn(dev,
  1307. + offset_chunk,
  1308. + dev->checkpt_buffer,
  1309. + &tags);
  1310. +
  1311. + /* Bail out if the chunk is corrupted. */
  1312. + if (tags.chunk_id != (dev->checkpt_page_seq + 1) ||
  1313. + tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
  1314. + tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
  1315. + break;
  1316. +
  1317. + /* Bail out if it is not a checkpoint chunk. */
  1318. + if(!yaffs2_checkpt_check_chunk_hdr(dev))
  1319. + break;
  1320. +
  1321. + dev->checkpt_page_seq++;
  1322. + dev->checkpt_cur_chunk++;
  1323. +
  1324. + if (dev->checkpt_cur_chunk >=
  1325. + dev->param.chunks_per_block)
  1326. + dev->checkpt_cur_block = -1;
  1327. +
  1328. + }
  1329. +
  1330. + *data_bytes = dev->checkpt_buffer[dev->checkpt_byte_offs];
  1331. + dev->checkpt_sum += *data_bytes;
  1332. + dev->checkpt_xor ^= *data_bytes;
  1333. + dev->checkpt_byte_offs++;
  1334. + i++;
  1335. + data_bytes++;
  1336. + dev->checkpt_byte_count++;
  1337. + }
  1338. +
  1339. + return i; /* Number of bytes read */
  1340. +}
  1341. +
  1342. +int yaffs_checkpt_close(struct yaffs_dev *dev)
  1343. +{
  1344. + int i;
  1345. +
  1346. + if (dev->checkpt_open_write) {
  1347. + if (dev->checkpt_byte_offs !=
  1348. + sizeof(sizeof(struct yaffs_checkpt_chunk_hdr)))
  1349. + yaffs2_checkpt_flush_buffer(dev);
  1350. + } else if (dev->checkpt_block_list) {
  1351. + for (i = 0;
  1352. + i < dev->blocks_in_checkpt &&
  1353. + dev->checkpt_block_list[i] >= 0; i++) {
  1354. + int blk = dev->checkpt_block_list[i];
  1355. + struct yaffs_block_info *bi = NULL;
  1356. +
  1357. + if (dev->internal_start_block <= blk &&
  1358. + blk <= dev->internal_end_block)
  1359. + bi = yaffs_get_block_info(dev, blk);
  1360. + if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY)
  1361. + bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
  1362. + }
  1363. + }
  1364. +
  1365. + dev->n_free_chunks -=
  1366. + dev->blocks_in_checkpt * dev->param.chunks_per_block;
  1367. + dev->n_erased_blocks -= dev->blocks_in_checkpt;
  1368. +
  1369. + yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d",
  1370. + dev->checkpt_byte_count);
  1371. +
  1372. + if (dev->checkpt_buffer)
  1373. + return 1;
  1374. + else
  1375. + return 0;
  1376. +}
  1377. +
  1378. +int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev)
  1379. +{
  1380. + /* Erase the checkpoint data */
  1381. +
  1382. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1383. + "checkpoint invalidate of %d blocks",
  1384. + dev->blocks_in_checkpt);
  1385. +
  1386. + return yaffs_checkpt_erase(dev);
  1387. +}
  1388. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_checkptrw.h linux-3.18.14/fs/yaffs2/yaffs_checkptrw.h
  1389. --- linux-3.18.14.orig/fs/yaffs2/yaffs_checkptrw.h 1970-01-01 01:00:00.000000000 +0100
  1390. +++ linux-3.18.14/fs/yaffs2/yaffs_checkptrw.h 2015-06-14 21:23:22.000000000 +0200
  1391. @@ -0,0 +1,33 @@
  1392. +/*
  1393. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  1394. + *
  1395. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1396. + * for Toby Churchill Ltd and Brightstar Engineering
  1397. + *
  1398. + * Created by Charles Manning <charles@aleph1.co.uk>
  1399. + *
  1400. + * This program is free software; you can redistribute it and/or modify
  1401. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  1402. + * published by the Free Software Foundation.
  1403. + *
  1404. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  1405. + */
  1406. +
  1407. +#ifndef __YAFFS_CHECKPTRW_H__
  1408. +#define __YAFFS_CHECKPTRW_H__
  1409. +
  1410. +#include "yaffs_guts.h"
  1411. +
  1412. +int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing);
  1413. +
  1414. +int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes);
  1415. +
  1416. +int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes);
  1417. +
  1418. +int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum);
  1419. +
  1420. +int yaffs_checkpt_close(struct yaffs_dev *dev);
  1421. +
  1422. +int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev);
  1423. +
  1424. +#endif
  1425. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_ecc.c linux-3.18.14/fs/yaffs2/yaffs_ecc.c
  1426. --- linux-3.18.14.orig/fs/yaffs2/yaffs_ecc.c 1970-01-01 01:00:00.000000000 +0100
  1427. +++ linux-3.18.14/fs/yaffs2/yaffs_ecc.c 2015-06-14 21:23:22.000000000 +0200
  1428. @@ -0,0 +1,281 @@
  1429. +/*
  1430. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  1431. + *
  1432. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1433. + * for Toby Churchill Ltd and Brightstar Engineering
  1434. + *
  1435. + * Created by Charles Manning <charles@aleph1.co.uk>
  1436. + *
  1437. + * This program is free software; you can redistribute it and/or modify
  1438. + * it under the terms of the GNU General Public License version 2 as
  1439. + * published by the Free Software Foundation.
  1440. + */
  1441. +
  1442. +/*
  1443. + * This code implements the ECC algorithm used in SmartMedia.
  1444. + *
  1445. + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
  1446. + * The two unused bit are set to 1.
  1447. + * The ECC can correct single bit errors in a 256-byte page of data. Thus, two
  1448. + * such ECC blocks are used on a 512-byte NAND page.
  1449. + *
  1450. + */
  1451. +
  1452. +#include "yportenv.h"
  1453. +
  1454. +#include "yaffs_ecc.h"
  1455. +
  1456. +/* Table generated by gen-ecc.c
  1457. + * Using a table means we do not have to calculate p1..p4 and p1'..p4'
  1458. + * for each byte of data. These are instead provided in a table in bits7..2.
  1459. + * Bit 0 of each entry indicates whether the entry has an odd or even parity,
  1460. + * and therefore this bytes influence on the line parity.
  1461. + */
  1462. +
  1463. +static const unsigned char column_parity_table[] = {
  1464. + 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
  1465. + 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
  1466. + 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
  1467. + 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
  1468. + 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
  1469. + 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
  1470. + 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
  1471. + 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
  1472. + 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
  1473. + 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
  1474. + 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
  1475. + 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
  1476. + 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
  1477. + 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
  1478. + 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
  1479. + 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
  1480. + 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
  1481. + 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
  1482. + 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
  1483. + 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
  1484. + 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
  1485. + 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
  1486. + 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
  1487. + 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
  1488. + 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
  1489. + 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
  1490. + 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
  1491. + 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
  1492. + 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
  1493. + 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
  1494. + 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
  1495. + 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
  1496. +};
  1497. +
  1498. +
  1499. +/* Calculate the ECC for a 256-byte block of data */
  1500. +void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc)
  1501. +{
  1502. + unsigned int i;
  1503. + unsigned char col_parity = 0;
  1504. + unsigned char line_parity = 0;
  1505. + unsigned char line_parity_prime = 0;
  1506. + unsigned char t;
  1507. + unsigned char b;
  1508. +
  1509. + for (i = 0; i < 256; i++) {
  1510. + b = column_parity_table[*data++];
  1511. + col_parity ^= b;
  1512. +
  1513. + if (b & 0x01) { /* odd number of bits in the byte */
  1514. + line_parity ^= i;
  1515. + line_parity_prime ^= ~i;
  1516. + }
  1517. + }
  1518. +
  1519. + ecc[2] = (~col_parity) | 0x03;
  1520. +
  1521. + t = 0;
  1522. + if (line_parity & 0x80)
  1523. + t |= 0x80;
  1524. + if (line_parity_prime & 0x80)
  1525. + t |= 0x40;
  1526. + if (line_parity & 0x40)
  1527. + t |= 0x20;
  1528. + if (line_parity_prime & 0x40)
  1529. + t |= 0x10;
  1530. + if (line_parity & 0x20)
  1531. + t |= 0x08;
  1532. + if (line_parity_prime & 0x20)
  1533. + t |= 0x04;
  1534. + if (line_parity & 0x10)
  1535. + t |= 0x02;
  1536. + if (line_parity_prime & 0x10)
  1537. + t |= 0x01;
  1538. + ecc[1] = ~t;
  1539. +
  1540. + t = 0;
  1541. + if (line_parity & 0x08)
  1542. + t |= 0x80;
  1543. + if (line_parity_prime & 0x08)
  1544. + t |= 0x40;
  1545. + if (line_parity & 0x04)
  1546. + t |= 0x20;
  1547. + if (line_parity_prime & 0x04)
  1548. + t |= 0x10;
  1549. + if (line_parity & 0x02)
  1550. + t |= 0x08;
  1551. + if (line_parity_prime & 0x02)
  1552. + t |= 0x04;
  1553. + if (line_parity & 0x01)
  1554. + t |= 0x02;
  1555. + if (line_parity_prime & 0x01)
  1556. + t |= 0x01;
  1557. + ecc[0] = ~t;
  1558. +
  1559. +}
  1560. +
  1561. +/* Correct the ECC on a 256 byte block of data */
  1562. +
  1563. +int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
  1564. + const unsigned char *test_ecc)
  1565. +{
  1566. + unsigned char d0, d1, d2; /* deltas */
  1567. +
  1568. + d0 = read_ecc[0] ^ test_ecc[0];
  1569. + d1 = read_ecc[1] ^ test_ecc[1];
  1570. + d2 = read_ecc[2] ^ test_ecc[2];
  1571. +
  1572. + if ((d0 | d1 | d2) == 0)
  1573. + return 0; /* no error */
  1574. +
  1575. + if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
  1576. + ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
  1577. + ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) {
  1578. + /* Single bit (recoverable) error in data */
  1579. +
  1580. + unsigned byte;
  1581. + unsigned bit;
  1582. +
  1583. + bit = byte = 0;
  1584. +
  1585. + if (d1 & 0x80)
  1586. + byte |= 0x80;
  1587. + if (d1 & 0x20)
  1588. + byte |= 0x40;
  1589. + if (d1 & 0x08)
  1590. + byte |= 0x20;
  1591. + if (d1 & 0x02)
  1592. + byte |= 0x10;
  1593. + if (d0 & 0x80)
  1594. + byte |= 0x08;
  1595. + if (d0 & 0x20)
  1596. + byte |= 0x04;
  1597. + if (d0 & 0x08)
  1598. + byte |= 0x02;
  1599. + if (d0 & 0x02)
  1600. + byte |= 0x01;
  1601. +
  1602. + if (d2 & 0x80)
  1603. + bit |= 0x04;
  1604. + if (d2 & 0x20)
  1605. + bit |= 0x02;
  1606. + if (d2 & 0x08)
  1607. + bit |= 0x01;
  1608. +
  1609. + data[byte] ^= (1 << bit);
  1610. +
  1611. + return 1; /* Corrected the error */
  1612. + }
  1613. +
  1614. + if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) {
  1615. + /* Reccoverable error in ecc */
  1616. +
  1617. + read_ecc[0] = test_ecc[0];
  1618. + read_ecc[1] = test_ecc[1];
  1619. + read_ecc[2] = test_ecc[2];
  1620. +
  1621. + return 1; /* Corrected the error */
  1622. + }
  1623. +
  1624. + /* Unrecoverable error */
  1625. +
  1626. + return -1;
  1627. +
  1628. +}
  1629. +
  1630. +/*
  1631. + * ECCxxxOther does ECC calcs on arbitrary n bytes of data
  1632. + */
  1633. +void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
  1634. + struct yaffs_ecc_other *ecc_other)
  1635. +{
  1636. + unsigned int i;
  1637. + unsigned char col_parity = 0;
  1638. + unsigned line_parity = 0;
  1639. + unsigned line_parity_prime = 0;
  1640. + unsigned char b;
  1641. +
  1642. + for (i = 0; i < n_bytes; i++) {
  1643. + b = column_parity_table[*data++];
  1644. + col_parity ^= b;
  1645. +
  1646. + if (b & 0x01) {
  1647. + /* odd number of bits in the byte */
  1648. + line_parity ^= i;
  1649. + line_parity_prime ^= ~i;
  1650. + }
  1651. +
  1652. + }
  1653. +
  1654. + ecc_other->col_parity = (col_parity >> 2) & 0x3f;
  1655. + ecc_other->line_parity = line_parity;
  1656. + ecc_other->line_parity_prime = line_parity_prime;
  1657. +}
  1658. +
  1659. +int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
  1660. + struct yaffs_ecc_other *read_ecc,
  1661. + const struct yaffs_ecc_other *test_ecc)
  1662. +{
  1663. + unsigned char delta_col; /* column parity delta */
  1664. + unsigned delta_line; /* line parity delta */
  1665. + unsigned delta_line_prime; /* line parity delta */
  1666. + unsigned bit;
  1667. +
  1668. + delta_col = read_ecc->col_parity ^ test_ecc->col_parity;
  1669. + delta_line = read_ecc->line_parity ^ test_ecc->line_parity;
  1670. + delta_line_prime =
  1671. + read_ecc->line_parity_prime ^ test_ecc->line_parity_prime;
  1672. +
  1673. + if ((delta_col | delta_line | delta_line_prime) == 0)
  1674. + return 0; /* no error */
  1675. +
  1676. + if (delta_line == ~delta_line_prime &&
  1677. + (((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) {
  1678. + /* Single bit (recoverable) error in data */
  1679. +
  1680. + bit = 0;
  1681. +
  1682. + if (delta_col & 0x20)
  1683. + bit |= 0x04;
  1684. + if (delta_col & 0x08)
  1685. + bit |= 0x02;
  1686. + if (delta_col & 0x02)
  1687. + bit |= 0x01;
  1688. +
  1689. + if (delta_line >= n_bytes)
  1690. + return -1;
  1691. +
  1692. + data[delta_line] ^= (1 << bit);
  1693. +
  1694. + return 1; /* corrected */
  1695. + }
  1696. +
  1697. + if ((hweight32(delta_line) +
  1698. + hweight32(delta_line_prime) +
  1699. + hweight8(delta_col)) == 1) {
  1700. + /* Reccoverable error in ecc */
  1701. +
  1702. + *read_ecc = *test_ecc;
  1703. + return 1; /* corrected */
  1704. + }
  1705. +
  1706. + /* Unrecoverable error */
  1707. +
  1708. + return -1;
  1709. +}
  1710. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_ecc.h linux-3.18.14/fs/yaffs2/yaffs_ecc.h
  1711. --- linux-3.18.14.orig/fs/yaffs2/yaffs_ecc.h 1970-01-01 01:00:00.000000000 +0100
  1712. +++ linux-3.18.14/fs/yaffs2/yaffs_ecc.h 2015-06-14 21:23:22.000000000 +0200
  1713. @@ -0,0 +1,44 @@
  1714. +/*
  1715. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  1716. + *
  1717. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1718. + * for Toby Churchill Ltd and Brightstar Engineering
  1719. + *
  1720. + * Created by Charles Manning <charles@aleph1.co.uk>
  1721. + *
  1722. + * This program is free software; you can redistribute it and/or modify
  1723. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  1724. + * published by the Free Software Foundation.
  1725. + *
  1726. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  1727. + */
  1728. +
  1729. +/*
  1730. + * This code implements the ECC algorithm used in SmartMedia.
  1731. + *
  1732. + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
  1733. + * The two unused bit are set to 1.
  1734. + * The ECC can correct single bit errors in a 256-byte page of data.
  1735. + * Thus, two such ECC blocks are used on a 512-byte NAND page.
  1736. + *
  1737. + */
  1738. +
  1739. +#ifndef __YAFFS_ECC_H__
  1740. +#define __YAFFS_ECC_H__
  1741. +
  1742. +struct yaffs_ecc_other {
  1743. + unsigned char col_parity;
  1744. + unsigned line_parity;
  1745. + unsigned line_parity_prime;
  1746. +};
  1747. +
  1748. +void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc);
  1749. +int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
  1750. + const unsigned char *test_ecc);
  1751. +
  1752. +void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
  1753. + struct yaffs_ecc_other *ecc);
  1754. +int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
  1755. + struct yaffs_ecc_other *read_ecc,
  1756. + const struct yaffs_ecc_other *test_ecc);
  1757. +#endif
  1758. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_getblockinfo.h linux-3.18.14/fs/yaffs2/yaffs_getblockinfo.h
  1759. --- linux-3.18.14.orig/fs/yaffs2/yaffs_getblockinfo.h 1970-01-01 01:00:00.000000000 +0100
  1760. +++ linux-3.18.14/fs/yaffs2/yaffs_getblockinfo.h 2015-06-14 21:23:22.000000000 +0200
  1761. @@ -0,0 +1,35 @@
  1762. +/*
  1763. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  1764. + *
  1765. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1766. + * for Toby Churchill Ltd and Brightstar Engineering
  1767. + *
  1768. + * Created by Charles Manning <charles@aleph1.co.uk>
  1769. + *
  1770. + * This program is free software; you can redistribute it and/or modify
  1771. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  1772. + * published by the Free Software Foundation.
  1773. + *
  1774. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  1775. + */
  1776. +
  1777. +#ifndef __YAFFS_GETBLOCKINFO_H__
  1778. +#define __YAFFS_GETBLOCKINFO_H__
  1779. +
  1780. +#include "yaffs_guts.h"
  1781. +#include "yaffs_trace.h"
  1782. +
  1783. +/* Function to manipulate block info */
  1784. +static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev
  1785. + *dev, int blk)
  1786. +{
  1787. + if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
  1788. + yaffs_trace(YAFFS_TRACE_ERROR,
  1789. + "**>> yaffs: get_block_info block %d is not valid",
  1790. + blk);
  1791. + BUG();
  1792. + }
  1793. + return &dev->block_info[blk - dev->internal_start_block];
  1794. +}
  1795. +
  1796. +#endif
  1797. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_guts.c linux-3.18.14/fs/yaffs2/yaffs_guts.c
  1798. --- linux-3.18.14.orig/fs/yaffs2/yaffs_guts.c 1970-01-01 01:00:00.000000000 +0100
  1799. +++ linux-3.18.14/fs/yaffs2/yaffs_guts.c 2015-06-14 21:23:22.000000000 +0200
  1800. @@ -0,0 +1,5140 @@
  1801. +/*
  1802. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  1803. + *
  1804. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1805. + * for Toby Churchill Ltd and Brightstar Engineering
  1806. + *
  1807. + * Created by Charles Manning <charles@aleph1.co.uk>
  1808. + *
  1809. + * This program is free software; you can redistribute it and/or modify
  1810. + * it under the terms of the GNU General Public License version 2 as
  1811. + * published by the Free Software Foundation.
  1812. + */
  1813. +
  1814. +#include "yportenv.h"
  1815. +#include "yaffs_trace.h"
  1816. +
  1817. +#include "yaffs_guts.h"
  1818. +#include "yaffs_getblockinfo.h"
  1819. +#include "yaffs_tagscompat.h"
  1820. +#include "yaffs_tagsmarshall.h"
  1821. +#include "yaffs_nand.h"
  1822. +#include "yaffs_yaffs1.h"
  1823. +#include "yaffs_yaffs2.h"
  1824. +#include "yaffs_bitmap.h"
  1825. +#include "yaffs_verify.h"
  1826. +#include "yaffs_nand.h"
  1827. +#include "yaffs_packedtags2.h"
  1828. +#include "yaffs_nameval.h"
  1829. +#include "yaffs_allocator.h"
  1830. +#include "yaffs_attribs.h"
  1831. +#include "yaffs_summary.h"
  1832. +
  1833. +/* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
  1834. +#define YAFFS_GC_GOOD_ENOUGH 2
  1835. +#define YAFFS_GC_PASSIVE_THRESHOLD 4
  1836. +
  1837. +#include "yaffs_ecc.h"
  1838. +
  1839. +/* Forward declarations */
  1840. +
  1841. +static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
  1842. + const u8 *buffer, int n_bytes, int use_reserve);
  1843. +
  1844. +static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
  1845. + int buffer_size);
  1846. +
  1847. +/* Function to calculate chunk and offset */
  1848. +
  1849. +void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
  1850. + int *chunk_out, u32 *offset_out)
  1851. +{
  1852. + int chunk;
  1853. + u32 offset;
  1854. +
  1855. + chunk = (u32) (addr >> dev->chunk_shift);
  1856. +
  1857. + if (dev->chunk_div == 1) {
  1858. + /* easy power of 2 case */
  1859. + offset = (u32) (addr & dev->chunk_mask);
  1860. + } else {
  1861. + /* Non power-of-2 case */
  1862. +
  1863. + loff_t chunk_base;
  1864. +
  1865. + chunk /= dev->chunk_div;
  1866. +
  1867. + chunk_base = ((loff_t) chunk) * dev->data_bytes_per_chunk;
  1868. + offset = (u32) (addr - chunk_base);
  1869. + }
  1870. +
  1871. + *chunk_out = chunk;
  1872. + *offset_out = offset;
  1873. +}
  1874. +
  1875. +/* Function to return the number of shifts for a power of 2 greater than or
  1876. + * equal to the given number
  1877. + * Note we don't try to cater for all possible numbers and this does not have to
  1878. + * be hellishly efficient.
  1879. + */
  1880. +
  1881. +static inline u32 calc_shifts_ceiling(u32 x)
  1882. +{
  1883. + int extra_bits;
  1884. + int shifts;
  1885. +
  1886. + shifts = extra_bits = 0;
  1887. +
  1888. + while (x > 1) {
  1889. + if (x & 1)
  1890. + extra_bits++;
  1891. + x >>= 1;
  1892. + shifts++;
  1893. + }
  1894. +
  1895. + if (extra_bits)
  1896. + shifts++;
  1897. +
  1898. + return shifts;
  1899. +}
  1900. +
  1901. +/* Function to return the number of shifts to get a 1 in bit 0
  1902. + */
  1903. +
  1904. +static inline u32 calc_shifts(u32 x)
  1905. +{
  1906. + u32 shifts;
  1907. +
  1908. + shifts = 0;
  1909. +
  1910. + if (!x)
  1911. + return 0;
  1912. +
  1913. + while (!(x & 1)) {
  1914. + x >>= 1;
  1915. + shifts++;
  1916. + }
  1917. +
  1918. + return shifts;
  1919. +}
  1920. +
  1921. +/*
  1922. + * Temporary buffer manipulations.
  1923. + */
  1924. +
  1925. +static int yaffs_init_tmp_buffers(struct yaffs_dev *dev)
  1926. +{
  1927. + int i;
  1928. + u8 *buf = (u8 *) 1;
  1929. +
  1930. + memset(dev->temp_buffer, 0, sizeof(dev->temp_buffer));
  1931. +
  1932. + for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
  1933. + dev->temp_buffer[i].in_use = 0;
  1934. + buf = kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
  1935. + dev->temp_buffer[i].buffer = buf;
  1936. + }
  1937. +
  1938. + return buf ? YAFFS_OK : YAFFS_FAIL;
  1939. +}
  1940. +
  1941. +u8 *yaffs_get_temp_buffer(struct yaffs_dev * dev)
  1942. +{
  1943. + int i;
  1944. +
  1945. + dev->temp_in_use++;
  1946. + if (dev->temp_in_use > dev->max_temp)
  1947. + dev->max_temp = dev->temp_in_use;
  1948. +
  1949. + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
  1950. + if (dev->temp_buffer[i].in_use == 0) {
  1951. + dev->temp_buffer[i].in_use = 1;
  1952. + return dev->temp_buffer[i].buffer;
  1953. + }
  1954. + }
  1955. +
  1956. + yaffs_trace(YAFFS_TRACE_BUFFERS, "Out of temp buffers");
  1957. + /*
  1958. + * If we got here then we have to allocate an unmanaged one
  1959. + * This is not good.
  1960. + */
  1961. +
  1962. + dev->unmanaged_buffer_allocs++;
  1963. + return kmalloc(dev->data_bytes_per_chunk, GFP_NOFS);
  1964. +
  1965. +}
  1966. +
  1967. +void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer)
  1968. +{
  1969. + int i;
  1970. +
  1971. + dev->temp_in_use--;
  1972. +
  1973. + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
  1974. + if (dev->temp_buffer[i].buffer == buffer) {
  1975. + dev->temp_buffer[i].in_use = 0;
  1976. + return;
  1977. + }
  1978. + }
  1979. +
  1980. + if (buffer) {
  1981. + /* assume it is an unmanaged one. */
  1982. + yaffs_trace(YAFFS_TRACE_BUFFERS,
  1983. + "Releasing unmanaged temp buffer");
  1984. + kfree(buffer);
  1985. + dev->unmanaged_buffer_deallocs++;
  1986. + }
  1987. +
  1988. +}
  1989. +
  1990. +/*
  1991. + * Functions for robustisizing TODO
  1992. + *
  1993. + */
  1994. +
  1995. +static void yaffs_handle_chunk_wr_ok(struct yaffs_dev *dev, int nand_chunk,
  1996. + const u8 *data,
  1997. + const struct yaffs_ext_tags *tags)
  1998. +{
  1999. + (void) dev;
  2000. + (void) nand_chunk;
  2001. + (void) data;
  2002. + (void) tags;
  2003. +}
  2004. +
  2005. +static void yaffs_handle_chunk_update(struct yaffs_dev *dev, int nand_chunk,
  2006. + const struct yaffs_ext_tags *tags)
  2007. +{
  2008. + (void) dev;
  2009. + (void) nand_chunk;
  2010. + (void) tags;
  2011. +}
  2012. +
  2013. +void yaffs_handle_chunk_error(struct yaffs_dev *dev,
  2014. + struct yaffs_block_info *bi)
  2015. +{
  2016. + if (!bi->gc_prioritise) {
  2017. + bi->gc_prioritise = 1;
  2018. + dev->has_pending_prioritised_gc = 1;
  2019. + bi->chunk_error_strikes++;
  2020. +
  2021. + if (bi->chunk_error_strikes > 3) {
  2022. + bi->needs_retiring = 1; /* Too many stikes, so retire */
  2023. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2024. + "yaffs: Block struck out");
  2025. +
  2026. + }
  2027. + }
  2028. +}
  2029. +
  2030. +static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk,
  2031. + int erased_ok)
  2032. +{
  2033. + int flash_block = nand_chunk / dev->param.chunks_per_block;
  2034. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
  2035. +
  2036. + yaffs_handle_chunk_error(dev, bi);
  2037. +
  2038. + if (erased_ok) {
  2039. + /* Was an actual write failure,
  2040. + * so mark the block for retirement.*/
  2041. + bi->needs_retiring = 1;
  2042. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  2043. + "**>> Block %d needs retiring", flash_block);
  2044. + }
  2045. +
  2046. + /* Delete the chunk */
  2047. + yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
  2048. + yaffs_skip_rest_of_block(dev);
  2049. +}
  2050. +
  2051. +/*
  2052. + * Verification code
  2053. + */
  2054. +
  2055. +/*
  2056. + * Simple hash function. Needs to have a reasonable spread
  2057. + */
  2058. +
  2059. +static inline int yaffs_hash_fn(int n)
  2060. +{
  2061. + if (n < 0)
  2062. + n = -n;
  2063. + return n % YAFFS_NOBJECT_BUCKETS;
  2064. +}
  2065. +
  2066. +/*
  2067. + * Access functions to useful fake objects.
  2068. + * Note that root might have a presence in NAND if permissions are set.
  2069. + */
  2070. +
  2071. +struct yaffs_obj *yaffs_root(struct yaffs_dev *dev)
  2072. +{
  2073. + return dev->root_dir;
  2074. +}
  2075. +
  2076. +struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev)
  2077. +{
  2078. + return dev->lost_n_found;
  2079. +}
  2080. +
  2081. +/*
  2082. + * Erased NAND checking functions
  2083. + */
  2084. +
  2085. +int yaffs_check_ff(u8 *buffer, int n_bytes)
  2086. +{
  2087. + /* Horrible, slow implementation */
  2088. + while (n_bytes--) {
  2089. + if (*buffer != 0xff)
  2090. + return 0;
  2091. + buffer++;
  2092. + }
  2093. + return 1;
  2094. +}
  2095. +
  2096. +static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk)
  2097. +{
  2098. + int retval = YAFFS_OK;
  2099. + u8 *data = yaffs_get_temp_buffer(dev);
  2100. + struct yaffs_ext_tags tags;
  2101. + int result;
  2102. +
  2103. + result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);
  2104. +
  2105. + if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
  2106. + retval = YAFFS_FAIL;
  2107. +
  2108. + if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) ||
  2109. + tags.chunk_used) {
  2110. + yaffs_trace(YAFFS_TRACE_NANDACCESS,
  2111. + "Chunk %d not erased", nand_chunk);
  2112. + retval = YAFFS_FAIL;
  2113. + }
  2114. +
  2115. + yaffs_release_temp_buffer(dev, data);
  2116. +
  2117. + return retval;
  2118. +
  2119. +}
  2120. +
  2121. +static int yaffs_verify_chunk_written(struct yaffs_dev *dev,
  2122. + int nand_chunk,
  2123. + const u8 *data,
  2124. + struct yaffs_ext_tags *tags)
  2125. +{
  2126. + int retval = YAFFS_OK;
  2127. + struct yaffs_ext_tags temp_tags;
  2128. + u8 *buffer = yaffs_get_temp_buffer(dev);
  2129. + int result;
  2130. +
  2131. + result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags);
  2132. + if (memcmp(buffer, data, dev->data_bytes_per_chunk) ||
  2133. + temp_tags.obj_id != tags->obj_id ||
  2134. + temp_tags.chunk_id != tags->chunk_id ||
  2135. + temp_tags.n_bytes != tags->n_bytes)
  2136. + retval = YAFFS_FAIL;
  2137. +
  2138. + yaffs_release_temp_buffer(dev, buffer);
  2139. +
  2140. + return retval;
  2141. +}
  2142. +
  2143. +
  2144. +int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks)
  2145. +{
  2146. + int reserved_chunks;
  2147. + int reserved_blocks = dev->param.n_reserved_blocks;
  2148. + int checkpt_blocks;
  2149. +
  2150. + checkpt_blocks = yaffs_calc_checkpt_blocks_required(dev);
  2151. +
  2152. + reserved_chunks =
  2153. + (reserved_blocks + checkpt_blocks) * dev->param.chunks_per_block;
  2154. +
  2155. + return (dev->n_free_chunks > (reserved_chunks + n_chunks));
  2156. +}
  2157. +
  2158. +static int yaffs_find_alloc_block(struct yaffs_dev *dev)
  2159. +{
  2160. + int i;
  2161. + struct yaffs_block_info *bi;
  2162. +
  2163. + if (dev->n_erased_blocks < 1) {
  2164. + /* Hoosterman we've got a problem.
  2165. + * Can't get space to gc
  2166. + */
  2167. + yaffs_trace(YAFFS_TRACE_ERROR,
  2168. + "yaffs tragedy: no more erased blocks");
  2169. +
  2170. + return -1;
  2171. + }
  2172. +
  2173. + /* Find an empty block. */
  2174. +
  2175. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  2176. + dev->alloc_block_finder++;
  2177. + if (dev->alloc_block_finder < dev->internal_start_block
  2178. + || dev->alloc_block_finder > dev->internal_end_block) {
  2179. + dev->alloc_block_finder = dev->internal_start_block;
  2180. + }
  2181. +
  2182. + bi = yaffs_get_block_info(dev, dev->alloc_block_finder);
  2183. +
  2184. + if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
  2185. + bi->block_state = YAFFS_BLOCK_STATE_ALLOCATING;
  2186. + dev->seq_number++;
  2187. + bi->seq_number = dev->seq_number;
  2188. + dev->n_erased_blocks--;
  2189. + yaffs_trace(YAFFS_TRACE_ALLOCATE,
  2190. + "Allocated block %d, seq %d, %d left" ,
  2191. + dev->alloc_block_finder, dev->seq_number,
  2192. + dev->n_erased_blocks);
  2193. + return dev->alloc_block_finder;
  2194. + }
  2195. + }
  2196. +
  2197. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2198. + "yaffs tragedy: no more erased blocks, but there should have been %d",
  2199. + dev->n_erased_blocks);
  2200. +
  2201. + return -1;
  2202. +}
  2203. +
  2204. +static int yaffs_alloc_chunk(struct yaffs_dev *dev, int use_reserver,
  2205. + struct yaffs_block_info **block_ptr)
  2206. +{
  2207. + int ret_val;
  2208. + struct yaffs_block_info *bi;
  2209. +
  2210. + if (dev->alloc_block < 0) {
  2211. + /* Get next block to allocate off */
  2212. + dev->alloc_block = yaffs_find_alloc_block(dev);
  2213. + dev->alloc_page = 0;
  2214. + }
  2215. +
  2216. + if (!use_reserver && !yaffs_check_alloc_available(dev, 1)) {
  2217. + /* No space unless we're allowed to use the reserve. */
  2218. + return -1;
  2219. + }
  2220. +
  2221. + if (dev->n_erased_blocks < dev->param.n_reserved_blocks
  2222. + && dev->alloc_page == 0)
  2223. + yaffs_trace(YAFFS_TRACE_ALLOCATE, "Allocating reserve");
  2224. +
  2225. + /* Next page please.... */
  2226. + if (dev->alloc_block >= 0) {
  2227. + bi = yaffs_get_block_info(dev, dev->alloc_block);
  2228. +
  2229. + ret_val = (dev->alloc_block * dev->param.chunks_per_block) +
  2230. + dev->alloc_page;
  2231. + bi->pages_in_use++;
  2232. + yaffs_set_chunk_bit(dev, dev->alloc_block, dev->alloc_page);
  2233. +
  2234. + dev->alloc_page++;
  2235. +
  2236. + dev->n_free_chunks--;
  2237. +
  2238. + /* If the block is full set the state to full */
  2239. + if (dev->alloc_page >= dev->param.chunks_per_block) {
  2240. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  2241. + dev->alloc_block = -1;
  2242. + }
  2243. +
  2244. + if (block_ptr)
  2245. + *block_ptr = bi;
  2246. +
  2247. + return ret_val;
  2248. + }
  2249. +
  2250. + yaffs_trace(YAFFS_TRACE_ERROR,
  2251. + "!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!");
  2252. +
  2253. + return -1;
  2254. +}
  2255. +
  2256. +static int yaffs_get_erased_chunks(struct yaffs_dev *dev)
  2257. +{
  2258. + int n;
  2259. +
  2260. + n = dev->n_erased_blocks * dev->param.chunks_per_block;
  2261. +
  2262. + if (dev->alloc_block > 0)
  2263. + n += (dev->param.chunks_per_block - dev->alloc_page);
  2264. +
  2265. + return n;
  2266. +
  2267. +}
  2268. +
  2269. +/*
  2270. + * yaffs_skip_rest_of_block() skips over the rest of the allocation block
  2271. + * if we don't want to write to it.
  2272. + */
  2273. +void yaffs_skip_rest_of_block(struct yaffs_dev *dev)
  2274. +{
  2275. + struct yaffs_block_info *bi;
  2276. +
  2277. + if (dev->alloc_block > 0) {
  2278. + bi = yaffs_get_block_info(dev, dev->alloc_block);
  2279. + if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) {
  2280. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  2281. + dev->alloc_block = -1;
  2282. + }
  2283. + }
  2284. +}
  2285. +
  2286. +static int yaffs_write_new_chunk(struct yaffs_dev *dev,
  2287. + const u8 *data,
  2288. + struct yaffs_ext_tags *tags, int use_reserver)
  2289. +{
  2290. + int attempts = 0;
  2291. + int write_ok = 0;
  2292. + int chunk;
  2293. +
  2294. + yaffs2_checkpt_invalidate(dev);
  2295. +
  2296. + do {
  2297. + struct yaffs_block_info *bi = 0;
  2298. + int erased_ok = 0;
  2299. +
  2300. + chunk = yaffs_alloc_chunk(dev, use_reserver, &bi);
  2301. + if (chunk < 0) {
  2302. + /* no space */
  2303. + break;
  2304. + }
  2305. +
  2306. + /* First check this chunk is erased, if it needs
  2307. + * checking. The checking policy (unless forced
  2308. + * always on) is as follows:
  2309. + *
  2310. + * Check the first page we try to write in a block.
  2311. + * If the check passes then we don't need to check any
  2312. + * more. If the check fails, we check again...
  2313. + * If the block has been erased, we don't need to check.
  2314. + *
  2315. + * However, if the block has been prioritised for gc,
  2316. + * then we think there might be something odd about
  2317. + * this block and stop using it.
  2318. + *
  2319. + * Rationale: We should only ever see chunks that have
  2320. + * not been erased if there was a partially written
  2321. + * chunk due to power loss. This checking policy should
  2322. + * catch that case with very few checks and thus save a
  2323. + * lot of checks that are most likely not needed.
  2324. + *
  2325. + * Mods to the above
  2326. + * If an erase check fails or the write fails we skip the
  2327. + * rest of the block.
  2328. + */
  2329. +
  2330. + /* let's give it a try */
  2331. + attempts++;
  2332. +
  2333. + if (dev->param.always_check_erased)
  2334. + bi->skip_erased_check = 0;
  2335. +
  2336. + if (!bi->skip_erased_check) {
  2337. + erased_ok = yaffs_check_chunk_erased(dev, chunk);
  2338. + if (erased_ok != YAFFS_OK) {
  2339. + yaffs_trace(YAFFS_TRACE_ERROR,
  2340. + "**>> yaffs chunk %d was not erased",
  2341. + chunk);
  2342. +
  2343. + /* If not erased, delete this one,
  2344. + * skip rest of block and
  2345. + * try another chunk */
  2346. + yaffs_chunk_del(dev, chunk, 1, __LINE__);
  2347. + yaffs_skip_rest_of_block(dev);
  2348. + continue;
  2349. + }
  2350. + }
  2351. +
  2352. + write_ok = yaffs_wr_chunk_tags_nand(dev, chunk, data, tags);
  2353. +
  2354. + if (!bi->skip_erased_check)
  2355. + write_ok =
  2356. + yaffs_verify_chunk_written(dev, chunk, data, tags);
  2357. +
  2358. + if (write_ok != YAFFS_OK) {
  2359. + /* Clean up aborted write, skip to next block and
  2360. + * try another chunk */
  2361. + yaffs_handle_chunk_wr_error(dev, chunk, erased_ok);
  2362. + continue;
  2363. + }
  2364. +
  2365. + bi->skip_erased_check = 1;
  2366. +
  2367. + /* Copy the data into the robustification buffer */
  2368. + yaffs_handle_chunk_wr_ok(dev, chunk, data, tags);
  2369. +
  2370. + } while (write_ok != YAFFS_OK &&
  2371. + (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
  2372. +
  2373. + if (!write_ok)
  2374. + chunk = -1;
  2375. +
  2376. + if (attempts > 1) {
  2377. + yaffs_trace(YAFFS_TRACE_ERROR,
  2378. + "**>> yaffs write required %d attempts",
  2379. + attempts);
  2380. + dev->n_retried_writes += (attempts - 1);
  2381. + }
  2382. +
  2383. + return chunk;
  2384. +}
  2385. +
  2386. +/*
  2387. + * Block retiring for handling a broken block.
  2388. + */
  2389. +
  2390. +static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block)
  2391. +{
  2392. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
  2393. +
  2394. + yaffs2_checkpt_invalidate(dev);
  2395. +
  2396. + yaffs2_clear_oldest_dirty_seq(dev, bi);
  2397. +
  2398. + if (yaffs_mark_bad(dev, flash_block) != YAFFS_OK) {
  2399. + if (yaffs_erase_block(dev, flash_block) != YAFFS_OK) {
  2400. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2401. + "yaffs: Failed to mark bad and erase block %d",
  2402. + flash_block);
  2403. + } else {
  2404. + struct yaffs_ext_tags tags;
  2405. + int chunk_id =
  2406. + flash_block * dev->param.chunks_per_block;
  2407. +
  2408. + u8 *buffer = yaffs_get_temp_buffer(dev);
  2409. +
  2410. + memset(buffer, 0xff, dev->data_bytes_per_chunk);
  2411. + memset(&tags, 0, sizeof(tags));
  2412. + tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK;
  2413. + if (dev->tagger.write_chunk_tags_fn(dev, chunk_id -
  2414. + dev->chunk_offset,
  2415. + buffer,
  2416. + &tags) != YAFFS_OK)
  2417. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2418. + "yaffs: Failed to write bad block marker to block %d",
  2419. + flash_block);
  2420. +
  2421. + yaffs_release_temp_buffer(dev, buffer);
  2422. + }
  2423. + }
  2424. +
  2425. + bi->block_state = YAFFS_BLOCK_STATE_DEAD;
  2426. + bi->gc_prioritise = 0;
  2427. + bi->needs_retiring = 0;
  2428. +
  2429. + dev->n_retired_blocks++;
  2430. +}
  2431. +
  2432. +/*---------------- Name handling functions ------------*/
  2433. +
  2434. +static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name,
  2435. + const YCHAR *oh_name, int buff_size)
  2436. +{
  2437. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  2438. + if (dev->param.auto_unicode) {
  2439. + if (*oh_name) {
  2440. + /* It is an ASCII name, do an ASCII to
  2441. + * unicode conversion */
  2442. + const char *ascii_oh_name = (const char *)oh_name;
  2443. + int n = buff_size - 1;
  2444. + while (n > 0 && *ascii_oh_name) {
  2445. + *name = *ascii_oh_name;
  2446. + name++;
  2447. + ascii_oh_name++;
  2448. + n--;
  2449. + }
  2450. + } else {
  2451. + strncpy(name, oh_name + 1, buff_size - 1);
  2452. + }
  2453. + } else {
  2454. +#else
  2455. + (void) dev;
  2456. + {
  2457. +#endif
  2458. + strncpy(name, oh_name, buff_size - 1);
  2459. + }
  2460. +}
  2461. +
  2462. +static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name,
  2463. + const YCHAR *name)
  2464. +{
  2465. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  2466. +
  2467. + int is_ascii;
  2468. + const YCHAR *w;
  2469. +
  2470. + if (dev->param.auto_unicode) {
  2471. +
  2472. + is_ascii = 1;
  2473. + w = name;
  2474. +
  2475. + /* Figure out if the name will fit in ascii character set */
  2476. + while (is_ascii && *w) {
  2477. + if ((*w) & 0xff00)
  2478. + is_ascii = 0;
  2479. + w++;
  2480. + }
  2481. +
  2482. + if (is_ascii) {
  2483. + /* It is an ASCII name, so convert unicode to ascii */
  2484. + char *ascii_oh_name = (char *)oh_name;
  2485. + int n = YAFFS_MAX_NAME_LENGTH - 1;
  2486. + while (n > 0 && *name) {
  2487. + *ascii_oh_name = *name;
  2488. + name++;
  2489. + ascii_oh_name++;
  2490. + n--;
  2491. + }
  2492. + } else {
  2493. + /* Unicode name, so save starting at the second YCHAR */
  2494. + *oh_name = 0;
  2495. + strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2);
  2496. + }
  2497. + } else {
  2498. +#else
  2499. + dev = dev;
  2500. + {
  2501. +#endif
  2502. + strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
  2503. + }
  2504. +}
  2505. +
  2506. +static u16 yaffs_calc_name_sum(const YCHAR *name)
  2507. +{
  2508. + u16 sum = 0;
  2509. + u16 i = 1;
  2510. +
  2511. + if (!name)
  2512. + return 0;
  2513. +
  2514. + while ((*name) && i < (YAFFS_MAX_NAME_LENGTH / 2)) {
  2515. +
  2516. + /* 0x1f mask is case insensitive */
  2517. + sum += ((*name) & 0x1f) * i;
  2518. + i++;
  2519. + name++;
  2520. + }
  2521. + return sum;
  2522. +}
  2523. +
  2524. +
  2525. +void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
  2526. +{
  2527. + memset(obj->short_name, 0, sizeof(obj->short_name));
  2528. +
  2529. + if (name && !name[0]) {
  2530. + yaffs_fix_null_name(obj, obj->short_name,
  2531. + YAFFS_SHORT_NAME_LENGTH);
  2532. + name = obj->short_name;
  2533. + } else if (name &&
  2534. + strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <=
  2535. + YAFFS_SHORT_NAME_LENGTH) {
  2536. + strcpy(obj->short_name, name);
  2537. + }
  2538. +
  2539. + obj->sum = yaffs_calc_name_sum(name);
  2540. +}
  2541. +
  2542. +void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
  2543. + const struct yaffs_obj_hdr *oh)
  2544. +{
  2545. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  2546. + YCHAR tmp_name[YAFFS_MAX_NAME_LENGTH + 1];
  2547. + memset(tmp_name, 0, sizeof(tmp_name));
  2548. + yaffs_load_name_from_oh(obj->my_dev, tmp_name, oh->name,
  2549. + YAFFS_MAX_NAME_LENGTH + 1);
  2550. + yaffs_set_obj_name(obj, tmp_name);
  2551. +#else
  2552. + yaffs_set_obj_name(obj, oh->name);
  2553. +#endif
  2554. +}
  2555. +
  2556. +loff_t yaffs_max_file_size(struct yaffs_dev *dev)
  2557. +{
  2558. + if(sizeof(loff_t) < 8)
  2559. + return YAFFS_MAX_FILE_SIZE_32;
  2560. + else
  2561. + return ((loff_t) YAFFS_MAX_CHUNK_ID) * dev->data_bytes_per_chunk;
  2562. +}
  2563. +
  2564. +/*-------------------- TNODES -------------------
  2565. +
  2566. + * List of spare tnodes
  2567. + * The list is hooked together using the first pointer
  2568. + * in the tnode.
  2569. + */
  2570. +
  2571. +struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev)
  2572. +{
  2573. + struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev);
  2574. +
  2575. + if (tn) {
  2576. + memset(tn, 0, dev->tnode_size);
  2577. + dev->n_tnodes++;
  2578. + }
  2579. +
  2580. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  2581. +
  2582. + return tn;
  2583. +}
  2584. +
  2585. +/* FreeTnode frees up a tnode and puts it back on the free list */
  2586. +static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
  2587. +{
  2588. + yaffs_free_raw_tnode(dev, tn);
  2589. + dev->n_tnodes--;
  2590. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  2591. +}
  2592. +
  2593. +static void yaffs_deinit_tnodes_and_objs(struct yaffs_dev *dev)
  2594. +{
  2595. + yaffs_deinit_raw_tnodes_and_objs(dev);
  2596. + dev->n_obj = 0;
  2597. + dev->n_tnodes = 0;
  2598. +}
  2599. +
  2600. +static void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn,
  2601. + unsigned pos, unsigned val)
  2602. +{
  2603. + u32 *map = (u32 *) tn;
  2604. + u32 bit_in_map;
  2605. + u32 bit_in_word;
  2606. + u32 word_in_map;
  2607. + u32 mask;
  2608. +
  2609. + pos &= YAFFS_TNODES_LEVEL0_MASK;
  2610. + val >>= dev->chunk_grp_bits;
  2611. +
  2612. + bit_in_map = pos * dev->tnode_width;
  2613. + word_in_map = bit_in_map / 32;
  2614. + bit_in_word = bit_in_map & (32 - 1);
  2615. +
  2616. + mask = dev->tnode_mask << bit_in_word;
  2617. +
  2618. + map[word_in_map] &= ~mask;
  2619. + map[word_in_map] |= (mask & (val << bit_in_word));
  2620. +
  2621. + if (dev->tnode_width > (32 - bit_in_word)) {
  2622. + bit_in_word = (32 - bit_in_word);
  2623. + word_in_map++;
  2624. + mask =
  2625. + dev->tnode_mask >> bit_in_word;
  2626. + map[word_in_map] &= ~mask;
  2627. + map[word_in_map] |= (mask & (val >> bit_in_word));
  2628. + }
  2629. +}
  2630. +
  2631. +u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
  2632. + unsigned pos)
  2633. +{
  2634. + u32 *map = (u32 *) tn;
  2635. + u32 bit_in_map;
  2636. + u32 bit_in_word;
  2637. + u32 word_in_map;
  2638. + u32 val;
  2639. +
  2640. + pos &= YAFFS_TNODES_LEVEL0_MASK;
  2641. +
  2642. + bit_in_map = pos * dev->tnode_width;
  2643. + word_in_map = bit_in_map / 32;
  2644. + bit_in_word = bit_in_map & (32 - 1);
  2645. +
  2646. + val = map[word_in_map] >> bit_in_word;
  2647. +
  2648. + if (dev->tnode_width > (32 - bit_in_word)) {
  2649. + bit_in_word = (32 - bit_in_word);
  2650. + word_in_map++;
  2651. + val |= (map[word_in_map] << bit_in_word);
  2652. + }
  2653. +
  2654. + val &= dev->tnode_mask;
  2655. + val <<= dev->chunk_grp_bits;
  2656. +
  2657. + return val;
  2658. +}
  2659. +
  2660. +/* ------------------- End of individual tnode manipulation -----------------*/
  2661. +
  2662. +/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
  2663. + * The look up tree is represented by the top tnode and the number of top_level
  2664. + * in the tree. 0 means only the level 0 tnode is in the tree.
  2665. + */
  2666. +
  2667. +/* FindLevel0Tnode finds the level 0 tnode, if one exists. */
  2668. +struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
  2669. + struct yaffs_file_var *file_struct,
  2670. + u32 chunk_id)
  2671. +{
  2672. + struct yaffs_tnode *tn = file_struct->top;
  2673. + u32 i;
  2674. + int required_depth;
  2675. + int level = file_struct->top_level;
  2676. +
  2677. + (void) dev;
  2678. +
  2679. + /* Check sane level and chunk Id */
  2680. + if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL)
  2681. + return NULL;
  2682. +
  2683. + if (chunk_id > YAFFS_MAX_CHUNK_ID)
  2684. + return NULL;
  2685. +
  2686. + /* First check we're tall enough (ie enough top_level) */
  2687. +
  2688. + i = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
  2689. + required_depth = 0;
  2690. + while (i) {
  2691. + i >>= YAFFS_TNODES_INTERNAL_BITS;
  2692. + required_depth++;
  2693. + }
  2694. +
  2695. + if (required_depth > file_struct->top_level)
  2696. + return NULL; /* Not tall enough, so we can't find it */
  2697. +
  2698. + /* Traverse down to level 0 */
  2699. + while (level > 0 && tn) {
  2700. + tn = tn->internal[(chunk_id >>
  2701. + (YAFFS_TNODES_LEVEL0_BITS +
  2702. + (level - 1) *
  2703. + YAFFS_TNODES_INTERNAL_BITS)) &
  2704. + YAFFS_TNODES_INTERNAL_MASK];
  2705. + level--;
  2706. + }
  2707. +
  2708. + return tn;
  2709. +}
  2710. +
  2711. +/* add_find_tnode_0 finds the level 0 tnode if it exists,
  2712. + * otherwise first expands the tree.
  2713. + * This happens in two steps:
  2714. + * 1. If the tree isn't tall enough, then make it taller.
  2715. + * 2. Scan down the tree towards the level 0 tnode adding tnodes if required.
  2716. + *
  2717. + * Used when modifying the tree.
  2718. + *
  2719. + * If the tn argument is NULL, then a fresh tnode will be added otherwise the
  2720. + * specified tn will be plugged into the ttree.
  2721. + */
  2722. +
  2723. +struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
  2724. + struct yaffs_file_var *file_struct,
  2725. + u32 chunk_id,
  2726. + struct yaffs_tnode *passed_tn)
  2727. +{
  2728. + int required_depth;
  2729. + int i;
  2730. + int l;
  2731. + struct yaffs_tnode *tn;
  2732. + u32 x;
  2733. +
  2734. + /* Check sane level and page Id */
  2735. + if (file_struct->top_level < 0 ||
  2736. + file_struct->top_level > YAFFS_TNODES_MAX_LEVEL)
  2737. + return NULL;
  2738. +
  2739. + if (chunk_id > YAFFS_MAX_CHUNK_ID)
  2740. + return NULL;
  2741. +
  2742. + /* First check we're tall enough (ie enough top_level) */
  2743. +
  2744. + x = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
  2745. + required_depth = 0;
  2746. + while (x) {
  2747. + x >>= YAFFS_TNODES_INTERNAL_BITS;
  2748. + required_depth++;
  2749. + }
  2750. +
  2751. + if (required_depth > file_struct->top_level) {
  2752. + /* Not tall enough, gotta make the tree taller */
  2753. + for (i = file_struct->top_level; i < required_depth; i++) {
  2754. +
  2755. + tn = yaffs_get_tnode(dev);
  2756. +
  2757. + if (tn) {
  2758. + tn->internal[0] = file_struct->top;
  2759. + file_struct->top = tn;
  2760. + file_struct->top_level++;
  2761. + } else {
  2762. + yaffs_trace(YAFFS_TRACE_ERROR,
  2763. + "yaffs: no more tnodes");
  2764. + return NULL;
  2765. + }
  2766. + }
  2767. + }
  2768. +
  2769. + /* Traverse down to level 0, adding anything we need */
  2770. +
  2771. + l = file_struct->top_level;
  2772. + tn = file_struct->top;
  2773. +
  2774. + if (l > 0) {
  2775. + while (l > 0 && tn) {
  2776. + x = (chunk_id >>
  2777. + (YAFFS_TNODES_LEVEL0_BITS +
  2778. + (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &
  2779. + YAFFS_TNODES_INTERNAL_MASK;
  2780. +
  2781. + if ((l > 1) && !tn->internal[x]) {
  2782. + /* Add missing non-level-zero tnode */
  2783. + tn->internal[x] = yaffs_get_tnode(dev);
  2784. + if (!tn->internal[x])
  2785. + return NULL;
  2786. + } else if (l == 1) {
  2787. + /* Looking from level 1 at level 0 */
  2788. + if (passed_tn) {
  2789. + /* If we already have one, release it */
  2790. + if (tn->internal[x])
  2791. + yaffs_free_tnode(dev,
  2792. + tn->internal[x]);
  2793. + tn->internal[x] = passed_tn;
  2794. +
  2795. + } else if (!tn->internal[x]) {
  2796. + /* Don't have one, none passed in */
  2797. + tn->internal[x] = yaffs_get_tnode(dev);
  2798. + if (!tn->internal[x])
  2799. + return NULL;
  2800. + }
  2801. + }
  2802. +
  2803. + tn = tn->internal[x];
  2804. + l--;
  2805. + }
  2806. + } else {
  2807. + /* top is level 0 */
  2808. + if (passed_tn) {
  2809. + memcpy(tn, passed_tn,
  2810. + (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8);
  2811. + yaffs_free_tnode(dev, passed_tn);
  2812. + }
  2813. + }
  2814. +
  2815. + return tn;
  2816. +}
  2817. +
  2818. +static int yaffs_tags_match(const struct yaffs_ext_tags *tags, int obj_id,
  2819. + int chunk_obj)
  2820. +{
  2821. + return (tags->chunk_id == chunk_obj &&
  2822. + tags->obj_id == obj_id &&
  2823. + !tags->is_deleted) ? 1 : 0;
  2824. +
  2825. +}
  2826. +
  2827. +static int yaffs_find_chunk_in_group(struct yaffs_dev *dev, int the_chunk,
  2828. + struct yaffs_ext_tags *tags, int obj_id,
  2829. + int inode_chunk)
  2830. +{
  2831. + int j;
  2832. +
  2833. + for (j = 0; the_chunk && j < dev->chunk_grp_size; j++) {
  2834. + if (yaffs_check_chunk_bit
  2835. + (dev, the_chunk / dev->param.chunks_per_block,
  2836. + the_chunk % dev->param.chunks_per_block)) {
  2837. +
  2838. + if (dev->chunk_grp_size == 1)
  2839. + return the_chunk;
  2840. + else {
  2841. + yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
  2842. + tags);
  2843. + if (yaffs_tags_match(tags,
  2844. + obj_id, inode_chunk)) {
  2845. + /* found it; */
  2846. + return the_chunk;
  2847. + }
  2848. + }
  2849. + }
  2850. + the_chunk++;
  2851. + }
  2852. + return -1;
  2853. +}
  2854. +
  2855. +int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  2856. + struct yaffs_ext_tags *tags)
  2857. +{
  2858. + /*Get the Tnode, then get the level 0 offset chunk offset */
  2859. + struct yaffs_tnode *tn;
  2860. + int the_chunk = -1;
  2861. + struct yaffs_ext_tags local_tags;
  2862. + int ret_val = -1;
  2863. + struct yaffs_dev *dev = in->my_dev;
  2864. +
  2865. + if (!tags) {
  2866. + /* Passed a NULL, so use our own tags space */
  2867. + tags = &local_tags;
  2868. + }
  2869. +
  2870. + tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
  2871. +
  2872. + if (!tn)
  2873. + return ret_val;
  2874. +
  2875. + the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
  2876. +
  2877. + ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
  2878. + inode_chunk);
  2879. + return ret_val;
  2880. +}
  2881. +
  2882. +static int yaffs_find_del_file_chunk(struct yaffs_obj *in, int inode_chunk,
  2883. + struct yaffs_ext_tags *tags)
  2884. +{
  2885. + /* Get the Tnode, then get the level 0 offset chunk offset */
  2886. + struct yaffs_tnode *tn;
  2887. + int the_chunk = -1;
  2888. + struct yaffs_ext_tags local_tags;
  2889. + struct yaffs_dev *dev = in->my_dev;
  2890. + int ret_val = -1;
  2891. +
  2892. + if (!tags) {
  2893. + /* Passed a NULL, so use our own tags space */
  2894. + tags = &local_tags;
  2895. + }
  2896. +
  2897. + tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
  2898. +
  2899. + if (!tn)
  2900. + return ret_val;
  2901. +
  2902. + the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
  2903. +
  2904. + ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
  2905. + inode_chunk);
  2906. +
  2907. + /* Delete the entry in the filestructure (if found) */
  2908. + if (ret_val != -1)
  2909. + yaffs_load_tnode_0(dev, tn, inode_chunk, 0);
  2910. +
  2911. + return ret_val;
  2912. +}
  2913. +
  2914. +int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  2915. + int nand_chunk, int in_scan)
  2916. +{
  2917. + /* NB in_scan is zero unless scanning.
  2918. + * For forward scanning, in_scan is > 0;
  2919. + * for backward scanning in_scan is < 0
  2920. + *
  2921. + * nand_chunk = 0 is a dummy insert to make sure the tnodes are there.
  2922. + */
  2923. +
  2924. + struct yaffs_tnode *tn;
  2925. + struct yaffs_dev *dev = in->my_dev;
  2926. + int existing_cunk;
  2927. + struct yaffs_ext_tags existing_tags;
  2928. + struct yaffs_ext_tags new_tags;
  2929. + unsigned existing_serial, new_serial;
  2930. +
  2931. + if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) {
  2932. + /* Just ignore an attempt at putting a chunk into a non-file
  2933. + * during scanning.
  2934. + * If it is not during Scanning then something went wrong!
  2935. + */
  2936. + if (!in_scan) {
  2937. + yaffs_trace(YAFFS_TRACE_ERROR,
  2938. + "yaffs tragedy:attempt to put data chunk into a non-file"
  2939. + );
  2940. + BUG();
  2941. + }
  2942. +
  2943. + yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
  2944. + return YAFFS_OK;
  2945. + }
  2946. +
  2947. + tn = yaffs_add_find_tnode_0(dev,
  2948. + &in->variant.file_variant,
  2949. + inode_chunk, NULL);
  2950. + if (!tn)
  2951. + return YAFFS_FAIL;
  2952. +
  2953. + if (!nand_chunk)
  2954. + /* Dummy insert, bail now */
  2955. + return YAFFS_OK;
  2956. +
  2957. + existing_cunk = yaffs_get_group_base(dev, tn, inode_chunk);
  2958. +
  2959. + if (in_scan != 0) {
  2960. + /* If we're scanning then we need to test for duplicates
  2961. + * NB This does not need to be efficient since it should only
  2962. + * happen when the power fails during a write, then only one
  2963. + * chunk should ever be affected.
  2964. + *
  2965. + * Correction for YAFFS2: This could happen quite a lot and we
  2966. + * need to think about efficiency! TODO
  2967. + * Update: For backward scanning we don't need to re-read tags
  2968. + * so this is quite cheap.
  2969. + */
  2970. +
  2971. + if (existing_cunk > 0) {
  2972. + /* NB Right now existing chunk will not be real
  2973. + * chunk_id if the chunk group size > 1
  2974. + * thus we have to do a FindChunkInFile to get the
  2975. + * real chunk id.
  2976. + *
  2977. + * We have a duplicate now we need to decide which
  2978. + * one to use:
  2979. + *
  2980. + * Backwards scanning YAFFS2: The old one is what
  2981. + * we use, dump the new one.
  2982. + * YAFFS1: Get both sets of tags and compare serial
  2983. + * numbers.
  2984. + */
  2985. +
  2986. + if (in_scan > 0) {
  2987. + /* Only do this for forward scanning */
  2988. + yaffs_rd_chunk_tags_nand(dev,
  2989. + nand_chunk,
  2990. + NULL, &new_tags);
  2991. +
  2992. + /* Do a proper find */
  2993. + existing_cunk =
  2994. + yaffs_find_chunk_in_file(in, inode_chunk,
  2995. + &existing_tags);
  2996. + }
  2997. +
  2998. + if (existing_cunk <= 0) {
  2999. + /*Hoosterman - how did this happen? */
  3000. +
  3001. + yaffs_trace(YAFFS_TRACE_ERROR,
  3002. + "yaffs tragedy: existing chunk < 0 in scan"
  3003. + );
  3004. +
  3005. + }
  3006. +
  3007. + /* NB The deleted flags should be false, otherwise
  3008. + * the chunks will not be loaded during a scan
  3009. + */
  3010. +
  3011. + if (in_scan > 0) {
  3012. + new_serial = new_tags.serial_number;
  3013. + existing_serial = existing_tags.serial_number;
  3014. + }
  3015. +
  3016. + if ((in_scan > 0) &&
  3017. + (existing_cunk <= 0 ||
  3018. + ((existing_serial + 1) & 3) == new_serial)) {
  3019. + /* Forward scanning.
  3020. + * Use new
  3021. + * Delete the old one and drop through to
  3022. + * update the tnode
  3023. + */
  3024. + yaffs_chunk_del(dev, existing_cunk, 1,
  3025. + __LINE__);
  3026. + } else {
  3027. + /* Backward scanning or we want to use the
  3028. + * existing one
  3029. + * Delete the new one and return early so that
  3030. + * the tnode isn't changed
  3031. + */
  3032. + yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
  3033. + return YAFFS_OK;
  3034. + }
  3035. + }
  3036. +
  3037. + }
  3038. +
  3039. + if (existing_cunk == 0)
  3040. + in->n_data_chunks++;
  3041. +
  3042. + yaffs_load_tnode_0(dev, tn, inode_chunk, nand_chunk);
  3043. +
  3044. + return YAFFS_OK;
  3045. +}
  3046. +
  3047. +static void yaffs_soft_del_chunk(struct yaffs_dev *dev, int chunk)
  3048. +{
  3049. + struct yaffs_block_info *the_block;
  3050. + unsigned block_no;
  3051. +
  3052. + yaffs_trace(YAFFS_TRACE_DELETION, "soft delete chunk %d", chunk);
  3053. +
  3054. + block_no = chunk / dev->param.chunks_per_block;
  3055. + the_block = yaffs_get_block_info(dev, block_no);
  3056. + if (the_block) {
  3057. + the_block->soft_del_pages++;
  3058. + dev->n_free_chunks++;
  3059. + yaffs2_update_oldest_dirty_seq(dev, block_no, the_block);
  3060. + }
  3061. +}
  3062. +
  3063. +/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all
  3064. + * the chunks in the file.
  3065. + * All soft deleting does is increment the block's softdelete count and pulls
  3066. + * the chunk out of the tnode.
  3067. + * Thus, essentially this is the same as DeleteWorker except that the chunks
  3068. + * are soft deleted.
  3069. + */
  3070. +
  3071. +static int yaffs_soft_del_worker(struct yaffs_obj *in, struct yaffs_tnode *tn,
  3072. + u32 level, int chunk_offset)
  3073. +{
  3074. + int i;
  3075. + int the_chunk;
  3076. + int all_done = 1;
  3077. + struct yaffs_dev *dev = in->my_dev;
  3078. +
  3079. + if (!tn)
  3080. + return 1;
  3081. +
  3082. + if (level > 0) {
  3083. + for (i = YAFFS_NTNODES_INTERNAL - 1;
  3084. + all_done && i >= 0;
  3085. + i--) {
  3086. + if (tn->internal[i]) {
  3087. + all_done =
  3088. + yaffs_soft_del_worker(in,
  3089. + tn->internal[i],
  3090. + level - 1,
  3091. + (chunk_offset <<
  3092. + YAFFS_TNODES_INTERNAL_BITS)
  3093. + + i);
  3094. + if (all_done) {
  3095. + yaffs_free_tnode(dev,
  3096. + tn->internal[i]);
  3097. + tn->internal[i] = NULL;
  3098. + } else {
  3099. + /* Can this happen? */
  3100. + }
  3101. + }
  3102. + }
  3103. + return (all_done) ? 1 : 0;
  3104. + }
  3105. +
  3106. + /* level 0 */
  3107. + for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
  3108. + the_chunk = yaffs_get_group_base(dev, tn, i);
  3109. + if (the_chunk) {
  3110. + yaffs_soft_del_chunk(dev, the_chunk);
  3111. + yaffs_load_tnode_0(dev, tn, i, 0);
  3112. + }
  3113. + }
  3114. + return 1;
  3115. +}
  3116. +
  3117. +static void yaffs_remove_obj_from_dir(struct yaffs_obj *obj)
  3118. +{
  3119. + struct yaffs_dev *dev = obj->my_dev;
  3120. + struct yaffs_obj *parent;
  3121. +
  3122. + yaffs_verify_obj_in_dir(obj);
  3123. + parent = obj->parent;
  3124. +
  3125. + yaffs_verify_dir(parent);
  3126. +
  3127. + if (dev && dev->param.remove_obj_fn)
  3128. + dev->param.remove_obj_fn(obj);
  3129. +
  3130. + list_del_init(&obj->siblings);
  3131. + obj->parent = NULL;
  3132. +
  3133. + yaffs_verify_dir(parent);
  3134. +}
  3135. +
  3136. +void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj)
  3137. +{
  3138. + if (!directory) {
  3139. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  3140. + "tragedy: Trying to add an object to a null pointer directory"
  3141. + );
  3142. + BUG();
  3143. + return;
  3144. + }
  3145. + if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  3146. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  3147. + "tragedy: Trying to add an object to a non-directory"
  3148. + );
  3149. + BUG();
  3150. + }
  3151. +
  3152. + if (obj->siblings.prev == NULL) {
  3153. + /* Not initialised */
  3154. + BUG();
  3155. + }
  3156. +
  3157. + yaffs_verify_dir(directory);
  3158. +
  3159. + yaffs_remove_obj_from_dir(obj);
  3160. +
  3161. + /* Now add it */
  3162. + list_add(&obj->siblings, &directory->variant.dir_variant.children);
  3163. + obj->parent = directory;
  3164. +
  3165. + if (directory == obj->my_dev->unlinked_dir
  3166. + || directory == obj->my_dev->del_dir) {
  3167. + obj->unlinked = 1;
  3168. + obj->my_dev->n_unlinked_files++;
  3169. + obj->rename_allowed = 0;
  3170. + }
  3171. +
  3172. + yaffs_verify_dir(directory);
  3173. + yaffs_verify_obj_in_dir(obj);
  3174. +}
  3175. +
  3176. +static int yaffs_change_obj_name(struct yaffs_obj *obj,
  3177. + struct yaffs_obj *new_dir,
  3178. + const YCHAR *new_name, int force, int shadows)
  3179. +{
  3180. + int unlink_op;
  3181. + int del_op;
  3182. + struct yaffs_obj *existing_target;
  3183. +
  3184. + if (new_dir == NULL)
  3185. + new_dir = obj->parent; /* use the old directory */
  3186. +
  3187. + if (new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  3188. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  3189. + "tragedy: yaffs_change_obj_name: new_dir is not a directory"
  3190. + );
  3191. + BUG();
  3192. + }
  3193. +
  3194. + unlink_op = (new_dir == obj->my_dev->unlinked_dir);
  3195. + del_op = (new_dir == obj->my_dev->del_dir);
  3196. +
  3197. + existing_target = yaffs_find_by_name(new_dir, new_name);
  3198. +
  3199. + /* If the object is a file going into the unlinked directory,
  3200. + * then it is OK to just stuff it in since duplicate names are OK.
  3201. + * else only proceed if the new name does not exist and we're putting
  3202. + * it into a directory.
  3203. + */
  3204. + if (!(unlink_op || del_op || force ||
  3205. + shadows > 0 || !existing_target) ||
  3206. + new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
  3207. + return YAFFS_FAIL;
  3208. +
  3209. + yaffs_set_obj_name(obj, new_name);
  3210. + obj->dirty = 1;
  3211. + yaffs_add_obj_to_dir(new_dir, obj);
  3212. +
  3213. + if (unlink_op)
  3214. + obj->unlinked = 1;
  3215. +
  3216. + /* If it is a deletion then we mark it as a shrink for gc */
  3217. + if (yaffs_update_oh(obj, new_name, 0, del_op, shadows, NULL) >= 0)
  3218. + return YAFFS_OK;
  3219. +
  3220. + return YAFFS_FAIL;
  3221. +}
  3222. +
  3223. +/*------------------------ Short Operations Cache ------------------------------
  3224. + * In many situations where there is no high level buffering a lot of
  3225. + * reads might be short sequential reads, and a lot of writes may be short
  3226. + * sequential writes. eg. scanning/writing a jpeg file.
  3227. + * In these cases, a short read/write cache can provide a huge perfomance
  3228. + * benefit with dumb-as-a-rock code.
  3229. + * In Linux, the page cache provides read buffering and the short op cache
  3230. + * provides write buffering.
  3231. + *
  3232. + * There are a small number (~10) of cache chunks per device so that we don't
  3233. + * need a very intelligent search.
  3234. + */
  3235. +
  3236. +static int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
  3237. +{
  3238. + struct yaffs_dev *dev = obj->my_dev;
  3239. + int i;
  3240. + struct yaffs_cache *cache;
  3241. + int n_caches = obj->my_dev->param.n_caches;
  3242. +
  3243. + for (i = 0; i < n_caches; i++) {
  3244. + cache = &dev->cache[i];
  3245. + if (cache->object == obj && cache->dirty)
  3246. + return 1;
  3247. + }
  3248. +
  3249. + return 0;
  3250. +}
  3251. +
  3252. +static void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard)
  3253. +{
  3254. +
  3255. + if (!cache || cache->locked)
  3256. + return;
  3257. +
  3258. + /* Write it out and free it up if need be.*/
  3259. + if (cache->dirty) {
  3260. + yaffs_wr_data_obj(cache->object,
  3261. + cache->chunk_id,
  3262. + cache->data,
  3263. + cache->n_bytes,
  3264. + 1);
  3265. +
  3266. + cache->dirty = 0;
  3267. + }
  3268. +
  3269. + if (discard)
  3270. + cache->object = NULL;
  3271. +}
  3272. +
  3273. +static void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard)
  3274. +{
  3275. + struct yaffs_dev *dev = obj->my_dev;
  3276. + int i;
  3277. + struct yaffs_cache *cache;
  3278. + int n_caches = obj->my_dev->param.n_caches;
  3279. +
  3280. + if (n_caches < 1)
  3281. + return;
  3282. +
  3283. +
  3284. + /* Find the chunks for this object and flush them. */
  3285. + for (i = 0; i < n_caches; i++) {
  3286. + cache = &dev->cache[i];
  3287. + if (cache->object == obj)
  3288. + yaffs_flush_single_cache(cache, discard);
  3289. + }
  3290. +
  3291. +}
  3292. +
  3293. +
  3294. +void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard)
  3295. +{
  3296. + struct yaffs_obj *obj;
  3297. + int n_caches = dev->param.n_caches;
  3298. + int i;
  3299. +
  3300. + /* Find a dirty object in the cache and flush it...
  3301. + * until there are no further dirty objects.
  3302. + */
  3303. + do {
  3304. + obj = NULL;
  3305. + for (i = 0; i < n_caches && !obj; i++) {
  3306. + if (dev->cache[i].object && dev->cache[i].dirty)
  3307. + obj = dev->cache[i].object;
  3308. + }
  3309. + if (obj)
  3310. + yaffs_flush_file_cache(obj, discard);
  3311. + } while (obj);
  3312. +
  3313. +}
  3314. +
  3315. +/* Grab us an unused cache chunk for use.
  3316. + * First look for an empty one.
  3317. + * Then look for the least recently used non-dirty one.
  3318. + * Then look for the least recently used dirty one...., flush and look again.
  3319. + */
  3320. +static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
  3321. +{
  3322. + int i;
  3323. +
  3324. + if (dev->param.n_caches > 0) {
  3325. + for (i = 0; i < dev->param.n_caches; i++) {
  3326. + if (!dev->cache[i].object)
  3327. + return &dev->cache[i];
  3328. + }
  3329. + }
  3330. +
  3331. + return NULL;
  3332. +}
  3333. +
  3334. +static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
  3335. +{
  3336. + struct yaffs_cache *cache;
  3337. + int usage;
  3338. + int i;
  3339. +
  3340. + if (dev->param.n_caches < 1)
  3341. + return NULL;
  3342. +
  3343. + /* First look for an unused cache */
  3344. +
  3345. + cache = yaffs_grab_chunk_worker(dev);
  3346. +
  3347. + if (cache)
  3348. + return cache;
  3349. +
  3350. + /*
  3351. + * Thery were all in use.
  3352. + * Find the LRU cache and flush it if it is dirty.
  3353. + */
  3354. +
  3355. + usage = -1;
  3356. + cache = NULL;
  3357. +
  3358. + for (i = 0; i < dev->param.n_caches; i++) {
  3359. + if (dev->cache[i].object &&
  3360. + !dev->cache[i].locked &&
  3361. + (dev->cache[i].last_use < usage || !cache)) {
  3362. + usage = dev->cache[i].last_use;
  3363. + cache = &dev->cache[i];
  3364. + }
  3365. + }
  3366. +
  3367. +#if 1
  3368. + yaffs_flush_single_cache(cache, 1);
  3369. +#else
  3370. + yaffs_flush_file_cache(cache->object, 1);
  3371. + cache = yaffs_grab_chunk_worker(dev);
  3372. +#endif
  3373. +
  3374. + return cache;
  3375. +}
  3376. +
  3377. +/* Find a cached chunk */
  3378. +static struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
  3379. + int chunk_id)
  3380. +{
  3381. + struct yaffs_dev *dev = obj->my_dev;
  3382. + int i;
  3383. +
  3384. + if (dev->param.n_caches < 1)
  3385. + return NULL;
  3386. +
  3387. + for (i = 0; i < dev->param.n_caches; i++) {
  3388. + if (dev->cache[i].object == obj &&
  3389. + dev->cache[i].chunk_id == chunk_id) {
  3390. + dev->cache_hits++;
  3391. +
  3392. + return &dev->cache[i];
  3393. + }
  3394. + }
  3395. + return NULL;
  3396. +}
  3397. +
  3398. +/* Mark the chunk for the least recently used algorithym */
  3399. +static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
  3400. + int is_write)
  3401. +{
  3402. + int i;
  3403. +
  3404. + if (dev->param.n_caches < 1)
  3405. + return;
  3406. +
  3407. + if (dev->cache_last_use < 0 ||
  3408. + dev->cache_last_use > 100000000) {
  3409. + /* Reset the cache usages */
  3410. + for (i = 1; i < dev->param.n_caches; i++)
  3411. + dev->cache[i].last_use = 0;
  3412. +
  3413. + dev->cache_last_use = 0;
  3414. + }
  3415. + dev->cache_last_use++;
  3416. + cache->last_use = dev->cache_last_use;
  3417. +
  3418. + if (is_write)
  3419. + cache->dirty = 1;
  3420. +}
  3421. +
  3422. +/* Invalidate a single cache page.
  3423. + * Do this when a whole page gets written,
  3424. + * ie the short cache for this page is no longer valid.
  3425. + */
  3426. +static void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id)
  3427. +{
  3428. + struct yaffs_cache *cache;
  3429. +
  3430. + if (object->my_dev->param.n_caches > 0) {
  3431. + cache = yaffs_find_chunk_cache(object, chunk_id);
  3432. +
  3433. + if (cache)
  3434. + cache->object = NULL;
  3435. + }
  3436. +}
  3437. +
  3438. +/* Invalidate all the cache pages associated with this object
  3439. + * Do this whenever ther file is deleted or resized.
  3440. + */
  3441. +static void yaffs_invalidate_whole_cache(struct yaffs_obj *in)
  3442. +{
  3443. + int i;
  3444. + struct yaffs_dev *dev = in->my_dev;
  3445. +
  3446. + if (dev->param.n_caches > 0) {
  3447. + /* Invalidate it. */
  3448. + for (i = 0; i < dev->param.n_caches; i++) {
  3449. + if (dev->cache[i].object == in)
  3450. + dev->cache[i].object = NULL;
  3451. + }
  3452. + }
  3453. +}
  3454. +
  3455. +static void yaffs_unhash_obj(struct yaffs_obj *obj)
  3456. +{
  3457. + int bucket;
  3458. + struct yaffs_dev *dev = obj->my_dev;
  3459. +
  3460. + /* If it is still linked into the bucket list, free from the list */
  3461. + if (!list_empty(&obj->hash_link)) {
  3462. + list_del_init(&obj->hash_link);
  3463. + bucket = yaffs_hash_fn(obj->obj_id);
  3464. + dev->obj_bucket[bucket].count--;
  3465. + }
  3466. +}
  3467. +
  3468. +/* FreeObject frees up a Object and puts it back on the free list */
  3469. +static void yaffs_free_obj(struct yaffs_obj *obj)
  3470. +{
  3471. + struct yaffs_dev *dev;
  3472. +
  3473. + if (!obj) {
  3474. + BUG();
  3475. + return;
  3476. + }
  3477. + dev = obj->my_dev;
  3478. + yaffs_trace(YAFFS_TRACE_OS, "FreeObject %p inode %p",
  3479. + obj, obj->my_inode);
  3480. + if (obj->parent)
  3481. + BUG();
  3482. + if (!list_empty(&obj->siblings))
  3483. + BUG();
  3484. +
  3485. + if (obj->my_inode) {
  3486. + /* We're still hooked up to a cached inode.
  3487. + * Don't delete now, but mark for later deletion
  3488. + */
  3489. + obj->defered_free = 1;
  3490. + return;
  3491. + }
  3492. +
  3493. + yaffs_unhash_obj(obj);
  3494. +
  3495. + yaffs_free_raw_obj(dev, obj);
  3496. + dev->n_obj--;
  3497. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  3498. +}
  3499. +
  3500. +void yaffs_handle_defered_free(struct yaffs_obj *obj)
  3501. +{
  3502. + if (obj->defered_free)
  3503. + yaffs_free_obj(obj);
  3504. +}
  3505. +
  3506. +static int yaffs_generic_obj_del(struct yaffs_obj *in)
  3507. +{
  3508. + /* Iinvalidate the file's data in the cache, without flushing. */
  3509. + yaffs_invalidate_whole_cache(in);
  3510. +
  3511. + if (in->my_dev->param.is_yaffs2 && in->parent != in->my_dev->del_dir) {
  3512. + /* Move to unlinked directory so we have a deletion record */
  3513. + yaffs_change_obj_name(in, in->my_dev->del_dir, _Y("deleted"), 0,
  3514. + 0);
  3515. + }
  3516. +
  3517. + yaffs_remove_obj_from_dir(in);
  3518. + yaffs_chunk_del(in->my_dev, in->hdr_chunk, 1, __LINE__);
  3519. + in->hdr_chunk = 0;
  3520. +
  3521. + yaffs_free_obj(in);
  3522. + return YAFFS_OK;
  3523. +
  3524. +}
  3525. +
  3526. +static void yaffs_soft_del_file(struct yaffs_obj *obj)
  3527. +{
  3528. + if (!obj->deleted ||
  3529. + obj->variant_type != YAFFS_OBJECT_TYPE_FILE ||
  3530. + obj->soft_del)
  3531. + return;
  3532. +
  3533. + if (obj->n_data_chunks <= 0) {
  3534. + /* Empty file with no duplicate object headers,
  3535. + * just delete it immediately */
  3536. + yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
  3537. + obj->variant.file_variant.top = NULL;
  3538. + yaffs_trace(YAFFS_TRACE_TRACING,
  3539. + "yaffs: Deleting empty file %d",
  3540. + obj->obj_id);
  3541. + yaffs_generic_obj_del(obj);
  3542. + } else {
  3543. + yaffs_soft_del_worker(obj,
  3544. + obj->variant.file_variant.top,
  3545. + obj->variant.
  3546. + file_variant.top_level, 0);
  3547. + obj->soft_del = 1;
  3548. + }
  3549. +}
  3550. +
  3551. +/* Pruning removes any part of the file structure tree that is beyond the
  3552. + * bounds of the file (ie that does not point to chunks).
  3553. + *
  3554. + * A file should only get pruned when its size is reduced.
  3555. + *
  3556. + * Before pruning, the chunks must be pulled from the tree and the
  3557. + * level 0 tnode entries must be zeroed out.
  3558. + * Could also use this for file deletion, but that's probably better handled
  3559. + * by a special case.
  3560. + *
  3561. + * This function is recursive. For levels > 0 the function is called again on
  3562. + * any sub-tree. For level == 0 we just check if the sub-tree has data.
  3563. + * If there is no data in a subtree then it is pruned.
  3564. + */
  3565. +
  3566. +static struct yaffs_tnode *yaffs_prune_worker(struct yaffs_dev *dev,
  3567. + struct yaffs_tnode *tn, u32 level,
  3568. + int del0)
  3569. +{
  3570. + int i;
  3571. + int has_data;
  3572. +
  3573. + if (!tn)
  3574. + return tn;
  3575. +
  3576. + has_data = 0;
  3577. +
  3578. + if (level > 0) {
  3579. + for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) {
  3580. + if (tn->internal[i]) {
  3581. + tn->internal[i] =
  3582. + yaffs_prune_worker(dev,
  3583. + tn->internal[i],
  3584. + level - 1,
  3585. + (i == 0) ? del0 : 1);
  3586. + }
  3587. +
  3588. + if (tn->internal[i])
  3589. + has_data++;
  3590. + }
  3591. + } else {
  3592. + int tnode_size_u32 = dev->tnode_size / sizeof(u32);
  3593. + u32 *map = (u32 *) tn;
  3594. +
  3595. + for (i = 0; !has_data && i < tnode_size_u32; i++) {
  3596. + if (map[i])
  3597. + has_data++;
  3598. + }
  3599. + }
  3600. +
  3601. + if (has_data == 0 && del0) {
  3602. + /* Free and return NULL */
  3603. + yaffs_free_tnode(dev, tn);
  3604. + tn = NULL;
  3605. + }
  3606. + return tn;
  3607. +}
  3608. +
  3609. +static int yaffs_prune_tree(struct yaffs_dev *dev,
  3610. + struct yaffs_file_var *file_struct)
  3611. +{
  3612. + int i;
  3613. + int has_data;
  3614. + int done = 0;
  3615. + struct yaffs_tnode *tn;
  3616. +
  3617. + if (file_struct->top_level < 1)
  3618. + return YAFFS_OK;
  3619. +
  3620. + file_struct->top =
  3621. + yaffs_prune_worker(dev, file_struct->top, file_struct->top_level, 0);
  3622. +
  3623. + /* Now we have a tree with all the non-zero branches NULL but
  3624. + * the height is the same as it was.
  3625. + * Let's see if we can trim internal tnodes to shorten the tree.
  3626. + * We can do this if only the 0th element in the tnode is in use
  3627. + * (ie all the non-zero are NULL)
  3628. + */
  3629. +
  3630. + while (file_struct->top_level && !done) {
  3631. + tn = file_struct->top;
  3632. +
  3633. + has_data = 0;
  3634. + for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) {
  3635. + if (tn->internal[i])
  3636. + has_data++;
  3637. + }
  3638. +
  3639. + if (!has_data) {
  3640. + file_struct->top = tn->internal[0];
  3641. + file_struct->top_level--;
  3642. + yaffs_free_tnode(dev, tn);
  3643. + } else {
  3644. + done = 1;
  3645. + }
  3646. + }
  3647. +
  3648. + return YAFFS_OK;
  3649. +}
  3650. +
  3651. +/*-------------------- End of File Structure functions.-------------------*/
  3652. +
  3653. +/* alloc_empty_obj gets us a clean Object.*/
  3654. +static struct yaffs_obj *yaffs_alloc_empty_obj(struct yaffs_dev *dev)
  3655. +{
  3656. + struct yaffs_obj *obj = yaffs_alloc_raw_obj(dev);
  3657. +
  3658. + if (!obj)
  3659. + return obj;
  3660. +
  3661. + dev->n_obj++;
  3662. +
  3663. + /* Now sweeten it up... */
  3664. +
  3665. + memset(obj, 0, sizeof(struct yaffs_obj));
  3666. + obj->being_created = 1;
  3667. +
  3668. + obj->my_dev = dev;
  3669. + obj->hdr_chunk = 0;
  3670. + obj->variant_type = YAFFS_OBJECT_TYPE_UNKNOWN;
  3671. + INIT_LIST_HEAD(&(obj->hard_links));
  3672. + INIT_LIST_HEAD(&(obj->hash_link));
  3673. + INIT_LIST_HEAD(&obj->siblings);
  3674. +
  3675. + /* Now make the directory sane */
  3676. + if (dev->root_dir) {
  3677. + obj->parent = dev->root_dir;
  3678. + list_add(&(obj->siblings),
  3679. + &dev->root_dir->variant.dir_variant.children);
  3680. + }
  3681. +
  3682. + /* Add it to the lost and found directory.
  3683. + * NB Can't put root or lost-n-found in lost-n-found so
  3684. + * check if lost-n-found exists first
  3685. + */
  3686. + if (dev->lost_n_found)
  3687. + yaffs_add_obj_to_dir(dev->lost_n_found, obj);
  3688. +
  3689. + obj->being_created = 0;
  3690. +
  3691. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  3692. +
  3693. + return obj;
  3694. +}
  3695. +
  3696. +static int yaffs_find_nice_bucket(struct yaffs_dev *dev)
  3697. +{
  3698. + int i;
  3699. + int l = 999;
  3700. + int lowest = 999999;
  3701. +
  3702. + /* Search for the shortest list or one that
  3703. + * isn't too long.
  3704. + */
  3705. +
  3706. + for (i = 0; i < 10 && lowest > 4; i++) {
  3707. + dev->bucket_finder++;
  3708. + dev->bucket_finder %= YAFFS_NOBJECT_BUCKETS;
  3709. + if (dev->obj_bucket[dev->bucket_finder].count < lowest) {
  3710. + lowest = dev->obj_bucket[dev->bucket_finder].count;
  3711. + l = dev->bucket_finder;
  3712. + }
  3713. + }
  3714. +
  3715. + return l;
  3716. +}
  3717. +
  3718. +static int yaffs_new_obj_id(struct yaffs_dev *dev)
  3719. +{
  3720. + int bucket = yaffs_find_nice_bucket(dev);
  3721. + int found = 0;
  3722. + struct list_head *i;
  3723. + u32 n = (u32) bucket;
  3724. +
  3725. + /*
  3726. + * Now find an object value that has not already been taken
  3727. + * by scanning the list, incrementing each time by number of buckets.
  3728. + */
  3729. + while (!found) {
  3730. + found = 1;
  3731. + n += YAFFS_NOBJECT_BUCKETS;
  3732. + list_for_each(i, &dev->obj_bucket[bucket].list) {
  3733. + /* Check if this value is already taken. */
  3734. + if (i && list_entry(i, struct yaffs_obj,
  3735. + hash_link)->obj_id == n)
  3736. + found = 0;
  3737. + }
  3738. + }
  3739. + return n;
  3740. +}
  3741. +
  3742. +static void yaffs_hash_obj(struct yaffs_obj *in)
  3743. +{
  3744. + int bucket = yaffs_hash_fn(in->obj_id);
  3745. + struct yaffs_dev *dev = in->my_dev;
  3746. +
  3747. + list_add(&in->hash_link, &dev->obj_bucket[bucket].list);
  3748. + dev->obj_bucket[bucket].count++;
  3749. +}
  3750. +
  3751. +struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number)
  3752. +{
  3753. + int bucket = yaffs_hash_fn(number);
  3754. + struct list_head *i;
  3755. + struct yaffs_obj *in;
  3756. +
  3757. + list_for_each(i, &dev->obj_bucket[bucket].list) {
  3758. + /* Look if it is in the list */
  3759. + in = list_entry(i, struct yaffs_obj, hash_link);
  3760. + if (in->obj_id == number) {
  3761. + /* Don't show if it is defered free */
  3762. + if (in->defered_free)
  3763. + return NULL;
  3764. + return in;
  3765. + }
  3766. + }
  3767. +
  3768. + return NULL;
  3769. +}
  3770. +
  3771. +static struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number,
  3772. + enum yaffs_obj_type type)
  3773. +{
  3774. + struct yaffs_obj *the_obj = NULL;
  3775. + struct yaffs_tnode *tn = NULL;
  3776. +
  3777. + if (number < 0)
  3778. + number = yaffs_new_obj_id(dev);
  3779. +
  3780. + if (type == YAFFS_OBJECT_TYPE_FILE) {
  3781. + tn = yaffs_get_tnode(dev);
  3782. + if (!tn)
  3783. + return NULL;
  3784. + }
  3785. +
  3786. + the_obj = yaffs_alloc_empty_obj(dev);
  3787. + if (!the_obj) {
  3788. + if (tn)
  3789. + yaffs_free_tnode(dev, tn);
  3790. + return NULL;
  3791. + }
  3792. +
  3793. + the_obj->fake = 0;
  3794. + the_obj->rename_allowed = 1;
  3795. + the_obj->unlink_allowed = 1;
  3796. + the_obj->obj_id = number;
  3797. + yaffs_hash_obj(the_obj);
  3798. + the_obj->variant_type = type;
  3799. + yaffs_load_current_time(the_obj, 1, 1);
  3800. +
  3801. + switch (type) {
  3802. + case YAFFS_OBJECT_TYPE_FILE:
  3803. + the_obj->variant.file_variant.file_size = 0;
  3804. + the_obj->variant.file_variant.scanned_size = 0;
  3805. + the_obj->variant.file_variant.shrink_size =
  3806. + yaffs_max_file_size(dev);
  3807. + the_obj->variant.file_variant.top_level = 0;
  3808. + the_obj->variant.file_variant.top = tn;
  3809. + break;
  3810. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  3811. + INIT_LIST_HEAD(&the_obj->variant.dir_variant.children);
  3812. + INIT_LIST_HEAD(&the_obj->variant.dir_variant.dirty);
  3813. + break;
  3814. + case YAFFS_OBJECT_TYPE_SYMLINK:
  3815. + case YAFFS_OBJECT_TYPE_HARDLINK:
  3816. + case YAFFS_OBJECT_TYPE_SPECIAL:
  3817. + /* No action required */
  3818. + break;
  3819. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  3820. + /* todo this should not happen */
  3821. + break;
  3822. + }
  3823. + return the_obj;
  3824. +}
  3825. +
  3826. +static struct yaffs_obj *yaffs_create_fake_dir(struct yaffs_dev *dev,
  3827. + int number, u32 mode)
  3828. +{
  3829. +
  3830. + struct yaffs_obj *obj =
  3831. + yaffs_new_obj(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
  3832. +
  3833. + if (!obj)
  3834. + return NULL;
  3835. +
  3836. + obj->fake = 1; /* it is fake so it might not use NAND */
  3837. + obj->rename_allowed = 0;
  3838. + obj->unlink_allowed = 0;
  3839. + obj->deleted = 0;
  3840. + obj->unlinked = 0;
  3841. + obj->yst_mode = mode;
  3842. + obj->my_dev = dev;
  3843. + obj->hdr_chunk = 0; /* Not a valid chunk. */
  3844. + return obj;
  3845. +
  3846. +}
  3847. +
  3848. +
  3849. +static void yaffs_init_tnodes_and_objs(struct yaffs_dev *dev)
  3850. +{
  3851. + int i;
  3852. +
  3853. + dev->n_obj = 0;
  3854. + dev->n_tnodes = 0;
  3855. + yaffs_init_raw_tnodes_and_objs(dev);
  3856. +
  3857. + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
  3858. + INIT_LIST_HEAD(&dev->obj_bucket[i].list);
  3859. + dev->obj_bucket[i].count = 0;
  3860. + }
  3861. +}
  3862. +
  3863. +struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
  3864. + int number,
  3865. + enum yaffs_obj_type type)
  3866. +{
  3867. + struct yaffs_obj *the_obj = NULL;
  3868. +
  3869. + if (number > 0)
  3870. + the_obj = yaffs_find_by_number(dev, number);
  3871. +
  3872. + if (!the_obj)
  3873. + the_obj = yaffs_new_obj(dev, number, type);
  3874. +
  3875. + return the_obj;
  3876. +
  3877. +}
  3878. +
  3879. +YCHAR *yaffs_clone_str(const YCHAR *str)
  3880. +{
  3881. + YCHAR *new_str = NULL;
  3882. + int len;
  3883. +
  3884. + if (!str)
  3885. + str = _Y("");
  3886. +
  3887. + len = strnlen(str, YAFFS_MAX_ALIAS_LENGTH);
  3888. + new_str = kmalloc((len + 1) * sizeof(YCHAR), GFP_NOFS);
  3889. + if (new_str) {
  3890. + strncpy(new_str, str, len);
  3891. + new_str[len] = 0;
  3892. + }
  3893. + return new_str;
  3894. +
  3895. +}
  3896. +/*
  3897. + *yaffs_update_parent() handles fixing a directories mtime and ctime when a new
  3898. + * link (ie. name) is created or deleted in the directory.
  3899. + *
  3900. + * ie.
  3901. + * create dir/a : update dir's mtime/ctime
  3902. + * rm dir/a: update dir's mtime/ctime
  3903. + * modify dir/a: don't update dir's mtimme/ctime
  3904. + *
  3905. + * This can be handled immediately or defered. Defering helps reduce the number
  3906. + * of updates when many files in a directory are changed within a brief period.
  3907. + *
  3908. + * If the directory updating is defered then yaffs_update_dirty_dirs must be
  3909. + * called periodically.
  3910. + */
  3911. +
  3912. +static void yaffs_update_parent(struct yaffs_obj *obj)
  3913. +{
  3914. + struct yaffs_dev *dev;
  3915. +
  3916. + if (!obj)
  3917. + return;
  3918. + dev = obj->my_dev;
  3919. + obj->dirty = 1;
  3920. + yaffs_load_current_time(obj, 0, 1);
  3921. + if (dev->param.defered_dir_update) {
  3922. + struct list_head *link = &obj->variant.dir_variant.dirty;
  3923. +
  3924. + if (list_empty(link)) {
  3925. + list_add(link, &dev->dirty_dirs);
  3926. + yaffs_trace(YAFFS_TRACE_BACKGROUND,
  3927. + "Added object %d to dirty directories",
  3928. + obj->obj_id);
  3929. + }
  3930. +
  3931. + } else {
  3932. + yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
  3933. + }
  3934. +}
  3935. +
  3936. +void yaffs_update_dirty_dirs(struct yaffs_dev *dev)
  3937. +{
  3938. + struct list_head *link;
  3939. + struct yaffs_obj *obj;
  3940. + struct yaffs_dir_var *d_s;
  3941. + union yaffs_obj_var *o_v;
  3942. +
  3943. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update dirty directories");
  3944. +
  3945. + while (!list_empty(&dev->dirty_dirs)) {
  3946. + link = dev->dirty_dirs.next;
  3947. + list_del_init(link);
  3948. +
  3949. + d_s = list_entry(link, struct yaffs_dir_var, dirty);
  3950. + o_v = list_entry(d_s, union yaffs_obj_var, dir_variant);
  3951. + obj = list_entry(o_v, struct yaffs_obj, variant);
  3952. +
  3953. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update directory %d",
  3954. + obj->obj_id);
  3955. +
  3956. + if (obj->dirty)
  3957. + yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
  3958. + }
  3959. +}
  3960. +
  3961. +/*
  3962. + * Mknod (create) a new object.
  3963. + * equiv_obj only has meaning for a hard link;
  3964. + * alias_str only has meaning for a symlink.
  3965. + * rdev only has meaning for devices (a subset of special objects)
  3966. + */
  3967. +
  3968. +static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type,
  3969. + struct yaffs_obj *parent,
  3970. + const YCHAR *name,
  3971. + u32 mode,
  3972. + u32 uid,
  3973. + u32 gid,
  3974. + struct yaffs_obj *equiv_obj,
  3975. + const YCHAR *alias_str, u32 rdev)
  3976. +{
  3977. + struct yaffs_obj *in;
  3978. + YCHAR *str = NULL;
  3979. + struct yaffs_dev *dev = parent->my_dev;
  3980. +
  3981. + /* Check if the entry exists.
  3982. + * If it does then fail the call since we don't want a dup. */
  3983. + if (yaffs_find_by_name(parent, name))
  3984. + return NULL;
  3985. +
  3986. + if (type == YAFFS_OBJECT_TYPE_SYMLINK) {
  3987. + str = yaffs_clone_str(alias_str);
  3988. + if (!str)
  3989. + return NULL;
  3990. + }
  3991. +
  3992. + in = yaffs_new_obj(dev, -1, type);
  3993. +
  3994. + if (!in) {
  3995. + kfree(str);
  3996. + return NULL;
  3997. + }
  3998. +
  3999. + in->hdr_chunk = 0;
  4000. + in->valid = 1;
  4001. + in->variant_type = type;
  4002. +
  4003. + in->yst_mode = mode;
  4004. +
  4005. + yaffs_attribs_init(in, gid, uid, rdev);
  4006. +
  4007. + in->n_data_chunks = 0;
  4008. +
  4009. + yaffs_set_obj_name(in, name);
  4010. + in->dirty = 1;
  4011. +
  4012. + yaffs_add_obj_to_dir(parent, in);
  4013. +
  4014. + in->my_dev = parent->my_dev;
  4015. +
  4016. + switch (type) {
  4017. + case YAFFS_OBJECT_TYPE_SYMLINK:
  4018. + in->variant.symlink_variant.alias = str;
  4019. + break;
  4020. + case YAFFS_OBJECT_TYPE_HARDLINK:
  4021. + in->variant.hardlink_variant.equiv_obj = equiv_obj;
  4022. + in->variant.hardlink_variant.equiv_id = equiv_obj->obj_id;
  4023. + list_add(&in->hard_links, &equiv_obj->hard_links);
  4024. + break;
  4025. + case YAFFS_OBJECT_TYPE_FILE:
  4026. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  4027. + case YAFFS_OBJECT_TYPE_SPECIAL:
  4028. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  4029. + /* do nothing */
  4030. + break;
  4031. + }
  4032. +
  4033. + if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) {
  4034. + /* Could not create the object header, fail */
  4035. + yaffs_del_obj(in);
  4036. + in = NULL;
  4037. + }
  4038. +
  4039. + if (in)
  4040. + yaffs_update_parent(parent);
  4041. +
  4042. + return in;
  4043. +}
  4044. +
  4045. +struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
  4046. + const YCHAR *name, u32 mode, u32 uid,
  4047. + u32 gid)
  4048. +{
  4049. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,
  4050. + uid, gid, NULL, NULL, 0);
  4051. +}
  4052. +
  4053. +struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name,
  4054. + u32 mode, u32 uid, u32 gid)
  4055. +{
  4056. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,
  4057. + mode, uid, gid, NULL, NULL, 0);
  4058. +}
  4059. +
  4060. +struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
  4061. + const YCHAR *name, u32 mode, u32 uid,
  4062. + u32 gid, u32 rdev)
  4063. +{
  4064. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,
  4065. + uid, gid, NULL, NULL, rdev);
  4066. +}
  4067. +
  4068. +struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
  4069. + const YCHAR *name, u32 mode, u32 uid,
  4070. + u32 gid, const YCHAR *alias)
  4071. +{
  4072. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,
  4073. + uid, gid, NULL, alias, 0);
  4074. +}
  4075. +
  4076. +/* yaffs_link_obj returns the object id of the equivalent object.*/
  4077. +struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR * name,
  4078. + struct yaffs_obj *equiv_obj)
  4079. +{
  4080. + /* Get the real object in case we were fed a hard link obj */
  4081. + equiv_obj = yaffs_get_equivalent_obj(equiv_obj);
  4082. +
  4083. + if (yaffs_create_obj(YAFFS_OBJECT_TYPE_HARDLINK,
  4084. + parent, name, 0, 0, 0,
  4085. + equiv_obj, NULL, 0))
  4086. + return equiv_obj;
  4087. +
  4088. + return NULL;
  4089. +
  4090. +}
  4091. +
  4092. +
  4093. +
  4094. +/*---------------------- Block Management and Page Allocation -------------*/
  4095. +
  4096. +static void yaffs_deinit_blocks(struct yaffs_dev *dev)
  4097. +{
  4098. + if (dev->block_info_alt && dev->block_info)
  4099. + vfree(dev->block_info);
  4100. + else
  4101. + kfree(dev->block_info);
  4102. +
  4103. + dev->block_info_alt = 0;
  4104. +
  4105. + dev->block_info = NULL;
  4106. +
  4107. + if (dev->chunk_bits_alt && dev->chunk_bits)
  4108. + vfree(dev->chunk_bits);
  4109. + else
  4110. + kfree(dev->chunk_bits);
  4111. + dev->chunk_bits_alt = 0;
  4112. + dev->chunk_bits = NULL;
  4113. +}
  4114. +
  4115. +static int yaffs_init_blocks(struct yaffs_dev *dev)
  4116. +{
  4117. + int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
  4118. +
  4119. + dev->block_info = NULL;
  4120. + dev->chunk_bits = NULL;
  4121. + dev->alloc_block = -1; /* force it to get a new one */
  4122. +
  4123. + /* If the first allocation strategy fails, thry the alternate one */
  4124. + dev->block_info =
  4125. + kmalloc(n_blocks * sizeof(struct yaffs_block_info), GFP_NOFS);
  4126. + if (!dev->block_info) {
  4127. + dev->block_info =
  4128. + vmalloc(n_blocks * sizeof(struct yaffs_block_info));
  4129. + dev->block_info_alt = 1;
  4130. + } else {
  4131. + dev->block_info_alt = 0;
  4132. + }
  4133. +
  4134. + if (!dev->block_info)
  4135. + goto alloc_error;
  4136. +
  4137. + /* Set up dynamic blockinfo stuff. Round up bytes. */
  4138. + dev->chunk_bit_stride = (dev->param.chunks_per_block + 7) / 8;
  4139. + dev->chunk_bits =
  4140. + kmalloc(dev->chunk_bit_stride * n_blocks, GFP_NOFS);
  4141. + if (!dev->chunk_bits) {
  4142. + dev->chunk_bits =
  4143. + vmalloc(dev->chunk_bit_stride * n_blocks);
  4144. + dev->chunk_bits_alt = 1;
  4145. + } else {
  4146. + dev->chunk_bits_alt = 0;
  4147. + }
  4148. + if (!dev->chunk_bits)
  4149. + goto alloc_error;
  4150. +
  4151. +
  4152. + memset(dev->block_info, 0, n_blocks * sizeof(struct yaffs_block_info));
  4153. + memset(dev->chunk_bits, 0, dev->chunk_bit_stride * n_blocks);
  4154. + return YAFFS_OK;
  4155. +
  4156. +alloc_error:
  4157. + yaffs_deinit_blocks(dev);
  4158. + return YAFFS_FAIL;
  4159. +}
  4160. +
  4161. +
  4162. +void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no)
  4163. +{
  4164. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, block_no);
  4165. + int erased_ok = 0;
  4166. + int i;
  4167. +
  4168. + /* If the block is still healthy erase it and mark as clean.
  4169. + * If the block has had a data failure, then retire it.
  4170. + */
  4171. +
  4172. + yaffs_trace(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
  4173. + "yaffs_block_became_dirty block %d state %d %s",
  4174. + block_no, bi->block_state,
  4175. + (bi->needs_retiring) ? "needs retiring" : "");
  4176. +
  4177. + yaffs2_clear_oldest_dirty_seq(dev, bi);
  4178. +
  4179. + bi->block_state = YAFFS_BLOCK_STATE_DIRTY;
  4180. +
  4181. + /* If this is the block being garbage collected then stop gc'ing */
  4182. + if (block_no == dev->gc_block)
  4183. + dev->gc_block = 0;
  4184. +
  4185. + /* If this block is currently the best candidate for gc
  4186. + * then drop as a candidate */
  4187. + if (block_no == dev->gc_dirtiest) {
  4188. + dev->gc_dirtiest = 0;
  4189. + dev->gc_pages_in_use = 0;
  4190. + }
  4191. +
  4192. + if (!bi->needs_retiring) {
  4193. + yaffs2_checkpt_invalidate(dev);
  4194. + erased_ok = yaffs_erase_block(dev, block_no);
  4195. + if (!erased_ok) {
  4196. + dev->n_erase_failures++;
  4197. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  4198. + "**>> Erasure failed %d", block_no);
  4199. + }
  4200. + }
  4201. +
  4202. + /* Verify erasure if needed */
  4203. + if (erased_ok &&
  4204. + ((yaffs_trace_mask & YAFFS_TRACE_ERASE) ||
  4205. + !yaffs_skip_verification(dev))) {
  4206. + for (i = 0; i < dev->param.chunks_per_block; i++) {
  4207. + if (!yaffs_check_chunk_erased(dev,
  4208. + block_no * dev->param.chunks_per_block + i)) {
  4209. + yaffs_trace(YAFFS_TRACE_ERROR,
  4210. + ">>Block %d erasure supposedly OK, but chunk %d not erased",
  4211. + block_no, i);
  4212. + }
  4213. + }
  4214. + }
  4215. +
  4216. + if (!erased_ok) {
  4217. + /* We lost a block of free space */
  4218. + dev->n_free_chunks -= dev->param.chunks_per_block;
  4219. + yaffs_retire_block(dev, block_no);
  4220. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  4221. + "**>> Block %d retired", block_no);
  4222. + return;
  4223. + }
  4224. +
  4225. + /* Clean it up... */
  4226. + bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
  4227. + bi->seq_number = 0;
  4228. + dev->n_erased_blocks++;
  4229. + bi->pages_in_use = 0;
  4230. + bi->soft_del_pages = 0;
  4231. + bi->has_shrink_hdr = 0;
  4232. + bi->skip_erased_check = 1; /* Clean, so no need to check */
  4233. + bi->gc_prioritise = 0;
  4234. + bi->has_summary = 0;
  4235. +
  4236. + yaffs_clear_chunk_bits(dev, block_no);
  4237. +
  4238. + yaffs_trace(YAFFS_TRACE_ERASE, "Erased block %d", block_no);
  4239. +}
  4240. +
  4241. +static inline int yaffs_gc_process_chunk(struct yaffs_dev *dev,
  4242. + struct yaffs_block_info *bi,
  4243. + int old_chunk, u8 *buffer)
  4244. +{
  4245. + int new_chunk;
  4246. + int mark_flash = 1;
  4247. + struct yaffs_ext_tags tags;
  4248. + struct yaffs_obj *object;
  4249. + int matching_chunk;
  4250. + int ret_val = YAFFS_OK;
  4251. +
  4252. + memset(&tags, 0, sizeof(tags));
  4253. + yaffs_rd_chunk_tags_nand(dev, old_chunk,
  4254. + buffer, &tags);
  4255. + object = yaffs_find_by_number(dev, tags.obj_id);
  4256. +
  4257. + yaffs_trace(YAFFS_TRACE_GC_DETAIL,
  4258. + "Collecting chunk in block %d, %d %d %d ",
  4259. + dev->gc_chunk, tags.obj_id,
  4260. + tags.chunk_id, tags.n_bytes);
  4261. +
  4262. + if (object && !yaffs_skip_verification(dev)) {
  4263. + if (tags.chunk_id == 0)
  4264. + matching_chunk =
  4265. + object->hdr_chunk;
  4266. + else if (object->soft_del)
  4267. + /* Defeat the test */
  4268. + matching_chunk = old_chunk;
  4269. + else
  4270. + matching_chunk =
  4271. + yaffs_find_chunk_in_file
  4272. + (object, tags.chunk_id,
  4273. + NULL);
  4274. +
  4275. + if (old_chunk != matching_chunk)
  4276. + yaffs_trace(YAFFS_TRACE_ERROR,
  4277. + "gc: page in gc mismatch: %d %d %d %d",
  4278. + old_chunk,
  4279. + matching_chunk,
  4280. + tags.obj_id,
  4281. + tags.chunk_id);
  4282. + }
  4283. +
  4284. + if (!object) {
  4285. + yaffs_trace(YAFFS_TRACE_ERROR,
  4286. + "page %d in gc has no object: %d %d %d ",
  4287. + old_chunk,
  4288. + tags.obj_id, tags.chunk_id,
  4289. + tags.n_bytes);
  4290. + }
  4291. +
  4292. + if (object &&
  4293. + object->deleted &&
  4294. + object->soft_del && tags.chunk_id != 0) {
  4295. + /* Data chunk in a soft deleted file,
  4296. + * throw it away.
  4297. + * It's a soft deleted data chunk,
  4298. + * No need to copy this, just forget
  4299. + * about it and fix up the object.
  4300. + */
  4301. +
  4302. + /* Free chunks already includes
  4303. + * softdeleted chunks, how ever this
  4304. + * chunk is going to soon be really
  4305. + * deleted which will increment free
  4306. + * chunks. We have to decrement free
  4307. + * chunks so this works out properly.
  4308. + */
  4309. + dev->n_free_chunks--;
  4310. + bi->soft_del_pages--;
  4311. +
  4312. + object->n_data_chunks--;
  4313. + if (object->n_data_chunks <= 0) {
  4314. + /* remeber to clean up obj */
  4315. + dev->gc_cleanup_list[dev->n_clean_ups] = tags.obj_id;
  4316. + dev->n_clean_ups++;
  4317. + }
  4318. + mark_flash = 0;
  4319. + } else if (object) {
  4320. + /* It's either a data chunk in a live
  4321. + * file or an ObjectHeader, so we're
  4322. + * interested in it.
  4323. + * NB Need to keep the ObjectHeaders of
  4324. + * deleted files until the whole file
  4325. + * has been deleted off
  4326. + */
  4327. + tags.serial_number++;
  4328. + dev->n_gc_copies++;
  4329. +
  4330. + if (tags.chunk_id == 0) {
  4331. + /* It is an object Id,
  4332. + * We need to nuke the
  4333. + * shrinkheader flags since its
  4334. + * work is done.
  4335. + * Also need to clean up
  4336. + * shadowing.
  4337. + */
  4338. + struct yaffs_obj_hdr *oh;
  4339. + oh = (struct yaffs_obj_hdr *) buffer;
  4340. +
  4341. + oh->is_shrink = 0;
  4342. + tags.extra_is_shrink = 0;
  4343. + oh->shadows_obj = 0;
  4344. + oh->inband_shadowed_obj_id = 0;
  4345. + tags.extra_shadows = 0;
  4346. +
  4347. + /* Update file size */
  4348. + if (object->variant_type == YAFFS_OBJECT_TYPE_FILE) {
  4349. + yaffs_oh_size_load(oh,
  4350. + object->variant.file_variant.file_size);
  4351. + tags.extra_file_size =
  4352. + object->variant.file_variant.file_size;
  4353. + }
  4354. +
  4355. + yaffs_verify_oh(object, oh, &tags, 1);
  4356. + new_chunk =
  4357. + yaffs_write_new_chunk(dev, (u8 *) oh, &tags, 1);
  4358. + } else {
  4359. + new_chunk =
  4360. + yaffs_write_new_chunk(dev, buffer, &tags, 1);
  4361. + }
  4362. +
  4363. + if (new_chunk < 0) {
  4364. + ret_val = YAFFS_FAIL;
  4365. + } else {
  4366. +
  4367. + /* Now fix up the Tnodes etc. */
  4368. +
  4369. + if (tags.chunk_id == 0) {
  4370. + /* It's a header */
  4371. + object->hdr_chunk = new_chunk;
  4372. + object->serial = tags.serial_number;
  4373. + } else {
  4374. + /* It's a data chunk */
  4375. + yaffs_put_chunk_in_file(object, tags.chunk_id,
  4376. + new_chunk, 0);
  4377. + }
  4378. + }
  4379. + }
  4380. + if (ret_val == YAFFS_OK)
  4381. + yaffs_chunk_del(dev, old_chunk, mark_flash, __LINE__);
  4382. + return ret_val;
  4383. +}
  4384. +
  4385. +static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block)
  4386. +{
  4387. + int old_chunk;
  4388. + int ret_val = YAFFS_OK;
  4389. + int i;
  4390. + int is_checkpt_block;
  4391. + int max_copies;
  4392. + int chunks_before = yaffs_get_erased_chunks(dev);
  4393. + int chunks_after;
  4394. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, block);
  4395. +
  4396. + is_checkpt_block = (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT);
  4397. +
  4398. + yaffs_trace(YAFFS_TRACE_TRACING,
  4399. + "Collecting block %d, in use %d, shrink %d, whole_block %d",
  4400. + block, bi->pages_in_use, bi->has_shrink_hdr,
  4401. + whole_block);
  4402. +
  4403. + /*yaffs_verify_free_chunks(dev); */
  4404. +
  4405. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL)
  4406. + bi->block_state = YAFFS_BLOCK_STATE_COLLECTING;
  4407. +
  4408. + bi->has_shrink_hdr = 0; /* clear the flag so that the block can erase */
  4409. +
  4410. + dev->gc_disable = 1;
  4411. +
  4412. + yaffs_summary_gc(dev, block);
  4413. +
  4414. + if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) {
  4415. + yaffs_trace(YAFFS_TRACE_TRACING,
  4416. + "Collecting block %d that has no chunks in use",
  4417. + block);
  4418. + yaffs_block_became_dirty(dev, block);
  4419. + } else {
  4420. +
  4421. + u8 *buffer = yaffs_get_temp_buffer(dev);
  4422. +
  4423. + yaffs_verify_blk(dev, bi, block);
  4424. +
  4425. + max_copies = (whole_block) ? dev->param.chunks_per_block : 5;
  4426. + old_chunk = block * dev->param.chunks_per_block + dev->gc_chunk;
  4427. +
  4428. + for (/* init already done */ ;
  4429. + ret_val == YAFFS_OK &&
  4430. + dev->gc_chunk < dev->param.chunks_per_block &&
  4431. + (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) &&
  4432. + max_copies > 0;
  4433. + dev->gc_chunk++, old_chunk++) {
  4434. + if (yaffs_check_chunk_bit(dev, block, dev->gc_chunk)) {
  4435. + /* Page is in use and might need to be copied */
  4436. + max_copies--;
  4437. + ret_val = yaffs_gc_process_chunk(dev, bi,
  4438. + old_chunk, buffer);
  4439. + }
  4440. + }
  4441. + yaffs_release_temp_buffer(dev, buffer);
  4442. + }
  4443. +
  4444. + yaffs_verify_collected_blk(dev, bi, block);
  4445. +
  4446. + if (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
  4447. + /*
  4448. + * The gc did not complete. Set block state back to FULL
  4449. + * because checkpointing does not restore gc.
  4450. + */
  4451. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  4452. + } else {
  4453. + /* The gc completed. */
  4454. + /* Do any required cleanups */
  4455. + for (i = 0; i < dev->n_clean_ups; i++) {
  4456. + /* Time to delete the file too */
  4457. + struct yaffs_obj *object =
  4458. + yaffs_find_by_number(dev, dev->gc_cleanup_list[i]);
  4459. + if (object) {
  4460. + yaffs_free_tnode(dev,
  4461. + object->variant.file_variant.top);
  4462. + object->variant.file_variant.top = NULL;
  4463. + yaffs_trace(YAFFS_TRACE_GC,
  4464. + "yaffs: About to finally delete object %d",
  4465. + object->obj_id);
  4466. + yaffs_generic_obj_del(object);
  4467. + object->my_dev->n_deleted_files--;
  4468. + }
  4469. +
  4470. + }
  4471. + chunks_after = yaffs_get_erased_chunks(dev);
  4472. + if (chunks_before >= chunks_after)
  4473. + yaffs_trace(YAFFS_TRACE_GC,
  4474. + "gc did not increase free chunks before %d after %d",
  4475. + chunks_before, chunks_after);
  4476. + dev->gc_block = 0;
  4477. + dev->gc_chunk = 0;
  4478. + dev->n_clean_ups = 0;
  4479. + }
  4480. +
  4481. + dev->gc_disable = 0;
  4482. +
  4483. + return ret_val;
  4484. +}
  4485. +
  4486. +/*
  4487. + * find_gc_block() selects the dirtiest block (or close enough)
  4488. + * for garbage collection.
  4489. + */
  4490. +
  4491. +static unsigned yaffs_find_gc_block(struct yaffs_dev *dev,
  4492. + int aggressive, int background)
  4493. +{
  4494. + int i;
  4495. + int iterations;
  4496. + unsigned selected = 0;
  4497. + int prioritised = 0;
  4498. + int prioritised_exist = 0;
  4499. + struct yaffs_block_info *bi;
  4500. + int threshold;
  4501. +
  4502. + /* First let's see if we need to grab a prioritised block */
  4503. + if (dev->has_pending_prioritised_gc && !aggressive) {
  4504. + dev->gc_dirtiest = 0;
  4505. + bi = dev->block_info;
  4506. + for (i = dev->internal_start_block;
  4507. + i <= dev->internal_end_block && !selected; i++) {
  4508. +
  4509. + if (bi->gc_prioritise) {
  4510. + prioritised_exist = 1;
  4511. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
  4512. + yaffs_block_ok_for_gc(dev, bi)) {
  4513. + selected = i;
  4514. + prioritised = 1;
  4515. + }
  4516. + }
  4517. + bi++;
  4518. + }
  4519. +
  4520. + /*
  4521. + * If there is a prioritised block and none was selected then
  4522. + * this happened because there is at least one old dirty block
  4523. + * gumming up the works. Let's gc the oldest dirty block.
  4524. + */
  4525. +
  4526. + if (prioritised_exist &&
  4527. + !selected && dev->oldest_dirty_block > 0)
  4528. + selected = dev->oldest_dirty_block;
  4529. +
  4530. + if (!prioritised_exist) /* None found, so we can clear this */
  4531. + dev->has_pending_prioritised_gc = 0;
  4532. + }
  4533. +
  4534. + /* If we're doing aggressive GC then we are happy to take a less-dirty
  4535. + * block, and search harder.
  4536. + * else (leasurely gc), then we only bother to do this if the
  4537. + * block has only a few pages in use.
  4538. + */
  4539. +
  4540. + if (!selected) {
  4541. + int pages_used;
  4542. + int n_blocks =
  4543. + dev->internal_end_block - dev->internal_start_block + 1;
  4544. + if (aggressive) {
  4545. + threshold = dev->param.chunks_per_block;
  4546. + iterations = n_blocks;
  4547. + } else {
  4548. + int max_threshold;
  4549. +
  4550. + if (background)
  4551. + max_threshold = dev->param.chunks_per_block / 2;
  4552. + else
  4553. + max_threshold = dev->param.chunks_per_block / 8;
  4554. +
  4555. + if (max_threshold < YAFFS_GC_PASSIVE_THRESHOLD)
  4556. + max_threshold = YAFFS_GC_PASSIVE_THRESHOLD;
  4557. +
  4558. + threshold = background ? (dev->gc_not_done + 2) * 2 : 0;
  4559. + if (threshold < YAFFS_GC_PASSIVE_THRESHOLD)
  4560. + threshold = YAFFS_GC_PASSIVE_THRESHOLD;
  4561. + if (threshold > max_threshold)
  4562. + threshold = max_threshold;
  4563. +
  4564. + iterations = n_blocks / 16 + 1;
  4565. + if (iterations > 100)
  4566. + iterations = 100;
  4567. + }
  4568. +
  4569. + for (i = 0;
  4570. + i < iterations &&
  4571. + (dev->gc_dirtiest < 1 ||
  4572. + dev->gc_pages_in_use > YAFFS_GC_GOOD_ENOUGH);
  4573. + i++) {
  4574. + dev->gc_block_finder++;
  4575. + if (dev->gc_block_finder < dev->internal_start_block ||
  4576. + dev->gc_block_finder > dev->internal_end_block)
  4577. + dev->gc_block_finder =
  4578. + dev->internal_start_block;
  4579. +
  4580. + bi = yaffs_get_block_info(dev, dev->gc_block_finder);
  4581. +
  4582. + pages_used = bi->pages_in_use - bi->soft_del_pages;
  4583. +
  4584. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
  4585. + pages_used < dev->param.chunks_per_block &&
  4586. + (dev->gc_dirtiest < 1 ||
  4587. + pages_used < dev->gc_pages_in_use) &&
  4588. + yaffs_block_ok_for_gc(dev, bi)) {
  4589. + dev->gc_dirtiest = dev->gc_block_finder;
  4590. + dev->gc_pages_in_use = pages_used;
  4591. + }
  4592. + }
  4593. +
  4594. + if (dev->gc_dirtiest > 0 && dev->gc_pages_in_use <= threshold)
  4595. + selected = dev->gc_dirtiest;
  4596. + }
  4597. +
  4598. + /*
  4599. + * If nothing has been selected for a while, try the oldest dirty
  4600. + * because that's gumming up the works.
  4601. + */
  4602. +
  4603. + if (!selected && dev->param.is_yaffs2 &&
  4604. + dev->gc_not_done >= (background ? 10 : 20)) {
  4605. + yaffs2_find_oldest_dirty_seq(dev);
  4606. + if (dev->oldest_dirty_block > 0) {
  4607. + selected = dev->oldest_dirty_block;
  4608. + dev->gc_dirtiest = selected;
  4609. + dev->oldest_dirty_gc_count++;
  4610. + bi = yaffs_get_block_info(dev, selected);
  4611. + dev->gc_pages_in_use =
  4612. + bi->pages_in_use - bi->soft_del_pages;
  4613. + } else {
  4614. + dev->gc_not_done = 0;
  4615. + }
  4616. + }
  4617. +
  4618. + if (selected) {
  4619. + yaffs_trace(YAFFS_TRACE_GC,
  4620. + "GC Selected block %d with %d free, prioritised:%d",
  4621. + selected,
  4622. + dev->param.chunks_per_block - dev->gc_pages_in_use,
  4623. + prioritised);
  4624. +
  4625. + dev->n_gc_blocks++;
  4626. + if (background)
  4627. + dev->bg_gcs++;
  4628. +
  4629. + dev->gc_dirtiest = 0;
  4630. + dev->gc_pages_in_use = 0;
  4631. + dev->gc_not_done = 0;
  4632. + if (dev->refresh_skip > 0)
  4633. + dev->refresh_skip--;
  4634. + } else {
  4635. + dev->gc_not_done++;
  4636. + yaffs_trace(YAFFS_TRACE_GC,
  4637. + "GC none: finder %d skip %d threshold %d dirtiest %d using %d oldest %d%s",
  4638. + dev->gc_block_finder, dev->gc_not_done, threshold,
  4639. + dev->gc_dirtiest, dev->gc_pages_in_use,
  4640. + dev->oldest_dirty_block, background ? " bg" : "");
  4641. + }
  4642. +
  4643. + return selected;
  4644. +}
  4645. +
  4646. +/* New garbage collector
  4647. + * If we're very low on erased blocks then we do aggressive garbage collection
  4648. + * otherwise we do "leasurely" garbage collection.
  4649. + * Aggressive gc looks further (whole array) and will accept less dirty blocks.
  4650. + * Passive gc only inspects smaller areas and only accepts more dirty blocks.
  4651. + *
  4652. + * The idea is to help clear out space in a more spread-out manner.
  4653. + * Dunno if it really does anything useful.
  4654. + */
  4655. +static int yaffs_check_gc(struct yaffs_dev *dev, int background)
  4656. +{
  4657. + int aggressive = 0;
  4658. + int gc_ok = YAFFS_OK;
  4659. + int max_tries = 0;
  4660. + int min_erased;
  4661. + int erased_chunks;
  4662. + int checkpt_block_adjust;
  4663. +
  4664. + if (dev->param.gc_control_fn &&
  4665. + (dev->param.gc_control_fn(dev) & 1) == 0)
  4666. + return YAFFS_OK;
  4667. +
  4668. + if (dev->gc_disable)
  4669. + /* Bail out so we don't get recursive gc */
  4670. + return YAFFS_OK;
  4671. +
  4672. + /* This loop should pass the first time.
  4673. + * Only loops here if the collection does not increase space.
  4674. + */
  4675. +
  4676. + do {
  4677. + max_tries++;
  4678. +
  4679. + checkpt_block_adjust = yaffs_calc_checkpt_blocks_required(dev);
  4680. +
  4681. + min_erased =
  4682. + dev->param.n_reserved_blocks + checkpt_block_adjust + 1;
  4683. + erased_chunks =
  4684. + dev->n_erased_blocks * dev->param.chunks_per_block;
  4685. +
  4686. + /* If we need a block soon then do aggressive gc. */
  4687. + if (dev->n_erased_blocks < min_erased)
  4688. + aggressive = 1;
  4689. + else {
  4690. + if (!background
  4691. + && erased_chunks > (dev->n_free_chunks / 4))
  4692. + break;
  4693. +
  4694. + if (dev->gc_skip > 20)
  4695. + dev->gc_skip = 20;
  4696. + if (erased_chunks < dev->n_free_chunks / 2 ||
  4697. + dev->gc_skip < 1 || background)
  4698. + aggressive = 0;
  4699. + else {
  4700. + dev->gc_skip--;
  4701. + break;
  4702. + }
  4703. + }
  4704. +
  4705. + dev->gc_skip = 5;
  4706. +
  4707. + /* If we don't already have a block being gc'd then see if we
  4708. + * should start another */
  4709. +
  4710. + if (dev->gc_block < 1 && !aggressive) {
  4711. + dev->gc_block = yaffs2_find_refresh_block(dev);
  4712. + dev->gc_chunk = 0;
  4713. + dev->n_clean_ups = 0;
  4714. + }
  4715. + if (dev->gc_block < 1) {
  4716. + dev->gc_block =
  4717. + yaffs_find_gc_block(dev, aggressive, background);
  4718. + dev->gc_chunk = 0;
  4719. + dev->n_clean_ups = 0;
  4720. + }
  4721. +
  4722. + if (dev->gc_block > 0) {
  4723. + dev->all_gcs++;
  4724. + if (!aggressive)
  4725. + dev->passive_gc_count++;
  4726. +
  4727. + yaffs_trace(YAFFS_TRACE_GC,
  4728. + "yaffs: GC n_erased_blocks %d aggressive %d",
  4729. + dev->n_erased_blocks, aggressive);
  4730. +
  4731. + gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive);
  4732. + }
  4733. +
  4734. + if (dev->n_erased_blocks < (dev->param.n_reserved_blocks) &&
  4735. + dev->gc_block > 0) {
  4736. + yaffs_trace(YAFFS_TRACE_GC,
  4737. + "yaffs: GC !!!no reclaim!!! n_erased_blocks %d after try %d block %d",
  4738. + dev->n_erased_blocks, max_tries,
  4739. + dev->gc_block);
  4740. + }
  4741. + } while ((dev->n_erased_blocks < dev->param.n_reserved_blocks) &&
  4742. + (dev->gc_block > 0) && (max_tries < 2));
  4743. +
  4744. + return aggressive ? gc_ok : YAFFS_OK;
  4745. +}
  4746. +
  4747. +/*
  4748. + * yaffs_bg_gc()
  4749. + * Garbage collects. Intended to be called from a background thread.
  4750. + * Returns non-zero if at least half the free chunks are erased.
  4751. + */
  4752. +int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency)
  4753. +{
  4754. + int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;
  4755. +
  4756. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "Background gc %u", urgency);
  4757. +
  4758. + yaffs_check_gc(dev, 1);
  4759. + return erased_chunks > dev->n_free_chunks / 2;
  4760. +}
  4761. +
  4762. +/*-------------------- Data file manipulation -----------------*/
  4763. +
  4764. +static int yaffs_rd_data_obj(struct yaffs_obj *in, int inode_chunk, u8 * buffer)
  4765. +{
  4766. + int nand_chunk = yaffs_find_chunk_in_file(in, inode_chunk, NULL);
  4767. +
  4768. + if (nand_chunk >= 0)
  4769. + return yaffs_rd_chunk_tags_nand(in->my_dev, nand_chunk,
  4770. + buffer, NULL);
  4771. + else {
  4772. + yaffs_trace(YAFFS_TRACE_NANDACCESS,
  4773. + "Chunk %d not found zero instead",
  4774. + nand_chunk);
  4775. + /* get sane (zero) data if you read a hole */
  4776. + memset(buffer, 0, in->my_dev->data_bytes_per_chunk);
  4777. + return 0;
  4778. + }
  4779. +
  4780. +}
  4781. +
  4782. +void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
  4783. + int lyn)
  4784. +{
  4785. + int block;
  4786. + int page;
  4787. + struct yaffs_ext_tags tags;
  4788. + struct yaffs_block_info *bi;
  4789. +
  4790. + if (chunk_id <= 0)
  4791. + return;
  4792. +
  4793. + dev->n_deletions++;
  4794. + block = chunk_id / dev->param.chunks_per_block;
  4795. + page = chunk_id % dev->param.chunks_per_block;
  4796. +
  4797. + if (!yaffs_check_chunk_bit(dev, block, page))
  4798. + yaffs_trace(YAFFS_TRACE_VERIFY,
  4799. + "Deleting invalid chunk %d", chunk_id);
  4800. +
  4801. + bi = yaffs_get_block_info(dev, block);
  4802. +
  4803. + yaffs2_update_oldest_dirty_seq(dev, block, bi);
  4804. +
  4805. + yaffs_trace(YAFFS_TRACE_DELETION,
  4806. + "line %d delete of chunk %d",
  4807. + lyn, chunk_id);
  4808. +
  4809. + if (!dev->param.is_yaffs2 && mark_flash &&
  4810. + bi->block_state != YAFFS_BLOCK_STATE_COLLECTING) {
  4811. +
  4812. + memset(&tags, 0, sizeof(tags));
  4813. + tags.is_deleted = 1;
  4814. + yaffs_wr_chunk_tags_nand(dev, chunk_id, NULL, &tags);
  4815. + yaffs_handle_chunk_update(dev, chunk_id, &tags);
  4816. + } else {
  4817. + dev->n_unmarked_deletions++;
  4818. + }
  4819. +
  4820. + /* Pull out of the management area.
  4821. + * If the whole block became dirty, this will kick off an erasure.
  4822. + */
  4823. + if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING ||
  4824. + bi->block_state == YAFFS_BLOCK_STATE_FULL ||
  4825. + bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
  4826. + bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
  4827. + dev->n_free_chunks++;
  4828. + yaffs_clear_chunk_bit(dev, block, page);
  4829. + bi->pages_in_use--;
  4830. +
  4831. + if (bi->pages_in_use == 0 &&
  4832. + !bi->has_shrink_hdr &&
  4833. + bi->block_state != YAFFS_BLOCK_STATE_ALLOCATING &&
  4834. + bi->block_state != YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  4835. + yaffs_block_became_dirty(dev, block);
  4836. + }
  4837. + }
  4838. +}
  4839. +
  4840. +static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
  4841. + const u8 *buffer, int n_bytes, int use_reserve)
  4842. +{
  4843. + /* Find old chunk Need to do this to get serial number
  4844. + * Write new one and patch into tree.
  4845. + * Invalidate old tags.
  4846. + */
  4847. +
  4848. + int prev_chunk_id;
  4849. + struct yaffs_ext_tags prev_tags;
  4850. + int new_chunk_id;
  4851. + struct yaffs_ext_tags new_tags;
  4852. + struct yaffs_dev *dev = in->my_dev;
  4853. +
  4854. + yaffs_check_gc(dev, 0);
  4855. +
  4856. + /* Get the previous chunk at this location in the file if it exists.
  4857. + * If it does not exist then put a zero into the tree. This creates
  4858. + * the tnode now, rather than later when it is harder to clean up.
  4859. + */
  4860. + prev_chunk_id = yaffs_find_chunk_in_file(in, inode_chunk, &prev_tags);
  4861. + if (prev_chunk_id < 1 &&
  4862. + !yaffs_put_chunk_in_file(in, inode_chunk, 0, 0))
  4863. + return 0;
  4864. +
  4865. + /* Set up new tags */
  4866. + memset(&new_tags, 0, sizeof(new_tags));
  4867. +
  4868. + new_tags.chunk_id = inode_chunk;
  4869. + new_tags.obj_id = in->obj_id;
  4870. + new_tags.serial_number =
  4871. + (prev_chunk_id > 0) ? prev_tags.serial_number + 1 : 1;
  4872. + new_tags.n_bytes = n_bytes;
  4873. +
  4874. + if (n_bytes < 1 || n_bytes > dev->param.total_bytes_per_chunk) {
  4875. + yaffs_trace(YAFFS_TRACE_ERROR,
  4876. + "Writing %d bytes to chunk!!!!!!!!!",
  4877. + n_bytes);
  4878. + BUG();
  4879. + }
  4880. +
  4881. + new_chunk_id =
  4882. + yaffs_write_new_chunk(dev, buffer, &new_tags, use_reserve);
  4883. +
  4884. + if (new_chunk_id > 0) {
  4885. + yaffs_put_chunk_in_file(in, inode_chunk, new_chunk_id, 0);
  4886. +
  4887. + if (prev_chunk_id > 0)
  4888. + yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);
  4889. +
  4890. + yaffs_verify_file_sane(in);
  4891. + }
  4892. + return new_chunk_id;
  4893. +
  4894. +}
  4895. +
  4896. +
  4897. +
  4898. +static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set,
  4899. + const YCHAR *name, const void *value, int size,
  4900. + int flags)
  4901. +{
  4902. + struct yaffs_xattr_mod xmod;
  4903. + int result;
  4904. +
  4905. + xmod.set = set;
  4906. + xmod.name = name;
  4907. + xmod.data = value;
  4908. + xmod.size = size;
  4909. + xmod.flags = flags;
  4910. + xmod.result = -ENOSPC;
  4911. +
  4912. + result = yaffs_update_oh(obj, NULL, 0, 0, 0, &xmod);
  4913. +
  4914. + if (result > 0)
  4915. + return xmod.result;
  4916. + else
  4917. + return -ENOSPC;
  4918. +}
  4919. +
  4920. +static int yaffs_apply_xattrib_mod(struct yaffs_obj *obj, char *buffer,
  4921. + struct yaffs_xattr_mod *xmod)
  4922. +{
  4923. + int retval = 0;
  4924. + int x_offs = sizeof(struct yaffs_obj_hdr);
  4925. + struct yaffs_dev *dev = obj->my_dev;
  4926. + int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
  4927. + char *x_buffer = buffer + x_offs;
  4928. +
  4929. + if (xmod->set)
  4930. + retval =
  4931. + nval_set(x_buffer, x_size, xmod->name, xmod->data,
  4932. + xmod->size, xmod->flags);
  4933. + else
  4934. + retval = nval_del(x_buffer, x_size, xmod->name);
  4935. +
  4936. + obj->has_xattr = nval_hasvalues(x_buffer, x_size);
  4937. + obj->xattr_known = 1;
  4938. + xmod->result = retval;
  4939. +
  4940. + return retval;
  4941. +}
  4942. +
  4943. +static int yaffs_do_xattrib_fetch(struct yaffs_obj *obj, const YCHAR *name,
  4944. + void *value, int size)
  4945. +{
  4946. + char *buffer = NULL;
  4947. + int result;
  4948. + struct yaffs_ext_tags tags;
  4949. + struct yaffs_dev *dev = obj->my_dev;
  4950. + int x_offs = sizeof(struct yaffs_obj_hdr);
  4951. + int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
  4952. + char *x_buffer;
  4953. + int retval = 0;
  4954. +
  4955. + if (obj->hdr_chunk < 1)
  4956. + return -ENODATA;
  4957. +
  4958. + /* If we know that the object has no xattribs then don't do all the
  4959. + * reading and parsing.
  4960. + */
  4961. + if (obj->xattr_known && !obj->has_xattr) {
  4962. + if (name)
  4963. + return -ENODATA;
  4964. + else
  4965. + return 0;
  4966. + }
  4967. +
  4968. + buffer = (char *)yaffs_get_temp_buffer(dev);
  4969. + if (!buffer)
  4970. + return -ENOMEM;
  4971. +
  4972. + result =
  4973. + yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, (u8 *) buffer, &tags);
  4974. +
  4975. + if (result != YAFFS_OK)
  4976. + retval = -ENOENT;
  4977. + else {
  4978. + x_buffer = buffer + x_offs;
  4979. +
  4980. + if (!obj->xattr_known) {
  4981. + obj->has_xattr = nval_hasvalues(x_buffer, x_size);
  4982. + obj->xattr_known = 1;
  4983. + }
  4984. +
  4985. + if (name)
  4986. + retval = nval_get(x_buffer, x_size, name, value, size);
  4987. + else
  4988. + retval = nval_list(x_buffer, x_size, value, size);
  4989. + }
  4990. + yaffs_release_temp_buffer(dev, (u8 *) buffer);
  4991. + return retval;
  4992. +}
  4993. +
  4994. +int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR * name,
  4995. + const void *value, int size, int flags)
  4996. +{
  4997. + return yaffs_do_xattrib_mod(obj, 1, name, value, size, flags);
  4998. +}
  4999. +
  5000. +int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR * name)
  5001. +{
  5002. + return yaffs_do_xattrib_mod(obj, 0, name, NULL, 0, 0);
  5003. +}
  5004. +
  5005. +int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR * name, void *value,
  5006. + int size)
  5007. +{
  5008. + return yaffs_do_xattrib_fetch(obj, name, value, size);
  5009. +}
  5010. +
  5011. +int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size)
  5012. +{
  5013. + return yaffs_do_xattrib_fetch(obj, NULL, buffer, size);
  5014. +}
  5015. +
  5016. +static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
  5017. +{
  5018. + u8 *buf;
  5019. + struct yaffs_obj_hdr *oh;
  5020. + struct yaffs_dev *dev;
  5021. + struct yaffs_ext_tags tags;
  5022. + int result;
  5023. + int alloc_failed = 0;
  5024. +
  5025. + if (!in || !in->lazy_loaded || in->hdr_chunk < 1)
  5026. + return;
  5027. +
  5028. + dev = in->my_dev;
  5029. + in->lazy_loaded = 0;
  5030. + buf = yaffs_get_temp_buffer(dev);
  5031. +
  5032. + result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
  5033. + oh = (struct yaffs_obj_hdr *)buf;
  5034. +
  5035. + in->yst_mode = oh->yst_mode;
  5036. + yaffs_load_attribs(in, oh);
  5037. + yaffs_set_obj_name_from_oh(in, oh);
  5038. +
  5039. + if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
  5040. + in->variant.symlink_variant.alias =
  5041. + yaffs_clone_str(oh->alias);
  5042. + if (!in->variant.symlink_variant.alias)
  5043. + alloc_failed = 1; /* Not returned */
  5044. + }
  5045. + yaffs_release_temp_buffer(dev, buf);
  5046. +}
  5047. +
  5048. +/* UpdateObjectHeader updates the header on NAND for an object.
  5049. + * If name is not NULL, then that new name is used.
  5050. + */
  5051. +int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
  5052. + int is_shrink, int shadows, struct yaffs_xattr_mod *xmod)
  5053. +{
  5054. +
  5055. + struct yaffs_block_info *bi;
  5056. + struct yaffs_dev *dev = in->my_dev;
  5057. + int prev_chunk_id;
  5058. + int ret_val = 0;
  5059. + int result = 0;
  5060. + int new_chunk_id;
  5061. + struct yaffs_ext_tags new_tags;
  5062. + struct yaffs_ext_tags old_tags;
  5063. + const YCHAR *alias = NULL;
  5064. + u8 *buffer = NULL;
  5065. + YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1];
  5066. + struct yaffs_obj_hdr *oh = NULL;
  5067. + loff_t file_size = 0;
  5068. +
  5069. + strcpy(old_name, _Y("silly old name"));
  5070. +
  5071. + if (in->fake && in != dev->root_dir && !force && !xmod)
  5072. + return ret_val;
  5073. +
  5074. + yaffs_check_gc(dev, 0);
  5075. + yaffs_check_obj_details_loaded(in);
  5076. +
  5077. + buffer = yaffs_get_temp_buffer(in->my_dev);
  5078. + oh = (struct yaffs_obj_hdr *)buffer;
  5079. +
  5080. + prev_chunk_id = in->hdr_chunk;
  5081. +
  5082. + if (prev_chunk_id > 0) {
  5083. + result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,
  5084. + buffer, &old_tags);
  5085. +
  5086. + yaffs_verify_oh(in, oh, &old_tags, 0);
  5087. + memcpy(old_name, oh->name, sizeof(oh->name));
  5088. + memset(buffer, 0xff, sizeof(struct yaffs_obj_hdr));
  5089. + } else {
  5090. + memset(buffer, 0xff, dev->data_bytes_per_chunk);
  5091. + }
  5092. +
  5093. + oh->type = in->variant_type;
  5094. + oh->yst_mode = in->yst_mode;
  5095. + oh->shadows_obj = oh->inband_shadowed_obj_id = shadows;
  5096. +
  5097. + yaffs_load_attribs_oh(oh, in);
  5098. +
  5099. + if (in->parent)
  5100. + oh->parent_obj_id = in->parent->obj_id;
  5101. + else
  5102. + oh->parent_obj_id = 0;
  5103. +
  5104. + if (name && *name) {
  5105. + memset(oh->name, 0, sizeof(oh->name));
  5106. + yaffs_load_oh_from_name(dev, oh->name, name);
  5107. + } else if (prev_chunk_id > 0) {
  5108. + memcpy(oh->name, old_name, sizeof(oh->name));
  5109. + } else {
  5110. + memset(oh->name, 0, sizeof(oh->name));
  5111. + }
  5112. +
  5113. + oh->is_shrink = is_shrink;
  5114. +
  5115. + switch (in->variant_type) {
  5116. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  5117. + /* Should not happen */
  5118. + break;
  5119. + case YAFFS_OBJECT_TYPE_FILE:
  5120. + if (oh->parent_obj_id != YAFFS_OBJECTID_DELETED &&
  5121. + oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED)
  5122. + file_size = in->variant.file_variant.file_size;
  5123. + yaffs_oh_size_load(oh, file_size);
  5124. + break;
  5125. + case YAFFS_OBJECT_TYPE_HARDLINK:
  5126. + oh->equiv_id = in->variant.hardlink_variant.equiv_id;
  5127. + break;
  5128. + case YAFFS_OBJECT_TYPE_SPECIAL:
  5129. + /* Do nothing */
  5130. + break;
  5131. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  5132. + /* Do nothing */
  5133. + break;
  5134. + case YAFFS_OBJECT_TYPE_SYMLINK:
  5135. + alias = in->variant.symlink_variant.alias;
  5136. + if (!alias)
  5137. + alias = _Y("no alias");
  5138. + strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH);
  5139. + oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
  5140. + break;
  5141. + }
  5142. +
  5143. + /* process any xattrib modifications */
  5144. + if (xmod)
  5145. + yaffs_apply_xattrib_mod(in, (char *)buffer, xmod);
  5146. +
  5147. + /* Tags */
  5148. + memset(&new_tags, 0, sizeof(new_tags));
  5149. + in->serial++;
  5150. + new_tags.chunk_id = 0;
  5151. + new_tags.obj_id = in->obj_id;
  5152. + new_tags.serial_number = in->serial;
  5153. +
  5154. + /* Add extra info for file header */
  5155. + new_tags.extra_available = 1;
  5156. + new_tags.extra_parent_id = oh->parent_obj_id;
  5157. + new_tags.extra_file_size = file_size;
  5158. + new_tags.extra_is_shrink = oh->is_shrink;
  5159. + new_tags.extra_equiv_id = oh->equiv_id;
  5160. + new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0;
  5161. + new_tags.extra_obj_type = in->variant_type;
  5162. + yaffs_verify_oh(in, oh, &new_tags, 1);
  5163. +
  5164. + /* Create new chunk in NAND */
  5165. + new_chunk_id =
  5166. + yaffs_write_new_chunk(dev, buffer, &new_tags,
  5167. + (prev_chunk_id > 0) ? 1 : 0);
  5168. +
  5169. + if (buffer)
  5170. + yaffs_release_temp_buffer(dev, buffer);
  5171. +
  5172. + if (new_chunk_id < 0)
  5173. + return new_chunk_id;
  5174. +
  5175. + in->hdr_chunk = new_chunk_id;
  5176. +
  5177. + if (prev_chunk_id > 0)
  5178. + yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);
  5179. +
  5180. + if (!yaffs_obj_cache_dirty(in))
  5181. + in->dirty = 0;
  5182. +
  5183. + /* If this was a shrink, then mark the block
  5184. + * that the chunk lives on */
  5185. + if (is_shrink) {
  5186. + bi = yaffs_get_block_info(in->my_dev,
  5187. + new_chunk_id /
  5188. + in->my_dev->param.chunks_per_block);
  5189. + bi->has_shrink_hdr = 1;
  5190. + }
  5191. +
  5192. +
  5193. + return new_chunk_id;
  5194. +}
  5195. +
  5196. +/*--------------------- File read/write ------------------------
  5197. + * Read and write have very similar structures.
  5198. + * In general the read/write has three parts to it
  5199. + * An incomplete chunk to start with (if the read/write is not chunk-aligned)
  5200. + * Some complete chunks
  5201. + * An incomplete chunk to end off with
  5202. + *
  5203. + * Curve-balls: the first chunk might also be the last chunk.
  5204. + */
  5205. +
  5206. +int yaffs_file_rd(struct yaffs_obj *in, u8 * buffer, loff_t offset, int n_bytes)
  5207. +{
  5208. + int chunk;
  5209. + u32 start;
  5210. + int n_copy;
  5211. + int n = n_bytes;
  5212. + int n_done = 0;
  5213. + struct yaffs_cache *cache;
  5214. + struct yaffs_dev *dev;
  5215. +
  5216. + dev = in->my_dev;
  5217. +
  5218. + while (n > 0) {
  5219. + yaffs_addr_to_chunk(dev, offset, &chunk, &start);
  5220. + chunk++;
  5221. +
  5222. + /* OK now check for the curveball where the start and end are in
  5223. + * the same chunk.
  5224. + */
  5225. + if ((start + n) < dev->data_bytes_per_chunk)
  5226. + n_copy = n;
  5227. + else
  5228. + n_copy = dev->data_bytes_per_chunk - start;
  5229. +
  5230. + cache = yaffs_find_chunk_cache(in, chunk);
  5231. +
  5232. + /* If the chunk is already in the cache or it is less than
  5233. + * a whole chunk or we're using inband tags then use the cache
  5234. + * (if there is caching) else bypass the cache.
  5235. + */
  5236. + if (cache || n_copy != dev->data_bytes_per_chunk ||
  5237. + dev->param.inband_tags) {
  5238. + if (dev->param.n_caches > 0) {
  5239. +
  5240. + /* If we can't find the data in the cache,
  5241. + * then load it up. */
  5242. +
  5243. + if (!cache) {
  5244. + cache =
  5245. + yaffs_grab_chunk_cache(in->my_dev);
  5246. + cache->object = in;
  5247. + cache->chunk_id = chunk;
  5248. + cache->dirty = 0;
  5249. + cache->locked = 0;
  5250. + yaffs_rd_data_obj(in, chunk,
  5251. + cache->data);
  5252. + cache->n_bytes = 0;
  5253. + }
  5254. +
  5255. + yaffs_use_cache(dev, cache, 0);
  5256. +
  5257. + cache->locked = 1;
  5258. +
  5259. + memcpy(buffer, &cache->data[start], n_copy);
  5260. +
  5261. + cache->locked = 0;
  5262. + } else {
  5263. + /* Read into the local buffer then copy.. */
  5264. +
  5265. + u8 *local_buffer =
  5266. + yaffs_get_temp_buffer(dev);
  5267. + yaffs_rd_data_obj(in, chunk, local_buffer);
  5268. +
  5269. + memcpy(buffer, &local_buffer[start], n_copy);
  5270. +
  5271. + yaffs_release_temp_buffer(dev, local_buffer);
  5272. + }
  5273. + } else {
  5274. + /* A full chunk. Read directly into the buffer. */
  5275. + yaffs_rd_data_obj(in, chunk, buffer);
  5276. + }
  5277. + n -= n_copy;
  5278. + offset += n_copy;
  5279. + buffer += n_copy;
  5280. + n_done += n_copy;
  5281. + }
  5282. + return n_done;
  5283. +}
  5284. +
  5285. +int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
  5286. + int n_bytes, int write_through)
  5287. +{
  5288. +
  5289. + int chunk;
  5290. + u32 start;
  5291. + int n_copy;
  5292. + int n = n_bytes;
  5293. + int n_done = 0;
  5294. + int n_writeback;
  5295. + loff_t start_write = offset;
  5296. + int chunk_written = 0;
  5297. + u32 n_bytes_read;
  5298. + loff_t chunk_start;
  5299. + struct yaffs_dev *dev;
  5300. +
  5301. + dev = in->my_dev;
  5302. +
  5303. + while (n > 0 && chunk_written >= 0) {
  5304. + yaffs_addr_to_chunk(dev, offset, &chunk, &start);
  5305. +
  5306. + if (((loff_t)chunk) *
  5307. + dev->data_bytes_per_chunk + start != offset ||
  5308. + start >= dev->data_bytes_per_chunk) {
  5309. + yaffs_trace(YAFFS_TRACE_ERROR,
  5310. + "AddrToChunk of offset %lld gives chunk %d start %d",
  5311. + offset, chunk, start);
  5312. + }
  5313. + chunk++; /* File pos to chunk in file offset */
  5314. +
  5315. + /* OK now check for the curveball where the start and end are in
  5316. + * the same chunk.
  5317. + */
  5318. +
  5319. + if ((start + n) < dev->data_bytes_per_chunk) {
  5320. + n_copy = n;
  5321. +
  5322. + /* Now calculate how many bytes to write back....
  5323. + * If we're overwriting and not writing to then end of
  5324. + * file then we need to write back as much as was there
  5325. + * before.
  5326. + */
  5327. +
  5328. + chunk_start = (((loff_t)(chunk - 1)) *
  5329. + dev->data_bytes_per_chunk);
  5330. +
  5331. + if (chunk_start > in->variant.file_variant.file_size)
  5332. + n_bytes_read = 0; /* Past end of file */
  5333. + else
  5334. + n_bytes_read =
  5335. + in->variant.file_variant.file_size -
  5336. + chunk_start;
  5337. +
  5338. + if (n_bytes_read > dev->data_bytes_per_chunk)
  5339. + n_bytes_read = dev->data_bytes_per_chunk;
  5340. +
  5341. + n_writeback =
  5342. + (n_bytes_read >
  5343. + (start + n)) ? n_bytes_read : (start + n);
  5344. +
  5345. + if (n_writeback < 0 ||
  5346. + n_writeback > dev->data_bytes_per_chunk)
  5347. + BUG();
  5348. +
  5349. + } else {
  5350. + n_copy = dev->data_bytes_per_chunk - start;
  5351. + n_writeback = dev->data_bytes_per_chunk;
  5352. + }
  5353. +
  5354. + if (n_copy != dev->data_bytes_per_chunk ||
  5355. + !dev->param.cache_bypass_aligned ||
  5356. + dev->param.inband_tags) {
  5357. + /* An incomplete start or end chunk (or maybe both
  5358. + * start and end chunk), or we're using inband tags,
  5359. + * or we're forcing writes through the cache,
  5360. + * so we want to use the cache buffers.
  5361. + */
  5362. + if (dev->param.n_caches > 0) {
  5363. + struct yaffs_cache *cache;
  5364. +
  5365. + /* If we can't find the data in the cache, then
  5366. + * load the cache */
  5367. + cache = yaffs_find_chunk_cache(in, chunk);
  5368. +
  5369. + if (!cache &&
  5370. + yaffs_check_alloc_available(dev, 1)) {
  5371. + cache = yaffs_grab_chunk_cache(dev);
  5372. + cache->object = in;
  5373. + cache->chunk_id = chunk;
  5374. + cache->dirty = 0;
  5375. + cache->locked = 0;
  5376. + yaffs_rd_data_obj(in, chunk,
  5377. + cache->data);
  5378. + } else if (cache &&
  5379. + !cache->dirty &&
  5380. + !yaffs_check_alloc_available(dev,
  5381. + 1)) {
  5382. + /* Drop the cache if it was a read cache
  5383. + * item and no space check has been made
  5384. + * for it.
  5385. + */
  5386. + cache = NULL;
  5387. + }
  5388. +
  5389. + if (cache) {
  5390. + yaffs_use_cache(dev, cache, 1);
  5391. + cache->locked = 1;
  5392. +
  5393. + memcpy(&cache->data[start], buffer,
  5394. + n_copy);
  5395. +
  5396. + cache->locked = 0;
  5397. + cache->n_bytes = n_writeback;
  5398. +
  5399. + if (write_through) {
  5400. + chunk_written =
  5401. + yaffs_wr_data_obj
  5402. + (cache->object,
  5403. + cache->chunk_id,
  5404. + cache->data,
  5405. + cache->n_bytes, 1);
  5406. + cache->dirty = 0;
  5407. + }
  5408. + } else {
  5409. + chunk_written = -1; /* fail write */
  5410. + }
  5411. + } else {
  5412. + /* An incomplete start or end chunk (or maybe
  5413. + * both start and end chunk). Read into the
  5414. + * local buffer then copy over and write back.
  5415. + */
  5416. +
  5417. + u8 *local_buffer = yaffs_get_temp_buffer(dev);
  5418. +
  5419. + yaffs_rd_data_obj(in, chunk, local_buffer);
  5420. + memcpy(&local_buffer[start], buffer, n_copy);
  5421. +
  5422. + chunk_written =
  5423. + yaffs_wr_data_obj(in, chunk,
  5424. + local_buffer,
  5425. + n_writeback, 0);
  5426. +
  5427. + yaffs_release_temp_buffer(dev, local_buffer);
  5428. + }
  5429. + } else {
  5430. + /* A full chunk. Write directly from the buffer. */
  5431. +
  5432. + chunk_written =
  5433. + yaffs_wr_data_obj(in, chunk, buffer,
  5434. + dev->data_bytes_per_chunk, 0);
  5435. +
  5436. + /* Since we've overwritten the cached data,
  5437. + * we better invalidate it. */
  5438. + yaffs_invalidate_chunk_cache(in, chunk);
  5439. + }
  5440. +
  5441. + if (chunk_written >= 0) {
  5442. + n -= n_copy;
  5443. + offset += n_copy;
  5444. + buffer += n_copy;
  5445. + n_done += n_copy;
  5446. + }
  5447. + }
  5448. +
  5449. + /* Update file object */
  5450. +
  5451. + if ((start_write + n_done) > in->variant.file_variant.file_size)
  5452. + in->variant.file_variant.file_size = (start_write + n_done);
  5453. +
  5454. + in->dirty = 1;
  5455. + return n_done;
  5456. +}
  5457. +
  5458. +int yaffs_wr_file(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
  5459. + int n_bytes, int write_through)
  5460. +{
  5461. + yaffs2_handle_hole(in, offset);
  5462. + return yaffs_do_file_wr(in, buffer, offset, n_bytes, write_through);
  5463. +}
  5464. +
  5465. +/* ---------------------- File resizing stuff ------------------ */
  5466. +
  5467. +static void yaffs_prune_chunks(struct yaffs_obj *in, loff_t new_size)
  5468. +{
  5469. +
  5470. + struct yaffs_dev *dev = in->my_dev;
  5471. + loff_t old_size = in->variant.file_variant.file_size;
  5472. + int i;
  5473. + int chunk_id;
  5474. + u32 dummy;
  5475. + int last_del;
  5476. + int start_del;
  5477. +
  5478. + if (old_size > 0)
  5479. + yaffs_addr_to_chunk(dev, old_size - 1, &last_del, &dummy);
  5480. + else
  5481. + last_del = 0;
  5482. +
  5483. + yaffs_addr_to_chunk(dev, new_size + dev->data_bytes_per_chunk - 1,
  5484. + &start_del, &dummy);
  5485. + last_del++;
  5486. + start_del++;
  5487. +
  5488. + /* Delete backwards so that we don't end up with holes if
  5489. + * power is lost part-way through the operation.
  5490. + */
  5491. + for (i = last_del; i >= start_del; i--) {
  5492. + /* NB this could be optimised somewhat,
  5493. + * eg. could retrieve the tags and write them without
  5494. + * using yaffs_chunk_del
  5495. + */
  5496. +
  5497. + chunk_id = yaffs_find_del_file_chunk(in, i, NULL);
  5498. +
  5499. + if (chunk_id < 1)
  5500. + continue;
  5501. +
  5502. + if (chunk_id <
  5503. + (dev->internal_start_block * dev->param.chunks_per_block) ||
  5504. + chunk_id >=
  5505. + ((dev->internal_end_block + 1) *
  5506. + dev->param.chunks_per_block)) {
  5507. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  5508. + "Found daft chunk_id %d for %d",
  5509. + chunk_id, i);
  5510. + } else {
  5511. + in->n_data_chunks--;
  5512. + yaffs_chunk_del(dev, chunk_id, 1, __LINE__);
  5513. + }
  5514. + }
  5515. +}
  5516. +
  5517. +void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size)
  5518. +{
  5519. + int new_full;
  5520. + u32 new_partial;
  5521. + struct yaffs_dev *dev = obj->my_dev;
  5522. +
  5523. + yaffs_addr_to_chunk(dev, new_size, &new_full, &new_partial);
  5524. +
  5525. + yaffs_prune_chunks(obj, new_size);
  5526. +
  5527. + if (new_partial != 0) {
  5528. + int last_chunk = 1 + new_full;
  5529. + u8 *local_buffer = yaffs_get_temp_buffer(dev);
  5530. +
  5531. + /* Rewrite the last chunk with its new size and zero pad */
  5532. + yaffs_rd_data_obj(obj, last_chunk, local_buffer);
  5533. + memset(local_buffer + new_partial, 0,
  5534. + dev->data_bytes_per_chunk - new_partial);
  5535. +
  5536. + yaffs_wr_data_obj(obj, last_chunk, local_buffer,
  5537. + new_partial, 1);
  5538. +
  5539. + yaffs_release_temp_buffer(dev, local_buffer);
  5540. + }
  5541. +
  5542. + obj->variant.file_variant.file_size = new_size;
  5543. +
  5544. + yaffs_prune_tree(dev, &obj->variant.file_variant);
  5545. +}
  5546. +
  5547. +int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
  5548. +{
  5549. + struct yaffs_dev *dev = in->my_dev;
  5550. + loff_t old_size = in->variant.file_variant.file_size;
  5551. +
  5552. + yaffs_flush_file_cache(in, 1);
  5553. + yaffs_invalidate_whole_cache(in);
  5554. +
  5555. + yaffs_check_gc(dev, 0);
  5556. +
  5557. + if (in->variant_type != YAFFS_OBJECT_TYPE_FILE)
  5558. + return YAFFS_FAIL;
  5559. +
  5560. + if (new_size == old_size)
  5561. + return YAFFS_OK;
  5562. +
  5563. + if (new_size > old_size) {
  5564. + yaffs2_handle_hole(in, new_size);
  5565. + in->variant.file_variant.file_size = new_size;
  5566. + } else {
  5567. + /* new_size < old_size */
  5568. + yaffs_resize_file_down(in, new_size);
  5569. + }
  5570. +
  5571. + /* Write a new object header to reflect the resize.
  5572. + * show we've shrunk the file, if need be
  5573. + * Do this only if the file is not in the deleted directories
  5574. + * and is not shadowed.
  5575. + */
  5576. + if (in->parent &&
  5577. + !in->is_shadowed &&
  5578. + in->parent->obj_id != YAFFS_OBJECTID_UNLINKED &&
  5579. + in->parent->obj_id != YAFFS_OBJECTID_DELETED)
  5580. + yaffs_update_oh(in, NULL, 0, 0, 0, NULL);
  5581. +
  5582. + return YAFFS_OK;
  5583. +}
  5584. +
  5585. +int yaffs_flush_file(struct yaffs_obj *in,
  5586. + int update_time,
  5587. + int data_sync,
  5588. + int discard_cache)
  5589. +{
  5590. + if (!in->dirty)
  5591. + return YAFFS_OK;
  5592. +
  5593. + yaffs_flush_file_cache(in, discard_cache);
  5594. +
  5595. + if (data_sync)
  5596. + return YAFFS_OK;
  5597. +
  5598. + if (update_time)
  5599. + yaffs_load_current_time(in, 0, 0);
  5600. +
  5601. + return (yaffs_update_oh(in, NULL, 0, 0, 0, NULL) >= 0) ?
  5602. + YAFFS_OK : YAFFS_FAIL;
  5603. +}
  5604. +
  5605. +
  5606. +/* yaffs_del_file deletes the whole file data
  5607. + * and the inode associated with the file.
  5608. + * It does not delete the links associated with the file.
  5609. + */
  5610. +static int yaffs_unlink_file_if_needed(struct yaffs_obj *in)
  5611. +{
  5612. + int ret_val;
  5613. + int del_now = 0;
  5614. + struct yaffs_dev *dev = in->my_dev;
  5615. +
  5616. + if (!in->my_inode)
  5617. + del_now = 1;
  5618. +
  5619. + if (del_now) {
  5620. + ret_val =
  5621. + yaffs_change_obj_name(in, in->my_dev->del_dir,
  5622. + _Y("deleted"), 0, 0);
  5623. + yaffs_trace(YAFFS_TRACE_TRACING,
  5624. + "yaffs: immediate deletion of file %d",
  5625. + in->obj_id);
  5626. + in->deleted = 1;
  5627. + in->my_dev->n_deleted_files++;
  5628. + if (dev->param.disable_soft_del || dev->param.is_yaffs2)
  5629. + yaffs_resize_file(in, 0);
  5630. + yaffs_soft_del_file(in);
  5631. + } else {
  5632. + ret_val =
  5633. + yaffs_change_obj_name(in, in->my_dev->unlinked_dir,
  5634. + _Y("unlinked"), 0, 0);
  5635. + }
  5636. + return ret_val;
  5637. +}
  5638. +
  5639. +static int yaffs_del_file(struct yaffs_obj *in)
  5640. +{
  5641. + int ret_val = YAFFS_OK;
  5642. + int deleted; /* Need to cache value on stack if in is freed */
  5643. + struct yaffs_dev *dev = in->my_dev;
  5644. +
  5645. + if (dev->param.disable_soft_del || dev->param.is_yaffs2)
  5646. + yaffs_resize_file(in, 0);
  5647. +
  5648. + if (in->n_data_chunks > 0) {
  5649. + /* Use soft deletion if there is data in the file.
  5650. + * That won't be the case if it has been resized to zero.
  5651. + */
  5652. + if (!in->unlinked)
  5653. + ret_val = yaffs_unlink_file_if_needed(in);
  5654. +
  5655. + deleted = in->deleted;
  5656. +
  5657. + if (ret_val == YAFFS_OK && in->unlinked && !in->deleted) {
  5658. + in->deleted = 1;
  5659. + deleted = 1;
  5660. + in->my_dev->n_deleted_files++;
  5661. + yaffs_soft_del_file(in);
  5662. + }
  5663. + return deleted ? YAFFS_OK : YAFFS_FAIL;
  5664. + } else {
  5665. + /* The file has no data chunks so we toss it immediately */
  5666. + yaffs_free_tnode(in->my_dev, in->variant.file_variant.top);
  5667. + in->variant.file_variant.top = NULL;
  5668. + yaffs_generic_obj_del(in);
  5669. +
  5670. + return YAFFS_OK;
  5671. + }
  5672. +}
  5673. +
  5674. +int yaffs_is_non_empty_dir(struct yaffs_obj *obj)
  5675. +{
  5676. + return (obj &&
  5677. + obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) &&
  5678. + !(list_empty(&obj->variant.dir_variant.children));
  5679. +}
  5680. +
  5681. +static int yaffs_del_dir(struct yaffs_obj *obj)
  5682. +{
  5683. + /* First check that the directory is empty. */
  5684. + if (yaffs_is_non_empty_dir(obj))
  5685. + return YAFFS_FAIL;
  5686. +
  5687. + return yaffs_generic_obj_del(obj);
  5688. +}
  5689. +
  5690. +static int yaffs_del_symlink(struct yaffs_obj *in)
  5691. +{
  5692. + kfree(in->variant.symlink_variant.alias);
  5693. + in->variant.symlink_variant.alias = NULL;
  5694. +
  5695. + return yaffs_generic_obj_del(in);
  5696. +}
  5697. +
  5698. +static int yaffs_del_link(struct yaffs_obj *in)
  5699. +{
  5700. + /* remove this hardlink from the list associated with the equivalent
  5701. + * object
  5702. + */
  5703. + list_del_init(&in->hard_links);
  5704. + return yaffs_generic_obj_del(in);
  5705. +}
  5706. +
  5707. +int yaffs_del_obj(struct yaffs_obj *obj)
  5708. +{
  5709. + int ret_val = -1;
  5710. +
  5711. + switch (obj->variant_type) {
  5712. + case YAFFS_OBJECT_TYPE_FILE:
  5713. + ret_val = yaffs_del_file(obj);
  5714. + break;
  5715. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  5716. + if (!list_empty(&obj->variant.dir_variant.dirty)) {
  5717. + yaffs_trace(YAFFS_TRACE_BACKGROUND,
  5718. + "Remove object %d from dirty directories",
  5719. + obj->obj_id);
  5720. + list_del_init(&obj->variant.dir_variant.dirty);
  5721. + }
  5722. + return yaffs_del_dir(obj);
  5723. + break;
  5724. + case YAFFS_OBJECT_TYPE_SYMLINK:
  5725. + ret_val = yaffs_del_symlink(obj);
  5726. + break;
  5727. + case YAFFS_OBJECT_TYPE_HARDLINK:
  5728. + ret_val = yaffs_del_link(obj);
  5729. + break;
  5730. + case YAFFS_OBJECT_TYPE_SPECIAL:
  5731. + ret_val = yaffs_generic_obj_del(obj);
  5732. + break;
  5733. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  5734. + ret_val = 0;
  5735. + break; /* should not happen. */
  5736. + }
  5737. + return ret_val;
  5738. +}
  5739. +
  5740. +
  5741. +static void yaffs_empty_dir_to_dir(struct yaffs_obj *from_dir,
  5742. + struct yaffs_obj *to_dir)
  5743. +{
  5744. + struct yaffs_obj *obj;
  5745. + struct list_head *lh;
  5746. + struct list_head *n;
  5747. +
  5748. + list_for_each_safe(lh, n, &from_dir->variant.dir_variant.children) {
  5749. + obj = list_entry(lh, struct yaffs_obj, siblings);
  5750. + yaffs_add_obj_to_dir(to_dir, obj);
  5751. + }
  5752. +}
  5753. +
  5754. +struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
  5755. + enum yaffs_obj_type type)
  5756. +{
  5757. + /* Tear down the old variant */
  5758. + switch (obj->variant_type) {
  5759. + case YAFFS_OBJECT_TYPE_FILE:
  5760. + /* Nuke file data */
  5761. + yaffs_resize_file(obj, 0);
  5762. + yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
  5763. + obj->variant.file_variant.top = NULL;
  5764. + break;
  5765. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  5766. + /* Put the children in lost and found. */
  5767. + yaffs_empty_dir_to_dir(obj, obj->my_dev->lost_n_found);
  5768. + if (!list_empty(&obj->variant.dir_variant.dirty))
  5769. + list_del_init(&obj->variant.dir_variant.dirty);
  5770. + break;
  5771. + case YAFFS_OBJECT_TYPE_SYMLINK:
  5772. + /* Nuke symplink data */
  5773. + kfree(obj->variant.symlink_variant.alias);
  5774. + obj->variant.symlink_variant.alias = NULL;
  5775. + break;
  5776. + case YAFFS_OBJECT_TYPE_HARDLINK:
  5777. + list_del_init(&obj->hard_links);
  5778. + break;
  5779. + default:
  5780. + break;
  5781. + }
  5782. +
  5783. + memset(&obj->variant, 0, sizeof(obj->variant));
  5784. +
  5785. + /*Set up new variant if the memset is not enough. */
  5786. + switch (type) {
  5787. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  5788. + INIT_LIST_HEAD(&obj->variant.dir_variant.children);
  5789. + INIT_LIST_HEAD(&obj->variant.dir_variant.dirty);
  5790. + break;
  5791. + case YAFFS_OBJECT_TYPE_FILE:
  5792. + case YAFFS_OBJECT_TYPE_SYMLINK:
  5793. + case YAFFS_OBJECT_TYPE_HARDLINK:
  5794. + default:
  5795. + break;
  5796. + }
  5797. +
  5798. + obj->variant_type = type;
  5799. +
  5800. + return obj;
  5801. +
  5802. +}
  5803. +
  5804. +static int yaffs_unlink_worker(struct yaffs_obj *obj)
  5805. +{
  5806. + int del_now = 0;
  5807. +
  5808. + if (!obj)
  5809. + return YAFFS_FAIL;
  5810. +
  5811. + if (!obj->my_inode)
  5812. + del_now = 1;
  5813. +
  5814. + yaffs_update_parent(obj->parent);
  5815. +
  5816. + if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
  5817. + return yaffs_del_link(obj);
  5818. + } else if (!list_empty(&obj->hard_links)) {
  5819. + /* Curve ball: We're unlinking an object that has a hardlink.
  5820. + *
  5821. + * This problem arises because we are not strictly following
  5822. + * The Linux link/inode model.
  5823. + *
  5824. + * We can't really delete the object.
  5825. + * Instead, we do the following:
  5826. + * - Select a hardlink.
  5827. + * - Unhook it from the hard links
  5828. + * - Move it from its parent directory so that the rename works.
  5829. + * - Rename the object to the hardlink's name.
  5830. + * - Delete the hardlink
  5831. + */
  5832. +
  5833. + struct yaffs_obj *hl;
  5834. + struct yaffs_obj *parent;
  5835. + int ret_val;
  5836. + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
  5837. +
  5838. + hl = list_entry(obj->hard_links.next, struct yaffs_obj,
  5839. + hard_links);
  5840. +
  5841. + yaffs_get_obj_name(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
  5842. + parent = hl->parent;
  5843. +
  5844. + list_del_init(&hl->hard_links);
  5845. +
  5846. + yaffs_add_obj_to_dir(obj->my_dev->unlinked_dir, hl);
  5847. +
  5848. + ret_val = yaffs_change_obj_name(obj, parent, name, 0, 0);
  5849. +
  5850. + if (ret_val == YAFFS_OK)
  5851. + ret_val = yaffs_generic_obj_del(hl);
  5852. +
  5853. + return ret_val;
  5854. +
  5855. + } else if (del_now) {
  5856. + switch (obj->variant_type) {
  5857. + case YAFFS_OBJECT_TYPE_FILE:
  5858. + return yaffs_del_file(obj);
  5859. + break;
  5860. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  5861. + list_del_init(&obj->variant.dir_variant.dirty);
  5862. + return yaffs_del_dir(obj);
  5863. + break;
  5864. + case YAFFS_OBJECT_TYPE_SYMLINK:
  5865. + return yaffs_del_symlink(obj);
  5866. + break;
  5867. + case YAFFS_OBJECT_TYPE_SPECIAL:
  5868. + return yaffs_generic_obj_del(obj);
  5869. + break;
  5870. + case YAFFS_OBJECT_TYPE_HARDLINK:
  5871. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  5872. + default:
  5873. + return YAFFS_FAIL;
  5874. + }
  5875. + } else if (yaffs_is_non_empty_dir(obj)) {
  5876. + return YAFFS_FAIL;
  5877. + } else {
  5878. + return yaffs_change_obj_name(obj, obj->my_dev->unlinked_dir,
  5879. + _Y("unlinked"), 0, 0);
  5880. + }
  5881. +}
  5882. +
  5883. +static int yaffs_unlink_obj(struct yaffs_obj *obj)
  5884. +{
  5885. + if (obj && obj->unlink_allowed)
  5886. + return yaffs_unlink_worker(obj);
  5887. +
  5888. + return YAFFS_FAIL;
  5889. +}
  5890. +
  5891. +int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR *name)
  5892. +{
  5893. + struct yaffs_obj *obj;
  5894. +
  5895. + obj = yaffs_find_by_name(dir, name);
  5896. + return yaffs_unlink_obj(obj);
  5897. +}
  5898. +
  5899. +/* Note:
  5900. + * If old_name is NULL then we take old_dir as the object to be renamed.
  5901. + */
  5902. +int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR *old_name,
  5903. + struct yaffs_obj *new_dir, const YCHAR *new_name)
  5904. +{
  5905. + struct yaffs_obj *obj = NULL;
  5906. + struct yaffs_obj *existing_target = NULL;
  5907. + int force = 0;
  5908. + int result;
  5909. + struct yaffs_dev *dev;
  5910. +
  5911. + if (!old_dir || old_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  5912. + BUG();
  5913. + return YAFFS_FAIL;
  5914. + }
  5915. + if (!new_dir || new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  5916. + BUG();
  5917. + return YAFFS_FAIL;
  5918. + }
  5919. +
  5920. + dev = old_dir->my_dev;
  5921. +
  5922. +#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
  5923. + /* Special case for case insemsitive systems.
  5924. + * While look-up is case insensitive, the name isn't.
  5925. + * Therefore we might want to change x.txt to X.txt
  5926. + */
  5927. + if (old_dir == new_dir &&
  5928. + old_name && new_name &&
  5929. + strcmp(old_name, new_name) == 0)
  5930. + force = 1;
  5931. +#endif
  5932. +
  5933. + if (strnlen(new_name, YAFFS_MAX_NAME_LENGTH + 1) >
  5934. + YAFFS_MAX_NAME_LENGTH)
  5935. + /* ENAMETOOLONG */
  5936. + return YAFFS_FAIL;
  5937. +
  5938. + if (old_name)
  5939. + obj = yaffs_find_by_name(old_dir, old_name);
  5940. + else{
  5941. + obj = old_dir;
  5942. + old_dir = obj->parent;
  5943. + }
  5944. +
  5945. + if (obj && obj->rename_allowed) {
  5946. + /* Now handle an existing target, if there is one */
  5947. + existing_target = yaffs_find_by_name(new_dir, new_name);
  5948. + if (yaffs_is_non_empty_dir(existing_target)) {
  5949. + return YAFFS_FAIL; /* ENOTEMPTY */
  5950. + } else if (existing_target && existing_target != obj) {
  5951. + /* Nuke the target first, using shadowing,
  5952. + * but only if it isn't the same object.
  5953. + *
  5954. + * Note we must disable gc here otherwise it can mess
  5955. + * up the shadowing.
  5956. + *
  5957. + */
  5958. + dev->gc_disable = 1;
  5959. + yaffs_change_obj_name(obj, new_dir, new_name, force,
  5960. + existing_target->obj_id);
  5961. + existing_target->is_shadowed = 1;
  5962. + yaffs_unlink_obj(existing_target);
  5963. + dev->gc_disable = 0;
  5964. + }
  5965. +
  5966. + result = yaffs_change_obj_name(obj, new_dir, new_name, 1, 0);
  5967. +
  5968. + yaffs_update_parent(old_dir);
  5969. + if (new_dir != old_dir)
  5970. + yaffs_update_parent(new_dir);
  5971. +
  5972. + return result;
  5973. + }
  5974. + return YAFFS_FAIL;
  5975. +}
  5976. +
  5977. +/*----------------------- Initialisation Scanning ---------------------- */
  5978. +
  5979. +void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id,
  5980. + int backward_scanning)
  5981. +{
  5982. + struct yaffs_obj *obj;
  5983. +
  5984. + if (backward_scanning) {
  5985. + /* Handle YAFFS2 case (backward scanning)
  5986. + * If the shadowed object exists then ignore.
  5987. + */
  5988. + obj = yaffs_find_by_number(dev, obj_id);
  5989. + if (obj)
  5990. + return;
  5991. + }
  5992. +
  5993. + /* Let's create it (if it does not exist) assuming it is a file so that
  5994. + * it can do shrinking etc.
  5995. + * We put it in unlinked dir to be cleaned up after the scanning
  5996. + */
  5997. + obj =
  5998. + yaffs_find_or_create_by_number(dev, obj_id, YAFFS_OBJECT_TYPE_FILE);
  5999. + if (!obj)
  6000. + return;
  6001. + obj->is_shadowed = 1;
  6002. + yaffs_add_obj_to_dir(dev->unlinked_dir, obj);
  6003. + obj->variant.file_variant.shrink_size = 0;
  6004. + obj->valid = 1; /* So that we don't read any other info. */
  6005. +}
  6006. +
  6007. +void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list)
  6008. +{
  6009. + struct list_head *lh;
  6010. + struct list_head *save;
  6011. + struct yaffs_obj *hl;
  6012. + struct yaffs_obj *in;
  6013. +
  6014. + list_for_each_safe(lh, save, hard_list) {
  6015. + hl = list_entry(lh, struct yaffs_obj, hard_links);
  6016. + in = yaffs_find_by_number(dev,
  6017. + hl->variant.hardlink_variant.equiv_id);
  6018. +
  6019. + if (in) {
  6020. + /* Add the hardlink pointers */
  6021. + hl->variant.hardlink_variant.equiv_obj = in;
  6022. + list_add(&hl->hard_links, &in->hard_links);
  6023. + } else {
  6024. + /* Todo Need to report/handle this better.
  6025. + * Got a problem... hardlink to a non-existant object
  6026. + */
  6027. + hl->variant.hardlink_variant.equiv_obj = NULL;
  6028. + INIT_LIST_HEAD(&hl->hard_links);
  6029. + }
  6030. + }
  6031. +}
  6032. +
  6033. +static void yaffs_strip_deleted_objs(struct yaffs_dev *dev)
  6034. +{
  6035. + /*
  6036. + * Sort out state of unlinked and deleted objects after scanning.
  6037. + */
  6038. + struct list_head *i;
  6039. + struct list_head *n;
  6040. + struct yaffs_obj *l;
  6041. +
  6042. + if (dev->read_only)
  6043. + return;
  6044. +
  6045. + /* Soft delete all the unlinked files */
  6046. + list_for_each_safe(i, n,
  6047. + &dev->unlinked_dir->variant.dir_variant.children) {
  6048. + l = list_entry(i, struct yaffs_obj, siblings);
  6049. + yaffs_del_obj(l);
  6050. + }
  6051. +
  6052. + list_for_each_safe(i, n, &dev->del_dir->variant.dir_variant.children) {
  6053. + l = list_entry(i, struct yaffs_obj, siblings);
  6054. + yaffs_del_obj(l);
  6055. + }
  6056. +}
  6057. +
  6058. +/*
  6059. + * This code iterates through all the objects making sure that they are rooted.
  6060. + * Any unrooted objects are re-rooted in lost+found.
  6061. + * An object needs to be in one of:
  6062. + * - Directly under deleted, unlinked
  6063. + * - Directly or indirectly under root.
  6064. + *
  6065. + * Note:
  6066. + * This code assumes that we don't ever change the current relationships
  6067. + * between directories:
  6068. + * root_dir->parent == unlinked_dir->parent == del_dir->parent == NULL
  6069. + * lost-n-found->parent == root_dir
  6070. + *
  6071. + * This fixes the problem where directories might have inadvertently been
  6072. + * deleted leaving the object "hanging" without being rooted in the
  6073. + * directory tree.
  6074. + */
  6075. +
  6076. +static int yaffs_has_null_parent(struct yaffs_dev *dev, struct yaffs_obj *obj)
  6077. +{
  6078. + return (obj == dev->del_dir ||
  6079. + obj == dev->unlinked_dir || obj == dev->root_dir);
  6080. +}
  6081. +
  6082. +static void yaffs_fix_hanging_objs(struct yaffs_dev *dev)
  6083. +{
  6084. + struct yaffs_obj *obj;
  6085. + struct yaffs_obj *parent;
  6086. + int i;
  6087. + struct list_head *lh;
  6088. + struct list_head *n;
  6089. + int depth_limit;
  6090. + int hanging;
  6091. +
  6092. + if (dev->read_only)
  6093. + return;
  6094. +
  6095. + /* Iterate through the objects in each hash entry,
  6096. + * looking at each object.
  6097. + * Make sure it is rooted.
  6098. + */
  6099. +
  6100. + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
  6101. + list_for_each_safe(lh, n, &dev->obj_bucket[i].list) {
  6102. + obj = list_entry(lh, struct yaffs_obj, hash_link);
  6103. + parent = obj->parent;
  6104. +
  6105. + if (yaffs_has_null_parent(dev, obj)) {
  6106. + /* These directories are not hanging */
  6107. + hanging = 0;
  6108. + } else if (!parent ||
  6109. + parent->variant_type !=
  6110. + YAFFS_OBJECT_TYPE_DIRECTORY) {
  6111. + hanging = 1;
  6112. + } else if (yaffs_has_null_parent(dev, parent)) {
  6113. + hanging = 0;
  6114. + } else {
  6115. + /*
  6116. + * Need to follow the parent chain to
  6117. + * see if it is hanging.
  6118. + */
  6119. + hanging = 0;
  6120. + depth_limit = 100;
  6121. +
  6122. + while (parent != dev->root_dir &&
  6123. + parent->parent &&
  6124. + parent->parent->variant_type ==
  6125. + YAFFS_OBJECT_TYPE_DIRECTORY &&
  6126. + depth_limit > 0) {
  6127. + parent = parent->parent;
  6128. + depth_limit--;
  6129. + }
  6130. + if (parent != dev->root_dir)
  6131. + hanging = 1;
  6132. + }
  6133. + if (hanging) {
  6134. + yaffs_trace(YAFFS_TRACE_SCAN,
  6135. + "Hanging object %d moved to lost and found",
  6136. + obj->obj_id);
  6137. + yaffs_add_obj_to_dir(dev->lost_n_found, obj);
  6138. + }
  6139. + }
  6140. + }
  6141. +}
  6142. +
  6143. +/*
  6144. + * Delete directory contents for cleaning up lost and found.
  6145. + */
  6146. +static void yaffs_del_dir_contents(struct yaffs_obj *dir)
  6147. +{
  6148. + struct yaffs_obj *obj;
  6149. + struct list_head *lh;
  6150. + struct list_head *n;
  6151. +
  6152. + if (dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
  6153. + BUG();
  6154. +
  6155. + list_for_each_safe(lh, n, &dir->variant.dir_variant.children) {
  6156. + obj = list_entry(lh, struct yaffs_obj, siblings);
  6157. + if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
  6158. + yaffs_del_dir_contents(obj);
  6159. + yaffs_trace(YAFFS_TRACE_SCAN,
  6160. + "Deleting lost_found object %d",
  6161. + obj->obj_id);
  6162. + yaffs_unlink_obj(obj);
  6163. + }
  6164. +}
  6165. +
  6166. +static void yaffs_empty_l_n_f(struct yaffs_dev *dev)
  6167. +{
  6168. + yaffs_del_dir_contents(dev->lost_n_found);
  6169. +}
  6170. +
  6171. +
  6172. +struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *directory,
  6173. + const YCHAR *name)
  6174. +{
  6175. + int sum;
  6176. + struct list_head *i;
  6177. + YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
  6178. + struct yaffs_obj *l;
  6179. +
  6180. + if (!name)
  6181. + return NULL;
  6182. +
  6183. + if (!directory) {
  6184. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6185. + "tragedy: yaffs_find_by_name: null pointer directory"
  6186. + );
  6187. + BUG();
  6188. + return NULL;
  6189. + }
  6190. + if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  6191. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6192. + "tragedy: yaffs_find_by_name: non-directory"
  6193. + );
  6194. + BUG();
  6195. + }
  6196. +
  6197. + sum = yaffs_calc_name_sum(name);
  6198. +
  6199. + list_for_each(i, &directory->variant.dir_variant.children) {
  6200. + l = list_entry(i, struct yaffs_obj, siblings);
  6201. +
  6202. + if (l->parent != directory)
  6203. + BUG();
  6204. +
  6205. + yaffs_check_obj_details_loaded(l);
  6206. +
  6207. + /* Special case for lost-n-found */
  6208. + if (l->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
  6209. + if (!strcmp(name, YAFFS_LOSTNFOUND_NAME))
  6210. + return l;
  6211. + } else if (l->sum == sum || l->hdr_chunk <= 0) {
  6212. + /* LostnFound chunk called Objxxx
  6213. + * Do a real check
  6214. + */
  6215. + yaffs_get_obj_name(l, buffer,
  6216. + YAFFS_MAX_NAME_LENGTH + 1);
  6217. + if (!strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH))
  6218. + return l;
  6219. + }
  6220. + }
  6221. + return NULL;
  6222. +}
  6223. +
  6224. +/* GetEquivalentObject dereferences any hard links to get to the
  6225. + * actual object.
  6226. + */
  6227. +
  6228. +struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj)
  6229. +{
  6230. + if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
  6231. + obj = obj->variant.hardlink_variant.equiv_obj;
  6232. + yaffs_check_obj_details_loaded(obj);
  6233. + }
  6234. + return obj;
  6235. +}
  6236. +
  6237. +/*
  6238. + * A note or two on object names.
  6239. + * * If the object name is missing, we then make one up in the form objnnn
  6240. + *
  6241. + * * ASCII names are stored in the object header's name field from byte zero
  6242. + * * Unicode names are historically stored starting from byte zero.
  6243. + *
  6244. + * Then there are automatic Unicode names...
  6245. + * The purpose of these is to save names in a way that can be read as
  6246. + * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII
  6247. + * system to share files.
  6248. + *
  6249. + * These automatic unicode are stored slightly differently...
  6250. + * - If the name can fit in the ASCII character space then they are saved as
  6251. + * ascii names as per above.
  6252. + * - If the name needs Unicode then the name is saved in Unicode
  6253. + * starting at oh->name[1].
  6254. +
  6255. + */
  6256. +static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
  6257. + int buffer_size)
  6258. +{
  6259. + /* Create an object name if we could not find one. */
  6260. + if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0) {
  6261. + YCHAR local_name[20];
  6262. + YCHAR num_string[20];
  6263. + YCHAR *x = &num_string[19];
  6264. + unsigned v = obj->obj_id;
  6265. + num_string[19] = 0;
  6266. + while (v > 0) {
  6267. + x--;
  6268. + *x = '0' + (v % 10);
  6269. + v /= 10;
  6270. + }
  6271. + /* make up a name */
  6272. + strcpy(local_name, YAFFS_LOSTNFOUND_PREFIX);
  6273. + strcat(local_name, x);
  6274. + strncpy(name, local_name, buffer_size - 1);
  6275. + }
  6276. +}
  6277. +
  6278. +int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size)
  6279. +{
  6280. + memset(name, 0, buffer_size * sizeof(YCHAR));
  6281. + yaffs_check_obj_details_loaded(obj);
  6282. + if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
  6283. + strncpy(name, YAFFS_LOSTNFOUND_NAME, buffer_size - 1);
  6284. + } else if (obj->short_name[0]) {
  6285. + strcpy(name, obj->short_name);
  6286. + } else if (obj->hdr_chunk > 0) {
  6287. + int result;
  6288. + u8 *buffer = yaffs_get_temp_buffer(obj->my_dev);
  6289. +
  6290. + struct yaffs_obj_hdr *oh = (struct yaffs_obj_hdr *)buffer;
  6291. +
  6292. + memset(buffer, 0, obj->my_dev->data_bytes_per_chunk);
  6293. +
  6294. + if (obj->hdr_chunk > 0) {
  6295. + result = yaffs_rd_chunk_tags_nand(obj->my_dev,
  6296. + obj->hdr_chunk,
  6297. + buffer, NULL);
  6298. + }
  6299. + yaffs_load_name_from_oh(obj->my_dev, name, oh->name,
  6300. + buffer_size);
  6301. +
  6302. + yaffs_release_temp_buffer(obj->my_dev, buffer);
  6303. + }
  6304. +
  6305. + yaffs_fix_null_name(obj, name, buffer_size);
  6306. +
  6307. + return strnlen(name, YAFFS_MAX_NAME_LENGTH);
  6308. +}
  6309. +
  6310. +loff_t yaffs_get_obj_length(struct yaffs_obj *obj)
  6311. +{
  6312. + /* Dereference any hard linking */
  6313. + obj = yaffs_get_equivalent_obj(obj);
  6314. +
  6315. + if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
  6316. + return obj->variant.file_variant.file_size;
  6317. + if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
  6318. + if (!obj->variant.symlink_variant.alias)
  6319. + return 0;
  6320. + return strnlen(obj->variant.symlink_variant.alias,
  6321. + YAFFS_MAX_ALIAS_LENGTH);
  6322. + } else {
  6323. + /* Only a directory should drop through to here */
  6324. + return obj->my_dev->data_bytes_per_chunk;
  6325. + }
  6326. +}
  6327. +
  6328. +int yaffs_get_obj_link_count(struct yaffs_obj *obj)
  6329. +{
  6330. + int count = 0;
  6331. + struct list_head *i;
  6332. +
  6333. + if (!obj->unlinked)
  6334. + count++; /* the object itself */
  6335. +
  6336. + list_for_each(i, &obj->hard_links)
  6337. + count++; /* add the hard links; */
  6338. +
  6339. + return count;
  6340. +}
  6341. +
  6342. +int yaffs_get_obj_inode(struct yaffs_obj *obj)
  6343. +{
  6344. + obj = yaffs_get_equivalent_obj(obj);
  6345. +
  6346. + return obj->obj_id;
  6347. +}
  6348. +
  6349. +unsigned yaffs_get_obj_type(struct yaffs_obj *obj)
  6350. +{
  6351. + obj = yaffs_get_equivalent_obj(obj);
  6352. +
  6353. + switch (obj->variant_type) {
  6354. + case YAFFS_OBJECT_TYPE_FILE:
  6355. + return DT_REG;
  6356. + break;
  6357. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  6358. + return DT_DIR;
  6359. + break;
  6360. + case YAFFS_OBJECT_TYPE_SYMLINK:
  6361. + return DT_LNK;
  6362. + break;
  6363. + case YAFFS_OBJECT_TYPE_HARDLINK:
  6364. + return DT_REG;
  6365. + break;
  6366. + case YAFFS_OBJECT_TYPE_SPECIAL:
  6367. + if (S_ISFIFO(obj->yst_mode))
  6368. + return DT_FIFO;
  6369. + if (S_ISCHR(obj->yst_mode))
  6370. + return DT_CHR;
  6371. + if (S_ISBLK(obj->yst_mode))
  6372. + return DT_BLK;
  6373. + if (S_ISSOCK(obj->yst_mode))
  6374. + return DT_SOCK;
  6375. + return DT_REG;
  6376. + break;
  6377. + default:
  6378. + return DT_REG;
  6379. + break;
  6380. + }
  6381. +}
  6382. +
  6383. +YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj)
  6384. +{
  6385. + obj = yaffs_get_equivalent_obj(obj);
  6386. + if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK)
  6387. + return yaffs_clone_str(obj->variant.symlink_variant.alias);
  6388. + else
  6389. + return yaffs_clone_str(_Y(""));
  6390. +}
  6391. +
  6392. +/*--------------------------- Initialisation code -------------------------- */
  6393. +
  6394. +static int yaffs_check_dev_fns(struct yaffs_dev *dev)
  6395. +{
  6396. + struct yaffs_driver *drv = &dev->drv;
  6397. + struct yaffs_tags_handler *tagger = &dev->tagger;
  6398. +
  6399. + /* Common functions, gotta have */
  6400. + if (!drv->drv_read_chunk_fn ||
  6401. + !drv->drv_write_chunk_fn ||
  6402. + !drv->drv_erase_fn)
  6403. + return 0;
  6404. +
  6405. + if (dev->param.is_yaffs2 &&
  6406. + (!drv->drv_mark_bad_fn || !drv->drv_check_bad_fn))
  6407. + return 0;
  6408. +
  6409. + /* Install the default tags marshalling functions if needed. */
  6410. + yaffs_tags_compat_install(dev);
  6411. + yaffs_tags_marshall_install(dev);
  6412. +
  6413. + /* Check we now have the marshalling functions required. */
  6414. + if (!tagger->write_chunk_tags_fn ||
  6415. + !tagger->read_chunk_tags_fn ||
  6416. + !tagger->query_block_fn ||
  6417. + !tagger->mark_bad_fn)
  6418. + return 0;
  6419. +
  6420. + return 1;
  6421. +}
  6422. +
  6423. +static int yaffs_create_initial_dir(struct yaffs_dev *dev)
  6424. +{
  6425. + /* Initialise the unlinked, deleted, root and lost+found directories */
  6426. + dev->lost_n_found = dev->root_dir = NULL;
  6427. + dev->unlinked_dir = dev->del_dir = NULL;
  6428. + dev->unlinked_dir =
  6429. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
  6430. + dev->del_dir =
  6431. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
  6432. + dev->root_dir =
  6433. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_ROOT,
  6434. + YAFFS_ROOT_MODE | S_IFDIR);
  6435. + dev->lost_n_found =
  6436. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_LOSTNFOUND,
  6437. + YAFFS_LOSTNFOUND_MODE | S_IFDIR);
  6438. +
  6439. + if (dev->lost_n_found && dev->root_dir && dev->unlinked_dir
  6440. + && dev->del_dir) {
  6441. + yaffs_add_obj_to_dir(dev->root_dir, dev->lost_n_found);
  6442. + return YAFFS_OK;
  6443. + }
  6444. + return YAFFS_FAIL;
  6445. +}
  6446. +
  6447. +/* Low level init.
  6448. + * Typically only used by yaffs_guts_initialise, but also used by the
  6449. + * Low level yaffs driver tests.
  6450. + */
  6451. +
  6452. +int yaffs_guts_ll_init(struct yaffs_dev *dev)
  6453. +{
  6454. +
  6455. +
  6456. + yaffs_trace(YAFFS_TRACE_TRACING, "yaffs: yaffs_ll_init()");
  6457. +
  6458. + if (!dev) {
  6459. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6460. + "yaffs: Need a device"
  6461. + );
  6462. + return YAFFS_FAIL;
  6463. + }
  6464. +
  6465. + if (dev->ll_init)
  6466. + return YAFFS_OK;
  6467. +
  6468. + dev->internal_start_block = dev->param.start_block;
  6469. + dev->internal_end_block = dev->param.end_block;
  6470. + dev->block_offset = 0;
  6471. + dev->chunk_offset = 0;
  6472. + dev->n_free_chunks = 0;
  6473. +
  6474. + dev->gc_block = 0;
  6475. +
  6476. + if (dev->param.start_block == 0) {
  6477. + dev->internal_start_block = dev->param.start_block + 1;
  6478. + dev->internal_end_block = dev->param.end_block + 1;
  6479. + dev->block_offset = 1;
  6480. + dev->chunk_offset = dev->param.chunks_per_block;
  6481. + }
  6482. +
  6483. + /* Check geometry parameters. */
  6484. +
  6485. + if ((!dev->param.inband_tags && dev->param.is_yaffs2 &&
  6486. + dev->param.total_bytes_per_chunk < 1024) ||
  6487. + (!dev->param.is_yaffs2 &&
  6488. + dev->param.total_bytes_per_chunk < 512) ||
  6489. + (dev->param.inband_tags && !dev->param.is_yaffs2) ||
  6490. + dev->param.chunks_per_block < 2 ||
  6491. + dev->param.n_reserved_blocks < 2 ||
  6492. + dev->internal_start_block <= 0 ||
  6493. + dev->internal_end_block <= 0 ||
  6494. + dev->internal_end_block <=
  6495. + (dev->internal_start_block + dev->param.n_reserved_blocks + 2)
  6496. + ) {
  6497. + /* otherwise it is too small */
  6498. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6499. + "NAND geometry problems: chunk size %d, type is yaffs%s, inband_tags %d ",
  6500. + dev->param.total_bytes_per_chunk,
  6501. + dev->param.is_yaffs2 ? "2" : "",
  6502. + dev->param.inband_tags);
  6503. + return YAFFS_FAIL;
  6504. + }
  6505. +
  6506. + /* Sort out space for inband tags, if required */
  6507. + if (dev->param.inband_tags)
  6508. + dev->data_bytes_per_chunk =
  6509. + dev->param.total_bytes_per_chunk -
  6510. + sizeof(struct yaffs_packed_tags2_tags_only);
  6511. + else
  6512. + dev->data_bytes_per_chunk = dev->param.total_bytes_per_chunk;
  6513. +
  6514. + /* Got the right mix of functions? */
  6515. + if (!yaffs_check_dev_fns(dev)) {
  6516. + /* Function missing */
  6517. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6518. + "device function(s) missing or wrong");
  6519. +
  6520. + return YAFFS_FAIL;
  6521. + }
  6522. +
  6523. + if (yaffs_init_nand(dev) != YAFFS_OK) {
  6524. + yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed");
  6525. + return YAFFS_FAIL;
  6526. + }
  6527. +
  6528. + return YAFFS_OK;
  6529. +}
  6530. +
  6531. +
  6532. +int yaffs_guts_format_dev(struct yaffs_dev *dev)
  6533. +{
  6534. + int i;
  6535. + enum yaffs_block_state state;
  6536. + u32 dummy;
  6537. +
  6538. + if(yaffs_guts_ll_init(dev) != YAFFS_OK)
  6539. + return YAFFS_FAIL;
  6540. +
  6541. + if(dev->is_mounted)
  6542. + return YAFFS_FAIL;
  6543. +
  6544. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  6545. + yaffs_query_init_block_state(dev, i, &state, &dummy);
  6546. + if (state != YAFFS_BLOCK_STATE_DEAD)
  6547. + yaffs_erase_block(dev, i);
  6548. + }
  6549. +
  6550. + return YAFFS_OK;
  6551. +}
  6552. +
  6553. +
  6554. +int yaffs_guts_initialise(struct yaffs_dev *dev)
  6555. +{
  6556. + int init_failed = 0;
  6557. + unsigned x;
  6558. + int bits;
  6559. +
  6560. + if(yaffs_guts_ll_init(dev) != YAFFS_OK)
  6561. + return YAFFS_FAIL;
  6562. +
  6563. + if (dev->is_mounted) {
  6564. + yaffs_trace(YAFFS_TRACE_ALWAYS, "device already mounted");
  6565. + return YAFFS_FAIL;
  6566. + }
  6567. +
  6568. + dev->is_mounted = 1;
  6569. +
  6570. + /* OK now calculate a few things for the device */
  6571. +
  6572. + /*
  6573. + * Calculate all the chunk size manipulation numbers:
  6574. + */
  6575. + x = dev->data_bytes_per_chunk;
  6576. + /* We always use dev->chunk_shift and dev->chunk_div */
  6577. + dev->chunk_shift = calc_shifts(x);
  6578. + x >>= dev->chunk_shift;
  6579. + dev->chunk_div = x;
  6580. + /* We only use chunk mask if chunk_div is 1 */
  6581. + dev->chunk_mask = (1 << dev->chunk_shift) - 1;
  6582. +
  6583. + /*
  6584. + * Calculate chunk_grp_bits.
  6585. + * We need to find the next power of 2 > than internal_end_block
  6586. + */
  6587. +
  6588. + x = dev->param.chunks_per_block * (dev->internal_end_block + 1);
  6589. +
  6590. + bits = calc_shifts_ceiling(x);
  6591. +
  6592. + /* Set up tnode width if wide tnodes are enabled. */
  6593. + if (!dev->param.wide_tnodes_disabled) {
  6594. + /* bits must be even so that we end up with 32-bit words */
  6595. + if (bits & 1)
  6596. + bits++;
  6597. + if (bits < 16)
  6598. + dev->tnode_width = 16;
  6599. + else
  6600. + dev->tnode_width = bits;
  6601. + } else {
  6602. + dev->tnode_width = 16;
  6603. + }
  6604. +
  6605. + dev->tnode_mask = (1 << dev->tnode_width) - 1;
  6606. +
  6607. + /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
  6608. + * so if the bitwidth of the
  6609. + * chunk range we're using is greater than 16 we need
  6610. + * to figure out chunk shift and chunk_grp_size
  6611. + */
  6612. +
  6613. + if (bits <= dev->tnode_width)
  6614. + dev->chunk_grp_bits = 0;
  6615. + else
  6616. + dev->chunk_grp_bits = bits - dev->tnode_width;
  6617. +
  6618. + dev->tnode_size = (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8;
  6619. + if (dev->tnode_size < sizeof(struct yaffs_tnode))
  6620. + dev->tnode_size = sizeof(struct yaffs_tnode);
  6621. +
  6622. + dev->chunk_grp_size = 1 << dev->chunk_grp_bits;
  6623. +
  6624. + if (dev->param.chunks_per_block < dev->chunk_grp_size) {
  6625. + /* We have a problem because the soft delete won't work if
  6626. + * the chunk group size > chunks per block.
  6627. + * This can be remedied by using larger "virtual blocks".
  6628. + */
  6629. + yaffs_trace(YAFFS_TRACE_ALWAYS, "chunk group too large");
  6630. +
  6631. + return YAFFS_FAIL;
  6632. + }
  6633. +
  6634. + /* Finished verifying the device, continue with initialisation */
  6635. +
  6636. + /* More device initialisation */
  6637. + dev->all_gcs = 0;
  6638. + dev->passive_gc_count = 0;
  6639. + dev->oldest_dirty_gc_count = 0;
  6640. + dev->bg_gcs = 0;
  6641. + dev->gc_block_finder = 0;
  6642. + dev->buffered_block = -1;
  6643. + dev->doing_buffered_block_rewrite = 0;
  6644. + dev->n_deleted_files = 0;
  6645. + dev->n_bg_deletions = 0;
  6646. + dev->n_unlinked_files = 0;
  6647. + dev->n_ecc_fixed = 0;
  6648. + dev->n_ecc_unfixed = 0;
  6649. + dev->n_tags_ecc_fixed = 0;
  6650. + dev->n_tags_ecc_unfixed = 0;
  6651. + dev->n_erase_failures = 0;
  6652. + dev->n_erased_blocks = 0;
  6653. + dev->gc_disable = 0;
  6654. + dev->has_pending_prioritised_gc = 1;
  6655. + /* Assume the worst for now, will get fixed on first GC */
  6656. + INIT_LIST_HEAD(&dev->dirty_dirs);
  6657. + dev->oldest_dirty_seq = 0;
  6658. + dev->oldest_dirty_block = 0;
  6659. +
  6660. + /* Initialise temporary buffers and caches. */
  6661. + if (!yaffs_init_tmp_buffers(dev))
  6662. + init_failed = 1;
  6663. +
  6664. + dev->cache = NULL;
  6665. + dev->gc_cleanup_list = NULL;
  6666. +
  6667. + if (!init_failed && dev->param.n_caches > 0) {
  6668. + int i;
  6669. + void *buf;
  6670. + int cache_bytes =
  6671. + dev->param.n_caches * sizeof(struct yaffs_cache);
  6672. +
  6673. + if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES)
  6674. + dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES;
  6675. +
  6676. + dev->cache = kmalloc(cache_bytes, GFP_NOFS);
  6677. +
  6678. + buf = (u8 *) dev->cache;
  6679. +
  6680. + if (dev->cache)
  6681. + memset(dev->cache, 0, cache_bytes);
  6682. +
  6683. + for (i = 0; i < dev->param.n_caches && buf; i++) {
  6684. + dev->cache[i].object = NULL;
  6685. + dev->cache[i].last_use = 0;
  6686. + dev->cache[i].dirty = 0;
  6687. + dev->cache[i].data = buf =
  6688. + kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
  6689. + }
  6690. + if (!buf)
  6691. + init_failed = 1;
  6692. +
  6693. + dev->cache_last_use = 0;
  6694. + }
  6695. +
  6696. + dev->cache_hits = 0;
  6697. +
  6698. + if (!init_failed) {
  6699. + dev->gc_cleanup_list =
  6700. + kmalloc(dev->param.chunks_per_block * sizeof(u32),
  6701. + GFP_NOFS);
  6702. + if (!dev->gc_cleanup_list)
  6703. + init_failed = 1;
  6704. + }
  6705. +
  6706. + if (dev->param.is_yaffs2)
  6707. + dev->param.use_header_file_size = 1;
  6708. +
  6709. + if (!init_failed && !yaffs_init_blocks(dev))
  6710. + init_failed = 1;
  6711. +
  6712. + yaffs_init_tnodes_and_objs(dev);
  6713. +
  6714. + if (!init_failed && !yaffs_create_initial_dir(dev))
  6715. + init_failed = 1;
  6716. +
  6717. + if (!init_failed && dev->param.is_yaffs2 &&
  6718. + !dev->param.disable_summary &&
  6719. + !yaffs_summary_init(dev))
  6720. + init_failed = 1;
  6721. +
  6722. + if (!init_failed) {
  6723. + /* Now scan the flash. */
  6724. + if (dev->param.is_yaffs2) {
  6725. + if (yaffs2_checkpt_restore(dev)) {
  6726. + yaffs_check_obj_details_loaded(dev->root_dir);
  6727. + yaffs_trace(YAFFS_TRACE_CHECKPOINT |
  6728. + YAFFS_TRACE_MOUNT,
  6729. + "yaffs: restored from checkpoint"
  6730. + );
  6731. + } else {
  6732. +
  6733. + /* Clean up the mess caused by an aborted
  6734. + * checkpoint load then scan backwards.
  6735. + */
  6736. + yaffs_deinit_blocks(dev);
  6737. +
  6738. + yaffs_deinit_tnodes_and_objs(dev);
  6739. +
  6740. + dev->n_erased_blocks = 0;
  6741. + dev->n_free_chunks = 0;
  6742. + dev->alloc_block = -1;
  6743. + dev->alloc_page = -1;
  6744. + dev->n_deleted_files = 0;
  6745. + dev->n_unlinked_files = 0;
  6746. + dev->n_bg_deletions = 0;
  6747. +
  6748. + if (!init_failed && !yaffs_init_blocks(dev))
  6749. + init_failed = 1;
  6750. +
  6751. + yaffs_init_tnodes_and_objs(dev);
  6752. +
  6753. + if (!init_failed
  6754. + && !yaffs_create_initial_dir(dev))
  6755. + init_failed = 1;
  6756. +
  6757. + if (!init_failed && !yaffs2_scan_backwards(dev))
  6758. + init_failed = 1;
  6759. + }
  6760. + } else if (!yaffs1_scan(dev)) {
  6761. + init_failed = 1;
  6762. + }
  6763. +
  6764. + yaffs_strip_deleted_objs(dev);
  6765. + yaffs_fix_hanging_objs(dev);
  6766. + if (dev->param.empty_lost_n_found)
  6767. + yaffs_empty_l_n_f(dev);
  6768. + }
  6769. +
  6770. + if (init_failed) {
  6771. + /* Clean up the mess */
  6772. + yaffs_trace(YAFFS_TRACE_TRACING,
  6773. + "yaffs: yaffs_guts_initialise() aborted.");
  6774. +
  6775. + yaffs_deinitialise(dev);
  6776. + return YAFFS_FAIL;
  6777. + }
  6778. +
  6779. + /* Zero out stats */
  6780. + dev->n_page_reads = 0;
  6781. + dev->n_page_writes = 0;
  6782. + dev->n_erasures = 0;
  6783. + dev->n_gc_copies = 0;
  6784. + dev->n_retried_writes = 0;
  6785. +
  6786. + dev->n_retired_blocks = 0;
  6787. +
  6788. + yaffs_verify_free_chunks(dev);
  6789. + yaffs_verify_blocks(dev);
  6790. +
  6791. + /* Clean up any aborted checkpoint data */
  6792. + if (!dev->is_checkpointed && dev->blocks_in_checkpt > 0)
  6793. + yaffs2_checkpt_invalidate(dev);
  6794. +
  6795. + yaffs_trace(YAFFS_TRACE_TRACING,
  6796. + "yaffs: yaffs_guts_initialise() done.");
  6797. + return YAFFS_OK;
  6798. +}
  6799. +
  6800. +void yaffs_deinitialise(struct yaffs_dev *dev)
  6801. +{
  6802. + if (dev->is_mounted) {
  6803. + int i;
  6804. +
  6805. + yaffs_deinit_blocks(dev);
  6806. + yaffs_deinit_tnodes_and_objs(dev);
  6807. + yaffs_summary_deinit(dev);
  6808. +
  6809. + if (dev->param.n_caches > 0 && dev->cache) {
  6810. +
  6811. + for (i = 0; i < dev->param.n_caches; i++) {
  6812. + kfree(dev->cache[i].data);
  6813. + dev->cache[i].data = NULL;
  6814. + }
  6815. +
  6816. + kfree(dev->cache);
  6817. + dev->cache = NULL;
  6818. + }
  6819. +
  6820. + kfree(dev->gc_cleanup_list);
  6821. +
  6822. + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
  6823. + kfree(dev->temp_buffer[i].buffer);
  6824. + dev->temp_buffer[i].buffer = NULL;
  6825. + }
  6826. +
  6827. + kfree(dev->checkpt_buffer);
  6828. + dev->checkpt_buffer = NULL;
  6829. + kfree(dev->checkpt_block_list);
  6830. + dev->checkpt_block_list = NULL;
  6831. +
  6832. + dev->is_mounted = 0;
  6833. +
  6834. + yaffs_deinit_nand(dev);
  6835. + }
  6836. +}
  6837. +
  6838. +int yaffs_count_free_chunks(struct yaffs_dev *dev)
  6839. +{
  6840. + int n_free = 0;
  6841. + int b;
  6842. + struct yaffs_block_info *blk;
  6843. +
  6844. + blk = dev->block_info;
  6845. + for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) {
  6846. + switch (blk->block_state) {
  6847. + case YAFFS_BLOCK_STATE_EMPTY:
  6848. + case YAFFS_BLOCK_STATE_ALLOCATING:
  6849. + case YAFFS_BLOCK_STATE_COLLECTING:
  6850. + case YAFFS_BLOCK_STATE_FULL:
  6851. + n_free +=
  6852. + (dev->param.chunks_per_block - blk->pages_in_use +
  6853. + blk->soft_del_pages);
  6854. + break;
  6855. + default:
  6856. + break;
  6857. + }
  6858. + blk++;
  6859. + }
  6860. + return n_free;
  6861. +}
  6862. +
  6863. +int yaffs_get_n_free_chunks(struct yaffs_dev *dev)
  6864. +{
  6865. + /* This is what we report to the outside world */
  6866. + int n_free;
  6867. + int n_dirty_caches;
  6868. + int blocks_for_checkpt;
  6869. + int i;
  6870. +
  6871. + n_free = dev->n_free_chunks;
  6872. + n_free += dev->n_deleted_files;
  6873. +
  6874. + /* Now count and subtract the number of dirty chunks in the cache. */
  6875. +
  6876. + for (n_dirty_caches = 0, i = 0; i < dev->param.n_caches; i++) {
  6877. + if (dev->cache[i].dirty)
  6878. + n_dirty_caches++;
  6879. + }
  6880. +
  6881. + n_free -= n_dirty_caches;
  6882. +
  6883. + n_free -=
  6884. + ((dev->param.n_reserved_blocks + 1) * dev->param.chunks_per_block);
  6885. +
  6886. + /* Now figure checkpoint space and report that... */
  6887. + blocks_for_checkpt = yaffs_calc_checkpt_blocks_required(dev);
  6888. +
  6889. + n_free -= (blocks_for_checkpt * dev->param.chunks_per_block);
  6890. +
  6891. + if (n_free < 0)
  6892. + n_free = 0;
  6893. +
  6894. + return n_free;
  6895. +}
  6896. +
  6897. +
  6898. +
  6899. +/*
  6900. + * Marshalling functions to get loff_t file sizes into and out of
  6901. + * object headers.
  6902. + */
  6903. +void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize)
  6904. +{
  6905. + oh->file_size_low = (fsize & 0xFFFFFFFF);
  6906. + oh->file_size_high = ((fsize >> 32) & 0xFFFFFFFF);
  6907. +}
  6908. +
  6909. +loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh)
  6910. +{
  6911. + loff_t retval;
  6912. +
  6913. + if (sizeof(loff_t) >= 8 && ~(oh->file_size_high))
  6914. + retval = (((loff_t) oh->file_size_high) << 32) |
  6915. + (((loff_t) oh->file_size_low) & 0xFFFFFFFF);
  6916. + else
  6917. + retval = (loff_t) oh->file_size_low;
  6918. +
  6919. + return retval;
  6920. +}
  6921. +
  6922. +
  6923. +void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10])
  6924. +{
  6925. + int i;
  6926. + struct yaffs_block_info *bi;
  6927. + int s;
  6928. +
  6929. + for(i = 0; i < 10; i++)
  6930. + bs[i] = 0;
  6931. +
  6932. + for(i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  6933. + bi = yaffs_get_block_info(dev, i);
  6934. + s = bi->block_state;
  6935. + if(s > YAFFS_BLOCK_STATE_DEAD || s < YAFFS_BLOCK_STATE_UNKNOWN)
  6936. + bs[0]++;
  6937. + else
  6938. + bs[s]++;
  6939. + }
  6940. +}
  6941. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_guts.h linux-3.18.14/fs/yaffs2/yaffs_guts.h
  6942. --- linux-3.18.14.orig/fs/yaffs2/yaffs_guts.h 1970-01-01 01:00:00.000000000 +0100
  6943. +++ linux-3.18.14/fs/yaffs2/yaffs_guts.h 2015-06-14 21:23:22.000000000 +0200
  6944. @@ -0,0 +1,1010 @@
  6945. +/*
  6946. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  6947. + *
  6948. + * Copyright (C) 2002-2011 Aleph One Ltd.
  6949. + * for Toby Churchill Ltd and Brightstar Engineering
  6950. + *
  6951. + * Created by Charles Manning <charles@aleph1.co.uk>
  6952. + *
  6953. + * This program is free software; you can redistribute it and/or modify
  6954. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  6955. + * published by the Free Software Foundation.
  6956. + *
  6957. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  6958. + */
  6959. +
  6960. +#ifndef __YAFFS_GUTS_H__
  6961. +#define __YAFFS_GUTS_H__
  6962. +
  6963. +#include "yportenv.h"
  6964. +
  6965. +#define YAFFS_OK 1
  6966. +#define YAFFS_FAIL 0
  6967. +
  6968. +/* Give us a Y=0x59,
  6969. + * Give us an A=0x41,
  6970. + * Give us an FF=0xff
  6971. + * Give us an S=0x53
  6972. + * And what have we got...
  6973. + */
  6974. +#define YAFFS_MAGIC 0x5941ff53
  6975. +
  6976. +/*
  6977. + * Tnodes form a tree with the tnodes in "levels"
  6978. + * Levels greater than 0 hold 8 slots which point to other tnodes.
  6979. + * Those at level 0 hold 16 slots which point to chunks in NAND.
  6980. + *
  6981. + * A maximum level of 8 thust supports files of size up to:
  6982. + *
  6983. + * 2^(3*MAX_LEVEL+4)
  6984. + *
  6985. + * Thus a max level of 8 supports files with up to 2^^28 chunks which gives
  6986. + * a maximum file size of around 512Gbytees with 2k chunks.
  6987. + */
  6988. +#define YAFFS_NTNODES_LEVEL0 16
  6989. +#define YAFFS_TNODES_LEVEL0_BITS 4
  6990. +#define YAFFS_TNODES_LEVEL0_MASK 0xf
  6991. +
  6992. +#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2)
  6993. +#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1)
  6994. +#define YAFFS_TNODES_INTERNAL_MASK 0x7
  6995. +#define YAFFS_TNODES_MAX_LEVEL 8
  6996. +#define YAFFS_TNODES_MAX_BITS (YAFFS_TNODES_LEVEL0_BITS + \
  6997. + YAFFS_TNODES_INTERNAL_BITS * \
  6998. + YAFFS_TNODES_MAX_LEVEL)
  6999. +#define YAFFS_MAX_CHUNK_ID ((1 << YAFFS_TNODES_MAX_BITS) - 1)
  7000. +
  7001. +#define YAFFS_MAX_FILE_SIZE_32 0x7fffffff
  7002. +
  7003. +/* Constants for YAFFS1 mode */
  7004. +#define YAFFS_BYTES_PER_SPARE 16
  7005. +#define YAFFS_BYTES_PER_CHUNK 512
  7006. +#define YAFFS_CHUNK_SIZE_SHIFT 9
  7007. +#define YAFFS_CHUNKS_PER_BLOCK 32
  7008. +#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
  7009. +
  7010. +#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024
  7011. +#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32
  7012. +
  7013. +
  7014. +
  7015. +#define YAFFS_ALLOCATION_NOBJECTS 100
  7016. +#define YAFFS_ALLOCATION_NTNODES 100
  7017. +#define YAFFS_ALLOCATION_NLINKS 100
  7018. +
  7019. +#define YAFFS_NOBJECT_BUCKETS 256
  7020. +
  7021. +#define YAFFS_OBJECT_SPACE 0x40000
  7022. +#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1)
  7023. +
  7024. +/* Binary data version stamps */
  7025. +#define YAFFS_SUMMARY_VERSION 1
  7026. +#define YAFFS_CHECKPOINT_VERSION 7
  7027. +
  7028. +#ifdef CONFIG_YAFFS_UNICODE
  7029. +#define YAFFS_MAX_NAME_LENGTH 127
  7030. +#define YAFFS_MAX_ALIAS_LENGTH 79
  7031. +#else
  7032. +#define YAFFS_MAX_NAME_LENGTH 255
  7033. +#define YAFFS_MAX_ALIAS_LENGTH 159
  7034. +#endif
  7035. +
  7036. +#define YAFFS_SHORT_NAME_LENGTH 15
  7037. +
  7038. +/* Some special object ids for pseudo objects */
  7039. +#define YAFFS_OBJECTID_ROOT 1
  7040. +#define YAFFS_OBJECTID_LOSTNFOUND 2
  7041. +#define YAFFS_OBJECTID_UNLINKED 3
  7042. +#define YAFFS_OBJECTID_DELETED 4
  7043. +
  7044. +/* Fake object Id for summary data */
  7045. +#define YAFFS_OBJECTID_SUMMARY 0x10
  7046. +
  7047. +/* Pseudo object ids for checkpointing */
  7048. +#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20
  7049. +#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21
  7050. +
  7051. +#define YAFFS_MAX_SHORT_OP_CACHES 20
  7052. +
  7053. +#define YAFFS_N_TEMP_BUFFERS 6
  7054. +
  7055. +/* We limit the number attempts at sucessfully saving a chunk of data.
  7056. + * Small-page devices have 32 pages per block; large-page devices have 64.
  7057. + * Default to something in the order of 5 to 10 blocks worth of chunks.
  7058. + */
  7059. +#define YAFFS_WR_ATTEMPTS (5*64)
  7060. +
  7061. +/* Sequence numbers are used in YAFFS2 to determine block allocation order.
  7062. + * The range is limited slightly to help distinguish bad numbers from good.
  7063. + * This also allows us to perhaps in the future use special numbers for
  7064. + * special purposes.
  7065. + * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years,
  7066. + * and is a larger number than the lifetime of a 2GB device.
  7067. + */
  7068. +#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000
  7069. +#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xefffff00
  7070. +
  7071. +/* Special sequence number for bad block that failed to be marked bad */
  7072. +#define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000
  7073. +
  7074. +/* ChunkCache is used for short read/write operations.*/
  7075. +struct yaffs_cache {
  7076. + struct yaffs_obj *object;
  7077. + int chunk_id;
  7078. + int last_use;
  7079. + int dirty;
  7080. + int n_bytes; /* Only valid if the cache is dirty */
  7081. + int locked; /* Can't push out or flush while locked. */
  7082. + u8 *data;
  7083. +};
  7084. +
  7085. +/* yaffs1 tags structures in RAM
  7086. + * NB This uses bitfield. Bitfields should not straddle a u32 boundary
  7087. + * otherwise the structure size will get blown out.
  7088. + */
  7089. +
  7090. +struct yaffs_tags {
  7091. + u32 chunk_id:20;
  7092. + u32 serial_number:2;
  7093. + u32 n_bytes_lsb:10;
  7094. + u32 obj_id:18;
  7095. + u32 ecc:12;
  7096. + u32 n_bytes_msb:2;
  7097. +};
  7098. +
  7099. +union yaffs_tags_union {
  7100. + struct yaffs_tags as_tags;
  7101. + u8 as_bytes[8];
  7102. +};
  7103. +
  7104. +
  7105. +/* Stuff used for extended tags in YAFFS2 */
  7106. +
  7107. +enum yaffs_ecc_result {
  7108. + YAFFS_ECC_RESULT_UNKNOWN,
  7109. + YAFFS_ECC_RESULT_NO_ERROR,
  7110. + YAFFS_ECC_RESULT_FIXED,
  7111. + YAFFS_ECC_RESULT_UNFIXED
  7112. +};
  7113. +
  7114. +enum yaffs_obj_type {
  7115. + YAFFS_OBJECT_TYPE_UNKNOWN,
  7116. + YAFFS_OBJECT_TYPE_FILE,
  7117. + YAFFS_OBJECT_TYPE_SYMLINK,
  7118. + YAFFS_OBJECT_TYPE_DIRECTORY,
  7119. + YAFFS_OBJECT_TYPE_HARDLINK,
  7120. + YAFFS_OBJECT_TYPE_SPECIAL
  7121. +};
  7122. +
  7123. +#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL
  7124. +
  7125. +struct yaffs_ext_tags {
  7126. + unsigned chunk_used; /* Status of the chunk: used or unused */
  7127. + unsigned obj_id; /* If 0 this is not used */
  7128. + unsigned chunk_id; /* If 0 this is a header, else a data chunk */
  7129. + unsigned n_bytes; /* Only valid for data chunks */
  7130. +
  7131. + /* The following stuff only has meaning when we read */
  7132. + enum yaffs_ecc_result ecc_result;
  7133. + unsigned block_bad;
  7134. +
  7135. + /* YAFFS 1 stuff */
  7136. + unsigned is_deleted; /* The chunk is marked deleted */
  7137. + unsigned serial_number; /* Yaffs1 2-bit serial number */
  7138. +
  7139. + /* YAFFS2 stuff */
  7140. + unsigned seq_number; /* The sequence number of this block */
  7141. +
  7142. + /* Extra info if this is an object header (YAFFS2 only) */
  7143. +
  7144. + unsigned extra_available; /* Extra info available if not zero */
  7145. + unsigned extra_parent_id; /* The parent object */
  7146. + unsigned extra_is_shrink; /* Is it a shrink header? */
  7147. + unsigned extra_shadows; /* Does this shadow another object? */
  7148. +
  7149. + enum yaffs_obj_type extra_obj_type; /* What object type? */
  7150. +
  7151. + loff_t extra_file_size; /* Length if it is a file */
  7152. + unsigned extra_equiv_id; /* Equivalent object for a hard link */
  7153. +};
  7154. +
  7155. +/* Spare structure for YAFFS1 */
  7156. +struct yaffs_spare {
  7157. + u8 tb0;
  7158. + u8 tb1;
  7159. + u8 tb2;
  7160. + u8 tb3;
  7161. + u8 page_status; /* set to 0 to delete the chunk */
  7162. + u8 block_status;
  7163. + u8 tb4;
  7164. + u8 tb5;
  7165. + u8 ecc1[3];
  7166. + u8 tb6;
  7167. + u8 tb7;
  7168. + u8 ecc2[3];
  7169. +};
  7170. +
  7171. +/*Special structure for passing through to mtd */
  7172. +struct yaffs_nand_spare {
  7173. + struct yaffs_spare spare;
  7174. + int eccres1;
  7175. + int eccres2;
  7176. +};
  7177. +
  7178. +/* Block data in RAM */
  7179. +
  7180. +enum yaffs_block_state {
  7181. + YAFFS_BLOCK_STATE_UNKNOWN = 0,
  7182. +
  7183. + YAFFS_BLOCK_STATE_SCANNING,
  7184. + /* Being scanned */
  7185. +
  7186. + YAFFS_BLOCK_STATE_NEEDS_SCAN,
  7187. + /* The block might have something on it (ie it is allocating or full,
  7188. + * perhaps empty) but it needs to be scanned to determine its true
  7189. + * state.
  7190. + * This state is only valid during scanning.
  7191. + * NB We tolerate empty because the pre-scanner might be incapable of
  7192. + * deciding
  7193. + * However, if this state is returned on a YAFFS2 device,
  7194. + * then we expect a sequence number
  7195. + */
  7196. +
  7197. + YAFFS_BLOCK_STATE_EMPTY,
  7198. + /* This block is empty */
  7199. +
  7200. + YAFFS_BLOCK_STATE_ALLOCATING,
  7201. + /* This block is partially allocated.
  7202. + * At least one page holds valid data.
  7203. + * This is the one currently being used for page
  7204. + * allocation. Should never be more than one of these.
  7205. + * If a block is only partially allocated at mount it is treated as
  7206. + * full.
  7207. + */
  7208. +
  7209. + YAFFS_BLOCK_STATE_FULL,
  7210. + /* All the pages in this block have been allocated.
  7211. + * If a block was only partially allocated when mounted we treat
  7212. + * it as fully allocated.
  7213. + */
  7214. +
  7215. + YAFFS_BLOCK_STATE_DIRTY,
  7216. + /* The block was full and now all chunks have been deleted.
  7217. + * Erase me, reuse me.
  7218. + */
  7219. +
  7220. + YAFFS_BLOCK_STATE_CHECKPOINT,
  7221. + /* This block is assigned to holding checkpoint data. */
  7222. +
  7223. + YAFFS_BLOCK_STATE_COLLECTING,
  7224. + /* This block is being garbage collected */
  7225. +
  7226. + YAFFS_BLOCK_STATE_DEAD
  7227. + /* This block has failed and is not in use */
  7228. +};
  7229. +
  7230. +#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1)
  7231. +
  7232. +struct yaffs_block_info {
  7233. +
  7234. + s32 soft_del_pages:10; /* number of soft deleted pages */
  7235. + s32 pages_in_use:10; /* number of pages in use */
  7236. + u32 block_state:4; /* One of the above block states. */
  7237. + /* NB use unsigned because enum is sometimes
  7238. + * an int */
  7239. + u32 needs_retiring:1; /* Data has failed on this block, */
  7240. + /*need to get valid data off and retire*/
  7241. + u32 skip_erased_check:1;/* Skip the erased check on this block */
  7242. + u32 gc_prioritise:1; /* An ECC check or blank check has failed.
  7243. + Block should be prioritised for GC */
  7244. + u32 chunk_error_strikes:3; /* How many times we've had ecc etc
  7245. + failures on this block and tried to reuse it */
  7246. + u32 has_summary:1; /* The block has a summary */
  7247. +
  7248. + u32 has_shrink_hdr:1; /* This block has at least one shrink header */
  7249. + u32 seq_number; /* block sequence number for yaffs2 */
  7250. +
  7251. +};
  7252. +
  7253. +/* -------------------------- Object structure -------------------------------*/
  7254. +/* This is the object structure as stored on NAND */
  7255. +
  7256. +struct yaffs_obj_hdr {
  7257. + enum yaffs_obj_type type;
  7258. +
  7259. + /* Apply to everything */
  7260. + int parent_obj_id;
  7261. + u16 sum_no_longer_used; /* checksum of name. No longer used */
  7262. + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
  7263. +
  7264. + /* The following apply to all object types except for hard links */
  7265. + u32 yst_mode; /* protection */
  7266. +
  7267. + u32 yst_uid;
  7268. + u32 yst_gid;
  7269. + u32 yst_atime;
  7270. + u32 yst_mtime;
  7271. + u32 yst_ctime;
  7272. +
  7273. + /* File size applies to files only */
  7274. + u32 file_size_low;
  7275. +
  7276. + /* Equivalent object id applies to hard links only. */
  7277. + int equiv_id;
  7278. +
  7279. + /* Alias is for symlinks only. */
  7280. + YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1];
  7281. +
  7282. + u32 yst_rdev; /* stuff for block and char devices (major/min) */
  7283. +
  7284. + u32 win_ctime[2];
  7285. + u32 win_atime[2];
  7286. + u32 win_mtime[2];
  7287. +
  7288. + u32 inband_shadowed_obj_id;
  7289. + u32 inband_is_shrink;
  7290. +
  7291. + u32 file_size_high;
  7292. + u32 reserved[1];
  7293. + int shadows_obj; /* This object header shadows the
  7294. + specified object if > 0 */
  7295. +
  7296. + /* is_shrink applies to object headers written when wemake a hole. */
  7297. + u32 is_shrink;
  7298. +
  7299. +};
  7300. +
  7301. +/*--------------------------- Tnode -------------------------- */
  7302. +
  7303. +struct yaffs_tnode {
  7304. + struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL];
  7305. +};
  7306. +
  7307. +/*------------------------ Object -----------------------------*/
  7308. +/* An object can be one of:
  7309. + * - a directory (no data, has children links
  7310. + * - a regular file (data.... not prunes :->).
  7311. + * - a symlink [symbolic link] (the alias).
  7312. + * - a hard link
  7313. + */
  7314. +
  7315. +struct yaffs_file_var {
  7316. + loff_t file_size;
  7317. + loff_t scanned_size;
  7318. + loff_t shrink_size;
  7319. + int top_level;
  7320. + struct yaffs_tnode *top;
  7321. +};
  7322. +
  7323. +struct yaffs_dir_var {
  7324. + struct list_head children; /* list of child links */
  7325. + struct list_head dirty; /* Entry for list of dirty directories */
  7326. +};
  7327. +
  7328. +struct yaffs_symlink_var {
  7329. + YCHAR *alias;
  7330. +};
  7331. +
  7332. +struct yaffs_hardlink_var {
  7333. + struct yaffs_obj *equiv_obj;
  7334. + u32 equiv_id;
  7335. +};
  7336. +
  7337. +union yaffs_obj_var {
  7338. + struct yaffs_file_var file_variant;
  7339. + struct yaffs_dir_var dir_variant;
  7340. + struct yaffs_symlink_var symlink_variant;
  7341. + struct yaffs_hardlink_var hardlink_variant;
  7342. +};
  7343. +
  7344. +struct yaffs_obj {
  7345. + u8 deleted:1; /* This should only apply to unlinked files. */
  7346. + u8 soft_del:1; /* it has also been soft deleted */
  7347. + u8 unlinked:1; /* An unlinked file.*/
  7348. + u8 fake:1; /* A fake object has no presence on NAND. */
  7349. + u8 rename_allowed:1; /* Some objects cannot be renamed. */
  7350. + u8 unlink_allowed:1;
  7351. + u8 dirty:1; /* the object needs to be written to flash */
  7352. + u8 valid:1; /* When the file system is being loaded up, this
  7353. + * object might be created before the data
  7354. + * is available
  7355. + * ie. file data chunks encountered before
  7356. + * the header.
  7357. + */
  7358. + u8 lazy_loaded:1; /* This object has been lazy loaded and
  7359. + * is missing some detail */
  7360. +
  7361. + u8 defered_free:1; /* Object is removed from NAND, but is
  7362. + * still in the inode cache.
  7363. + * Free of object is defered.
  7364. + * until the inode is released.
  7365. + */
  7366. + u8 being_created:1; /* This object is still being created
  7367. + * so skip some verification checks. */
  7368. + u8 is_shadowed:1; /* This object is shadowed on the way
  7369. + * to being renamed. */
  7370. +
  7371. + u8 xattr_known:1; /* We know if this has object has xattribs
  7372. + * or not. */
  7373. + u8 has_xattr:1; /* This object has xattribs.
  7374. + * Only valid if xattr_known. */
  7375. +
  7376. + u8 serial; /* serial number of chunk in NAND.*/
  7377. + u16 sum; /* sum of the name to speed searching */
  7378. +
  7379. + struct yaffs_dev *my_dev; /* The device I'm on */
  7380. +
  7381. + struct list_head hash_link; /* list of objects in hash bucket */
  7382. +
  7383. + struct list_head hard_links; /* hard linked object chain*/
  7384. +
  7385. + /* directory structure stuff */
  7386. + /* also used for linking up the free list */
  7387. + struct yaffs_obj *parent;
  7388. + struct list_head siblings;
  7389. +
  7390. + /* Where's my object header in NAND? */
  7391. + int hdr_chunk;
  7392. +
  7393. + int n_data_chunks; /* Number of data chunks for this file. */
  7394. +
  7395. + u32 obj_id; /* the object id value */
  7396. +
  7397. + u32 yst_mode;
  7398. +
  7399. + YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1];
  7400. +
  7401. +#ifdef CONFIG_YAFFS_WINCE
  7402. + u32 win_ctime[2];
  7403. + u32 win_mtime[2];
  7404. + u32 win_atime[2];
  7405. +#else
  7406. + u32 yst_uid;
  7407. + u32 yst_gid;
  7408. + u32 yst_atime;
  7409. + u32 yst_mtime;
  7410. + u32 yst_ctime;
  7411. +#endif
  7412. +
  7413. + u32 yst_rdev;
  7414. +
  7415. + void *my_inode;
  7416. +
  7417. + enum yaffs_obj_type variant_type;
  7418. +
  7419. + union yaffs_obj_var variant;
  7420. +
  7421. +};
  7422. +
  7423. +struct yaffs_obj_bucket {
  7424. + struct list_head list;
  7425. + int count;
  7426. +};
  7427. +
  7428. +/* yaffs_checkpt_obj holds the definition of an object as dumped
  7429. + * by checkpointing.
  7430. + */
  7431. +
  7432. +struct yaffs_checkpt_obj {
  7433. + int struct_type;
  7434. + u32 obj_id;
  7435. + u32 parent_id;
  7436. + int hdr_chunk;
  7437. + enum yaffs_obj_type variant_type:3;
  7438. + u8 deleted:1;
  7439. + u8 soft_del:1;
  7440. + u8 unlinked:1;
  7441. + u8 fake:1;
  7442. + u8 rename_allowed:1;
  7443. + u8 unlink_allowed:1;
  7444. + u8 serial;
  7445. + int n_data_chunks;
  7446. + loff_t size_or_equiv_obj;
  7447. +};
  7448. +
  7449. +/*--------------------- Temporary buffers ----------------
  7450. + *
  7451. + * These are chunk-sized working buffers. Each device has a few.
  7452. + */
  7453. +
  7454. +struct yaffs_buffer {
  7455. + u8 *buffer;
  7456. + int in_use;
  7457. +};
  7458. +
  7459. +/*----------------- Device ---------------------------------*/
  7460. +
  7461. +struct yaffs_param {
  7462. + const YCHAR *name;
  7463. +
  7464. + /*
  7465. + * Entry parameters set up way early. Yaffs sets up the rest.
  7466. + * The structure should be zeroed out before use so that unused
  7467. + * and default values are zero.
  7468. + */
  7469. +
  7470. + int inband_tags; /* Use unband tags */
  7471. + u32 total_bytes_per_chunk; /* Should be >= 512, does not need to
  7472. + be a power of 2 */
  7473. + int chunks_per_block; /* does not need to be a power of 2 */
  7474. + int spare_bytes_per_chunk; /* spare area size */
  7475. + int start_block; /* Start block we're allowed to use */
  7476. + int end_block; /* End block we're allowed to use */
  7477. + int n_reserved_blocks; /* Tuneable so that we can reduce
  7478. + * reserved blocks on NOR and RAM. */
  7479. +
  7480. + int n_caches; /* If <= 0, then short op caching is disabled,
  7481. + * else the number of short op caches.
  7482. + */
  7483. + int cache_bypass_aligned; /* If non-zero then bypass the cache for
  7484. + * aligned writes.
  7485. + */
  7486. +
  7487. + int use_nand_ecc; /* Flag to decide whether or not to use
  7488. + * NAND driver ECC on data (yaffs1) */
  7489. + int tags_9bytes; /* Use 9 byte tags */
  7490. + int no_tags_ecc; /* Flag to decide whether or not to do ECC
  7491. + * on packed tags (yaffs2) */
  7492. +
  7493. + int is_yaffs2; /* Use yaffs2 mode on this device */
  7494. +
  7495. + int empty_lost_n_found; /* Auto-empty lost+found directory on mount */
  7496. +
  7497. + int refresh_period; /* How often to check for a block refresh */
  7498. +
  7499. + /* Checkpoint control. Can be set before or after initialisation */
  7500. + u8 skip_checkpt_rd;
  7501. + u8 skip_checkpt_wr;
  7502. +
  7503. + int enable_xattr; /* Enable xattribs */
  7504. +
  7505. + int max_objects; /*
  7506. + * Set to limit the number of objects created.
  7507. + * 0 = no limit.
  7508. + */
  7509. +
  7510. + /* The remove_obj_fn function must be supplied by OS flavours that
  7511. + * need it.
  7512. + * yaffs direct uses it to implement the faster readdir.
  7513. + * Linux uses it to protect the directory during unlocking.
  7514. + */
  7515. + void (*remove_obj_fn) (struct yaffs_obj *obj);
  7516. +
  7517. + /* Callback to mark the superblock dirty */
  7518. + void (*sb_dirty_fn) (struct yaffs_dev *dev);
  7519. +
  7520. + /* Callback to control garbage collection. */
  7521. + unsigned (*gc_control_fn) (struct yaffs_dev *dev);
  7522. +
  7523. + /* Debug control flags. Don't use unless you know what you're doing */
  7524. + int use_header_file_size; /* Flag to determine if we should use
  7525. + * file sizes from the header */
  7526. + int disable_lazy_load; /* Disable lazy loading on this device */
  7527. + int wide_tnodes_disabled; /* Set to disable wide tnodes */
  7528. + int disable_soft_del; /* yaffs 1 only: Set to disable the use of
  7529. + * softdeletion. */
  7530. +
  7531. + int defered_dir_update; /* Set to defer directory updates */
  7532. +
  7533. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  7534. + int auto_unicode;
  7535. +#endif
  7536. + int always_check_erased; /* Force chunk erased check always on */
  7537. +
  7538. + int disable_summary;
  7539. + int disable_bad_block_marking;
  7540. +
  7541. +};
  7542. +
  7543. +struct yaffs_driver {
  7544. + int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
  7545. + const u8 *data, int data_len,
  7546. + const u8 *oob, int oob_len);
  7547. + int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
  7548. + u8 *data, int data_len,
  7549. + u8 *oob, int oob_len,
  7550. + enum yaffs_ecc_result *ecc_result);
  7551. + int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no);
  7552. + int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no);
  7553. + int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no);
  7554. + int (*drv_initialise_fn) (struct yaffs_dev *dev);
  7555. + int (*drv_deinitialise_fn) (struct yaffs_dev *dev);
  7556. +};
  7557. +
  7558. +struct yaffs_tags_handler {
  7559. + int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
  7560. + int nand_chunk, const u8 *data,
  7561. + const struct yaffs_ext_tags *tags);
  7562. + int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
  7563. + int nand_chunk, u8 *data,
  7564. + struct yaffs_ext_tags *tags);
  7565. +
  7566. + int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
  7567. + enum yaffs_block_state *state,
  7568. + u32 *seq_number);
  7569. + int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no);
  7570. +};
  7571. +
  7572. +struct yaffs_dev {
  7573. + struct yaffs_param param;
  7574. + struct yaffs_driver drv;
  7575. + struct yaffs_tags_handler tagger;
  7576. +
  7577. + /* Context storage. Holds extra OS specific data for this device */
  7578. +
  7579. + void *os_context;
  7580. + void *driver_context;
  7581. +
  7582. + struct list_head dev_list;
  7583. +
  7584. + int ll_init;
  7585. + /* Runtime parameters. Set up by YAFFS. */
  7586. + int data_bytes_per_chunk;
  7587. +
  7588. + /* Non-wide tnode stuff */
  7589. + u16 chunk_grp_bits; /* Number of bits that need to be resolved if
  7590. + * the tnodes are not wide enough.
  7591. + */
  7592. + u16 chunk_grp_size; /* == 2^^chunk_grp_bits */
  7593. +
  7594. + /* Stuff to support wide tnodes */
  7595. + u32 tnode_width;
  7596. + u32 tnode_mask;
  7597. + u32 tnode_size;
  7598. +
  7599. + /* Stuff for figuring out file offset to chunk conversions */
  7600. + u32 chunk_shift; /* Shift value */
  7601. + u32 chunk_div; /* Divisor after shifting: 1 for 2^n sizes */
  7602. + u32 chunk_mask; /* Mask to use for power-of-2 case */
  7603. +
  7604. + int is_mounted;
  7605. + int read_only;
  7606. + int is_checkpointed;
  7607. +
  7608. + /* Stuff to support block offsetting to support start block zero */
  7609. + int internal_start_block;
  7610. + int internal_end_block;
  7611. + int block_offset;
  7612. + int chunk_offset;
  7613. +
  7614. + /* Runtime checkpointing stuff */
  7615. + int checkpt_page_seq; /* running sequence number of checkpt pages */
  7616. + int checkpt_byte_count;
  7617. + int checkpt_byte_offs;
  7618. + u8 *checkpt_buffer;
  7619. + int checkpt_open_write;
  7620. + int blocks_in_checkpt;
  7621. + int checkpt_cur_chunk;
  7622. + int checkpt_cur_block;
  7623. + int checkpt_next_block;
  7624. + int *checkpt_block_list;
  7625. + int checkpt_max_blocks;
  7626. + u32 checkpt_sum;
  7627. + u32 checkpt_xor;
  7628. +
  7629. + int checkpoint_blocks_required; /* Number of blocks needed to store
  7630. + * current checkpoint set */
  7631. +
  7632. + /* Block Info */
  7633. + struct yaffs_block_info *block_info;
  7634. + u8 *chunk_bits; /* bitmap of chunks in use */
  7635. + u8 block_info_alt:1; /* allocated using alternative alloc */
  7636. + u8 chunk_bits_alt:1; /* allocated using alternative alloc */
  7637. + int chunk_bit_stride; /* Number of bytes of chunk_bits per block.
  7638. + * Must be consistent with chunks_per_block.
  7639. + */
  7640. +
  7641. + int n_erased_blocks;
  7642. + int alloc_block; /* Current block being allocated off */
  7643. + u32 alloc_page;
  7644. + int alloc_block_finder; /* Used to search for next allocation block */
  7645. +
  7646. + /* Object and Tnode memory management */
  7647. + void *allocator;
  7648. + int n_obj;
  7649. + int n_tnodes;
  7650. +
  7651. + int n_hardlinks;
  7652. +
  7653. + struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS];
  7654. + u32 bucket_finder;
  7655. +
  7656. + int n_free_chunks;
  7657. +
  7658. + /* Garbage collection control */
  7659. + u32 *gc_cleanup_list; /* objects to delete at the end of a GC. */
  7660. + u32 n_clean_ups;
  7661. +
  7662. + unsigned has_pending_prioritised_gc; /* We think this device might
  7663. + have pending prioritised gcs */
  7664. + unsigned gc_disable;
  7665. + unsigned gc_block_finder;
  7666. + unsigned gc_dirtiest;
  7667. + unsigned gc_pages_in_use;
  7668. + unsigned gc_not_done;
  7669. + unsigned gc_block;
  7670. + unsigned gc_chunk;
  7671. + unsigned gc_skip;
  7672. + struct yaffs_summary_tags *gc_sum_tags;
  7673. +
  7674. + /* Special directories */
  7675. + struct yaffs_obj *root_dir;
  7676. + struct yaffs_obj *lost_n_found;
  7677. +
  7678. + int buffered_block; /* Which block is buffered here? */
  7679. + int doing_buffered_block_rewrite;
  7680. +
  7681. + struct yaffs_cache *cache;
  7682. + int cache_last_use;
  7683. +
  7684. + /* Stuff for background deletion and unlinked files. */
  7685. + struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted
  7686. + files live. */
  7687. + struct yaffs_obj *del_dir; /* Directory where deleted objects are
  7688. + sent to disappear. */
  7689. + struct yaffs_obj *unlinked_deletion; /* Current file being
  7690. + background deleted. */
  7691. + int n_deleted_files; /* Count of files awaiting deletion; */
  7692. + int n_unlinked_files; /* Count of unlinked files. */
  7693. + int n_bg_deletions; /* Count of background deletions. */
  7694. +
  7695. + /* Temporary buffer management */
  7696. + struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS];
  7697. + int max_temp;
  7698. + int temp_in_use;
  7699. + int unmanaged_buffer_allocs;
  7700. + int unmanaged_buffer_deallocs;
  7701. +
  7702. + /* yaffs2 runtime stuff */
  7703. + unsigned seq_number; /* Sequence number of currently
  7704. + allocating block */
  7705. + unsigned oldest_dirty_seq;
  7706. + unsigned oldest_dirty_block;
  7707. +
  7708. + /* Block refreshing */
  7709. + int refresh_skip; /* A skip down counter.
  7710. + * Refresh happens when this gets to zero. */
  7711. +
  7712. + /* Dirty directory handling */
  7713. + struct list_head dirty_dirs; /* List of dirty directories */
  7714. +
  7715. + /* Summary */
  7716. + int chunks_per_summary;
  7717. + struct yaffs_summary_tags *sum_tags;
  7718. +
  7719. + /* Statistics */
  7720. + u32 n_page_writes;
  7721. + u32 n_page_reads;
  7722. + u32 n_erasures;
  7723. + u32 n_bad_queries;
  7724. + u32 n_bad_markings;
  7725. + u32 n_erase_failures;
  7726. + u32 n_gc_copies;
  7727. + u32 all_gcs;
  7728. + u32 passive_gc_count;
  7729. + u32 oldest_dirty_gc_count;
  7730. + u32 n_gc_blocks;
  7731. + u32 bg_gcs;
  7732. + u32 n_retried_writes;
  7733. + u32 n_retired_blocks;
  7734. + u32 n_ecc_fixed;
  7735. + u32 n_ecc_unfixed;
  7736. + u32 n_tags_ecc_fixed;
  7737. + u32 n_tags_ecc_unfixed;
  7738. + u32 n_deletions;
  7739. + u32 n_unmarked_deletions;
  7740. + u32 refresh_count;
  7741. + u32 cache_hits;
  7742. + u32 tags_used;
  7743. + u32 summary_used;
  7744. +
  7745. +};
  7746. +
  7747. +/* The CheckpointDevice structure holds the device information that changes
  7748. + *at runtime and must be preserved over unmount/mount cycles.
  7749. + */
  7750. +struct yaffs_checkpt_dev {
  7751. + int struct_type;
  7752. + int n_erased_blocks;
  7753. + int alloc_block; /* Current block being allocated off */
  7754. + u32 alloc_page;
  7755. + int n_free_chunks;
  7756. +
  7757. + int n_deleted_files; /* Count of files awaiting deletion; */
  7758. + int n_unlinked_files; /* Count of unlinked files. */
  7759. + int n_bg_deletions; /* Count of background deletions. */
  7760. +
  7761. + /* yaffs2 runtime stuff */
  7762. + unsigned seq_number; /* Sequence number of currently
  7763. + * allocating block */
  7764. +
  7765. +};
  7766. +
  7767. +struct yaffs_checkpt_validity {
  7768. + int struct_type;
  7769. + u32 magic;
  7770. + u32 version;
  7771. + u32 head;
  7772. +};
  7773. +
  7774. +struct yaffs_shadow_fixer {
  7775. + int obj_id;
  7776. + int shadowed_id;
  7777. + struct yaffs_shadow_fixer *next;
  7778. +};
  7779. +
  7780. +/* Structure for doing xattr modifications */
  7781. +struct yaffs_xattr_mod {
  7782. + int set; /* If 0 then this is a deletion */
  7783. + const YCHAR *name;
  7784. + const void *data;
  7785. + int size;
  7786. + int flags;
  7787. + int result;
  7788. +};
  7789. +
  7790. +/*----------------------- YAFFS Functions -----------------------*/
  7791. +
  7792. +int yaffs_guts_initialise(struct yaffs_dev *dev);
  7793. +void yaffs_deinitialise(struct yaffs_dev *dev);
  7794. +
  7795. +int yaffs_get_n_free_chunks(struct yaffs_dev *dev);
  7796. +
  7797. +int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
  7798. + struct yaffs_obj *new_dir, const YCHAR * new_name);
  7799. +
  7800. +int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name);
  7801. +int yaffs_del_obj(struct yaffs_obj *obj);
  7802. +struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
  7803. + enum yaffs_obj_type type);
  7804. +
  7805. +
  7806. +int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
  7807. +loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
  7808. +int yaffs_get_obj_inode(struct yaffs_obj *obj);
  7809. +unsigned yaffs_get_obj_type(struct yaffs_obj *obj);
  7810. +int yaffs_get_obj_link_count(struct yaffs_obj *obj);
  7811. +
  7812. +/* File operations */
  7813. +int yaffs_file_rd(struct yaffs_obj *obj, u8 * buffer, loff_t offset,
  7814. + int n_bytes);
  7815. +int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset,
  7816. + int n_bytes, int write_trhrough);
  7817. +int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size);
  7818. +
  7819. +struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
  7820. + const YCHAR *name, u32 mode, u32 uid,
  7821. + u32 gid);
  7822. +
  7823. +int yaffs_flush_file(struct yaffs_obj *in,
  7824. + int update_time,
  7825. + int data_sync,
  7826. + int discard_cache);
  7827. +
  7828. +/* Flushing and checkpointing */
  7829. +void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard);
  7830. +
  7831. +int yaffs_checkpoint_save(struct yaffs_dev *dev);
  7832. +int yaffs_checkpoint_restore(struct yaffs_dev *dev);
  7833. +
  7834. +/* Directory operations */
  7835. +struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name,
  7836. + u32 mode, u32 uid, u32 gid);
  7837. +struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir,
  7838. + const YCHAR *name);
  7839. +struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number);
  7840. +
  7841. +/* Link operations */
  7842. +struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name,
  7843. + struct yaffs_obj *equiv_obj);
  7844. +
  7845. +struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj);
  7846. +
  7847. +/* Symlink operations */
  7848. +struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
  7849. + const YCHAR *name, u32 mode, u32 uid,
  7850. + u32 gid, const YCHAR *alias);
  7851. +YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj);
  7852. +
  7853. +/* Special inodes (fifos, sockets and devices) */
  7854. +struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
  7855. + const YCHAR *name, u32 mode, u32 uid,
  7856. + u32 gid, u32 rdev);
  7857. +
  7858. +int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name,
  7859. + const void *value, int size, int flags);
  7860. +int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value,
  7861. + int size);
  7862. +int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size);
  7863. +int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name);
  7864. +
  7865. +/* Special directories */
  7866. +struct yaffs_obj *yaffs_root(struct yaffs_dev *dev);
  7867. +struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev);
  7868. +
  7869. +void yaffs_handle_defered_free(struct yaffs_obj *obj);
  7870. +
  7871. +void yaffs_update_dirty_dirs(struct yaffs_dev *dev);
  7872. +
  7873. +int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency);
  7874. +
  7875. +/* Debug dump */
  7876. +int yaffs_dump_obj(struct yaffs_obj *obj);
  7877. +
  7878. +void yaffs_guts_test(struct yaffs_dev *dev);
  7879. +int yaffs_guts_ll_init(struct yaffs_dev *dev);
  7880. +
  7881. +
  7882. +/* A few useful functions to be used within the core files*/
  7883. +void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
  7884. + int lyn);
  7885. +int yaffs_check_ff(u8 *buffer, int n_bytes);
  7886. +void yaffs_handle_chunk_error(struct yaffs_dev *dev,
  7887. + struct yaffs_block_info *bi);
  7888. +
  7889. +u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev);
  7890. +void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer);
  7891. +
  7892. +struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
  7893. + int number,
  7894. + enum yaffs_obj_type type);
  7895. +int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  7896. + int nand_chunk, int in_scan);
  7897. +void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name);
  7898. +void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
  7899. + const struct yaffs_obj_hdr *oh);
  7900. +void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj);
  7901. +YCHAR *yaffs_clone_str(const YCHAR *str);
  7902. +void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list);
  7903. +void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no);
  7904. +int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name,
  7905. + int force, int is_shrink, int shadows,
  7906. + struct yaffs_xattr_mod *xop);
  7907. +void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id,
  7908. + int backward_scanning);
  7909. +int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks);
  7910. +struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev);
  7911. +struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
  7912. + struct yaffs_file_var *file_struct,
  7913. + u32 chunk_id,
  7914. + struct yaffs_tnode *passed_tn);
  7915. +
  7916. +int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
  7917. + int n_bytes, int write_trhrough);
  7918. +void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size);
  7919. +void yaffs_skip_rest_of_block(struct yaffs_dev *dev);
  7920. +
  7921. +int yaffs_count_free_chunks(struct yaffs_dev *dev);
  7922. +
  7923. +struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
  7924. + struct yaffs_file_var *file_struct,
  7925. + u32 chunk_id);
  7926. +
  7927. +u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
  7928. + unsigned pos);
  7929. +
  7930. +int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
  7931. +
  7932. +int yaffs_guts_format_dev(struct yaffs_dev *dev);
  7933. +
  7934. +void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
  7935. + int *chunk_out, u32 *offset_out);
  7936. +/*
  7937. + * Marshalling functions to get loff_t file sizes into aand out of
  7938. + * object headers.
  7939. + */
  7940. +void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize);
  7941. +loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh);
  7942. +loff_t yaffs_max_file_size(struct yaffs_dev *dev);
  7943. +
  7944. +/*
  7945. + * Debug function to count number of blocks in each state
  7946. + * NB Needs to be called with correct number of integers
  7947. + */
  7948. +
  7949. +void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10]);
  7950. +
  7951. +int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  7952. + struct yaffs_ext_tags *tags);
  7953. +
  7954. +#endif
  7955. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_linux.h linux-3.18.14/fs/yaffs2/yaffs_linux.h
  7956. --- linux-3.18.14.orig/fs/yaffs2/yaffs_linux.h 1970-01-01 01:00:00.000000000 +0100
  7957. +++ linux-3.18.14/fs/yaffs2/yaffs_linux.h 2015-06-14 21:23:22.000000000 +0200
  7958. @@ -0,0 +1,48 @@
  7959. +/*
  7960. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  7961. + *
  7962. + * Copyright (C) 2002-2011 Aleph One Ltd.
  7963. + * for Toby Churchill Ltd and Brightstar Engineering
  7964. + *
  7965. + * Created by Charles Manning <charles@aleph1.co.uk>
  7966. + *
  7967. + * This program is free software; you can redistribute it and/or modify
  7968. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  7969. + * published by the Free Software Foundation.
  7970. + *
  7971. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  7972. + */
  7973. +
  7974. +#ifndef __YAFFS_LINUX_H__
  7975. +#define __YAFFS_LINUX_H__
  7976. +
  7977. +#include "yportenv.h"
  7978. +
  7979. +struct yaffs_linux_context {
  7980. + struct list_head context_list; /* List of these we have mounted */
  7981. + struct yaffs_dev *dev;
  7982. + struct super_block *super;
  7983. + struct task_struct *bg_thread; /* Background thread for this device */
  7984. + int bg_running;
  7985. + struct mutex gross_lock; /* Gross locking mutex*/
  7986. + u8 *spare_buffer; /* For mtdif2 use. Don't know the buffer size
  7987. + * at compile time so we have to allocate it.
  7988. + */
  7989. + struct list_head search_contexts;
  7990. + struct task_struct *readdir_process;
  7991. + unsigned mount_id;
  7992. + int dirty;
  7993. +};
  7994. +
  7995. +#define yaffs_dev_to_lc(dev) ((struct yaffs_linux_context *)((dev)->os_context))
  7996. +#define yaffs_dev_to_mtd(dev) ((struct mtd_info *)((dev)->driver_context))
  7997. +
  7998. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  7999. +#define WRITE_SIZE_STR "writesize"
  8000. +#define WRITE_SIZE(mtd) ((mtd)->writesize)
  8001. +#else
  8002. +#define WRITE_SIZE_STR "oobblock"
  8003. +#define WRITE_SIZE(mtd) ((mtd)->oobblock)
  8004. +#endif
  8005. +
  8006. +#endif
  8007. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_mtdif.c linux-3.18.14/fs/yaffs2/yaffs_mtdif.c
  8008. --- linux-3.18.14.orig/fs/yaffs2/yaffs_mtdif.c 1970-01-01 01:00:00.000000000 +0100
  8009. +++ linux-3.18.14/fs/yaffs2/yaffs_mtdif.c 2015-06-14 21:23:22.000000000 +0200
  8010. @@ -0,0 +1,310 @@
  8011. +/*
  8012. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  8013. + *
  8014. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8015. + * for Toby Churchill Ltd and Brightstar Engineering
  8016. + *
  8017. + * Created by Charles Manning <charles@aleph1.co.uk>
  8018. + *
  8019. + * This program is free software; you can redistribute it and/or modify
  8020. + * it under the terms of the GNU General Public License version 2 as
  8021. + * published by the Free Software Foundation.
  8022. + */
  8023. +
  8024. +#include "yportenv.h"
  8025. +
  8026. +#include "yaffs_mtdif.h"
  8027. +
  8028. +#include "linux/mtd/mtd.h"
  8029. +#include "linux/types.h"
  8030. +#include "linux/time.h"
  8031. +#include "linux/mtd/nand.h"
  8032. +#include "linux/kernel.h"
  8033. +#include "linux/version.h"
  8034. +#include "linux/types.h"
  8035. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  8036. +#include "uapi/linux/major.h"
  8037. +#endif
  8038. +
  8039. +#include "yaffs_trace.h"
  8040. +#include "yaffs_guts.h"
  8041. +#include "yaffs_linux.h"
  8042. +
  8043. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
  8044. +#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
  8045. +#endif
  8046. +
  8047. +
  8048. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
  8049. +#define mtd_erase(m, ei) (m)->erase(m, ei)
  8050. +#define mtd_write_oob(m, addr, pops) (m)->write_oob(m, addr, pops)
  8051. +#define mtd_read_oob(m, addr, pops) (m)->read_oob(m, addr, pops)
  8052. +#define mtd_block_isbad(m, offs) (m)->block_isbad(m, offs)
  8053. +#define mtd_block_markbad(m, offs) (m)->block_markbad(m, offs)
  8054. +#endif
  8055. +
  8056. +
  8057. +
  8058. +int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
  8059. +{
  8060. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8061. + u32 addr =
  8062. + ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
  8063. + dev->param.chunks_per_block;
  8064. + struct erase_info ei;
  8065. + int retval = 0;
  8066. +
  8067. + ei.mtd = mtd;
  8068. + ei.addr = addr;
  8069. + ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
  8070. + ei.time = 1000;
  8071. + ei.retries = 2;
  8072. + ei.callback = NULL;
  8073. + ei.priv = (u_long) dev;
  8074. +
  8075. + retval = mtd_erase(mtd, &ei);
  8076. +
  8077. + if (retval == 0)
  8078. + return YAFFS_OK;
  8079. +
  8080. + return YAFFS_FAIL;
  8081. +}
  8082. +
  8083. +
  8084. +static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
  8085. + const u8 *data, int data_len,
  8086. + const u8 *oob, int oob_len)
  8087. +{
  8088. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8089. + loff_t addr;
  8090. + struct mtd_oob_ops ops;
  8091. + int retval;
  8092. +
  8093. + yaffs_trace(YAFFS_TRACE_MTD,
  8094. + "yaffs_mtd_write(%p, %d, %p, %d, %p, %d)\n",
  8095. + dev, nand_chunk, data, data_len, oob, oob_len);
  8096. +
  8097. + if (!data || !data_len) {
  8098. + data = NULL;
  8099. + data_len = 0;
  8100. + }
  8101. +
  8102. + if (!oob || !oob_len) {
  8103. + oob = NULL;
  8104. + oob_len = 0;
  8105. + }
  8106. +
  8107. + addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
  8108. + memset(&ops, 0, sizeof(ops));
  8109. + ops.mode = MTD_OPS_AUTO_OOB;
  8110. + ops.len = (data) ? data_len : 0;
  8111. + ops.ooblen = oob_len;
  8112. + ops.datbuf = (u8 *)data;
  8113. + ops.oobbuf = (u8 *)oob;
  8114. +
  8115. + retval = mtd_write_oob(mtd, addr, &ops);
  8116. + if (retval) {
  8117. + yaffs_trace(YAFFS_TRACE_MTD,
  8118. + "write_oob failed, chunk %d, mtd error %d",
  8119. + nand_chunk, retval);
  8120. + }
  8121. + return retval ? YAFFS_FAIL : YAFFS_OK;
  8122. +}
  8123. +
  8124. +static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk,
  8125. + u8 *data, int data_len,
  8126. + u8 *oob, int oob_len,
  8127. + enum yaffs_ecc_result *ecc_result)
  8128. +{
  8129. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8130. + loff_t addr;
  8131. + struct mtd_oob_ops ops;
  8132. + int retval;
  8133. +
  8134. + addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
  8135. + memset(&ops, 0, sizeof(ops));
  8136. + ops.mode = MTD_OPS_AUTO_OOB;
  8137. + ops.len = (data) ? data_len : 0;
  8138. + ops.ooblen = oob_len;
  8139. + ops.datbuf = data;
  8140. + ops.oobbuf = oob;
  8141. +
  8142. +#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
  8143. + /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
  8144. + * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
  8145. + */
  8146. + ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
  8147. +#endif
  8148. + /* Read page and oob using MTD.
  8149. + * Check status and determine ECC result.
  8150. + */
  8151. + retval = mtd_read_oob(mtd, addr, &ops);
  8152. + if (retval)
  8153. + yaffs_trace(YAFFS_TRACE_MTD,
  8154. + "read_oob failed, chunk %d, mtd error %d",
  8155. + nand_chunk, retval);
  8156. +
  8157. + switch (retval) {
  8158. + case 0:
  8159. + /* no error */
  8160. + if(ecc_result)
  8161. + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  8162. + break;
  8163. +
  8164. + case -EUCLEAN:
  8165. + /* MTD's ECC fixed the data */
  8166. + if(ecc_result)
  8167. + *ecc_result = YAFFS_ECC_RESULT_FIXED;
  8168. + dev->n_ecc_fixed++;
  8169. + break;
  8170. +
  8171. + case -EBADMSG:
  8172. + default:
  8173. + /* MTD's ECC could not fix the data */
  8174. + dev->n_ecc_unfixed++;
  8175. + if(ecc_result)
  8176. + *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  8177. + return YAFFS_FAIL;
  8178. + }
  8179. +
  8180. + return YAFFS_OK;
  8181. +}
  8182. +
  8183. +static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
  8184. +{
  8185. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8186. +
  8187. + loff_t addr;
  8188. + struct erase_info ei;
  8189. + int retval = 0;
  8190. + u32 block_size;
  8191. +
  8192. + block_size = dev->param.total_bytes_per_chunk *
  8193. + dev->param.chunks_per_block;
  8194. + addr = ((loff_t) block_no) * block_size;
  8195. +
  8196. + ei.mtd = mtd;
  8197. + ei.addr = addr;
  8198. + ei.len = block_size;
  8199. + ei.time = 1000;
  8200. + ei.retries = 2;
  8201. + ei.callback = NULL;
  8202. + ei.priv = (u_long) dev;
  8203. +
  8204. + retval = mtd_erase(mtd, &ei);
  8205. +
  8206. + if (retval == 0)
  8207. + return YAFFS_OK;
  8208. +
  8209. + return YAFFS_FAIL;
  8210. +}
  8211. +
  8212. +static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no)
  8213. +{
  8214. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8215. + int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk;
  8216. + int retval;
  8217. +
  8218. + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
  8219. +
  8220. + retval = mtd_block_markbad(mtd, (loff_t) blocksize * block_no);
  8221. + return (retval) ? YAFFS_FAIL : YAFFS_OK;
  8222. +}
  8223. +
  8224. +static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no)
  8225. +{
  8226. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8227. + int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk;
  8228. + int retval;
  8229. +
  8230. + yaffs_trace(YAFFS_TRACE_MTD, "checking block %d bad", block_no);
  8231. +
  8232. + retval = mtd_block_isbad(mtd, (loff_t) blocksize * block_no);
  8233. + return (retval) ? YAFFS_FAIL : YAFFS_OK;
  8234. +}
  8235. +
  8236. +static int yaffs_mtd_initialise(struct yaffs_dev *dev)
  8237. +{
  8238. + return YAFFS_OK;
  8239. +}
  8240. +
  8241. +static int yaffs_mtd_deinitialise(struct yaffs_dev *dev)
  8242. +{
  8243. + return YAFFS_OK;
  8244. +}
  8245. +
  8246. +
  8247. +void yaffs_mtd_drv_install(struct yaffs_dev *dev)
  8248. +{
  8249. + struct yaffs_driver *drv = &dev->drv;
  8250. +
  8251. + drv->drv_write_chunk_fn = yaffs_mtd_write;
  8252. + drv->drv_read_chunk_fn = yaffs_mtd_read;
  8253. + drv->drv_erase_fn = yaffs_mtd_erase;
  8254. + drv->drv_mark_bad_fn = yaffs_mtd_mark_bad;
  8255. + drv->drv_check_bad_fn = yaffs_mtd_check_bad;
  8256. + drv->drv_initialise_fn = yaffs_mtd_initialise;
  8257. + drv->drv_deinitialise_fn = yaffs_mtd_deinitialise;
  8258. +}
  8259. +
  8260. +
  8261. +struct mtd_info * yaffs_get_mtd_device(dev_t sdev)
  8262. +{
  8263. + struct mtd_info *mtd;
  8264. +
  8265. + mtd = yaffs_get_mtd_device(sdev);
  8266. +
  8267. + /* Check it's an mtd device..... */
  8268. + if (MAJOR(sdev) != MTD_BLOCK_MAJOR)
  8269. + return NULL; /* This isn't an mtd device */
  8270. +
  8271. + /* Check it's NAND */
  8272. + if (mtd->type != MTD_NANDFLASH) {
  8273. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  8274. + "yaffs: MTD device is not NAND it's type %d",
  8275. + mtd->type);
  8276. + return NULL;
  8277. + }
  8278. +
  8279. + yaffs_trace(YAFFS_TRACE_OS, " %s %d", WRITE_SIZE_STR, WRITE_SIZE(mtd));
  8280. + yaffs_trace(YAFFS_TRACE_OS, " oobsize %d", mtd->oobsize);
  8281. + yaffs_trace(YAFFS_TRACE_OS, " erasesize %d", mtd->erasesize);
  8282. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
  8283. + yaffs_trace(YAFFS_TRACE_OS, " size %u", mtd->size);
  8284. +#else
  8285. + yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size);
  8286. +#endif
  8287. +
  8288. + return mtd;
  8289. +}
  8290. +
  8291. +int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags)
  8292. +{
  8293. + if (yaffs_version == 2) {
  8294. + if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
  8295. + mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
  8296. + !inband_tags) {
  8297. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  8298. + "MTD device does not have the right page sizes"
  8299. + );
  8300. + return -1;
  8301. + }
  8302. + } else {
  8303. + if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK ||
  8304. + mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
  8305. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  8306. + "MTD device does not support have the right page sizes"
  8307. + );
  8308. + return -1;
  8309. + }
  8310. + }
  8311. +
  8312. + return 0;
  8313. +}
  8314. +
  8315. +
  8316. +void yaffs_put_mtd_device(struct mtd_info *mtd)
  8317. +{
  8318. + if(mtd)
  8319. + put_mtd_device(mtd);
  8320. +}
  8321. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_mtdif.h linux-3.18.14/fs/yaffs2/yaffs_mtdif.h
  8322. --- linux-3.18.14.orig/fs/yaffs2/yaffs_mtdif.h 1970-01-01 01:00:00.000000000 +0100
  8323. +++ linux-3.18.14/fs/yaffs2/yaffs_mtdif.h 2015-06-14 21:23:22.000000000 +0200
  8324. @@ -0,0 +1,25 @@
  8325. +/*
  8326. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  8327. + *
  8328. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8329. + * for Toby Churchill Ltd and Brightstar Engineering
  8330. + *
  8331. + * Created by Charles Manning <charles@aleph1.co.uk>
  8332. + *
  8333. + * This program is free software; you can redistribute it and/or modify
  8334. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  8335. + * published by the Free Software Foundation.
  8336. + *
  8337. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  8338. + */
  8339. +
  8340. +#ifndef __YAFFS_MTDIF_H__
  8341. +#define __YAFFS_MTDIF_H__
  8342. +
  8343. +#include "yaffs_guts.h"
  8344. +
  8345. +void yaffs_mtd_drv_install(struct yaffs_dev *dev);
  8346. +struct mtd_info * yaffs_get_mtd_device(dev_t sdev);
  8347. +void yaffs_put_mtd_device(struct mtd_info *mtd);
  8348. +int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags);
  8349. +#endif
  8350. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_nameval.c linux-3.18.14/fs/yaffs2/yaffs_nameval.c
  8351. --- linux-3.18.14.orig/fs/yaffs2/yaffs_nameval.c 1970-01-01 01:00:00.000000000 +0100
  8352. +++ linux-3.18.14/fs/yaffs2/yaffs_nameval.c 2015-06-14 21:23:22.000000000 +0200
  8353. @@ -0,0 +1,208 @@
  8354. +/*
  8355. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  8356. + *
  8357. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8358. + * for Toby Churchill Ltd and Brightstar Engineering
  8359. + *
  8360. + * Created by Charles Manning <charles@aleph1.co.uk>
  8361. + *
  8362. + * This program is free software; you can redistribute it and/or modify
  8363. + * it under the terms of the GNU General Public License version 2 as
  8364. + * published by the Free Software Foundation.
  8365. + */
  8366. +
  8367. +/*
  8368. + * This simple implementation of a name-value store assumes a small number of
  8369. +* values and fits into a small finite buffer.
  8370. + *
  8371. + * Each attribute is stored as a record:
  8372. + * sizeof(int) bytes record size.
  8373. + * strnlen+1 bytes name null terminated.
  8374. + * nbytes value.
  8375. + * ----------
  8376. + * total size stored in record size
  8377. + *
  8378. + * This code has not been tested with unicode yet.
  8379. + */
  8380. +
  8381. +#include "yaffs_nameval.h"
  8382. +
  8383. +#include "yportenv.h"
  8384. +
  8385. +static int nval_find(const char *xb, int xb_size, const YCHAR *name,
  8386. + int *exist_size)
  8387. +{
  8388. + int pos = 0;
  8389. + int size;
  8390. +
  8391. + memcpy(&size, xb, sizeof(int));
  8392. + while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
  8393. + if (!strncmp((YCHAR *) (xb + pos + sizeof(int)),
  8394. + name, size)) {
  8395. + if (exist_size)
  8396. + *exist_size = size;
  8397. + return pos;
  8398. + }
  8399. + pos += size;
  8400. + if (pos < xb_size - sizeof(int))
  8401. + memcpy(&size, xb + pos, sizeof(int));
  8402. + else
  8403. + size = 0;
  8404. + }
  8405. + if (exist_size)
  8406. + *exist_size = 0;
  8407. + return -ENODATA;
  8408. +}
  8409. +
  8410. +static int nval_used(const char *xb, int xb_size)
  8411. +{
  8412. + int pos = 0;
  8413. + int size;
  8414. +
  8415. + memcpy(&size, xb + pos, sizeof(int));
  8416. + while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
  8417. + pos += size;
  8418. + if (pos < xb_size - sizeof(int))
  8419. + memcpy(&size, xb + pos, sizeof(int));
  8420. + else
  8421. + size = 0;
  8422. + }
  8423. + return pos;
  8424. +}
  8425. +
  8426. +int nval_del(char *xb, int xb_size, const YCHAR *name)
  8427. +{
  8428. + int pos = nval_find(xb, xb_size, name, NULL);
  8429. + int size;
  8430. +
  8431. + if (pos < 0 || pos >= xb_size)
  8432. + return -ENODATA;
  8433. +
  8434. + /* Find size, shift rest over this record,
  8435. + * then zero out the rest of buffer */
  8436. + memcpy(&size, xb + pos, sizeof(int));
  8437. + memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
  8438. + memset(xb + (xb_size - size), 0, size);
  8439. + return 0;
  8440. +}
  8441. +
  8442. +int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf,
  8443. + int bsize, int flags)
  8444. +{
  8445. + int pos;
  8446. + int namelen = strnlen(name, xb_size);
  8447. + int reclen;
  8448. + int size_exist = 0;
  8449. + int space;
  8450. + int start;
  8451. +
  8452. + pos = nval_find(xb, xb_size, name, &size_exist);
  8453. +
  8454. + if (flags & XATTR_CREATE && pos >= 0)
  8455. + return -EEXIST;
  8456. + if (flags & XATTR_REPLACE && pos < 0)
  8457. + return -ENODATA;
  8458. +
  8459. + start = nval_used(xb, xb_size);
  8460. + space = xb_size - start + size_exist;
  8461. +
  8462. + reclen = (sizeof(int) + namelen + 1 + bsize);
  8463. +
  8464. + if (reclen > space)
  8465. + return -ENOSPC;
  8466. +
  8467. + if (pos >= 0) {
  8468. + nval_del(xb, xb_size, name);
  8469. + start = nval_used(xb, xb_size);
  8470. + }
  8471. +
  8472. + pos = start;
  8473. +
  8474. + memcpy(xb + pos, &reclen, sizeof(int));
  8475. + pos += sizeof(int);
  8476. + strncpy((YCHAR *) (xb + pos), name, reclen);
  8477. + pos += (namelen + 1);
  8478. + memcpy(xb + pos, buf, bsize);
  8479. + return 0;
  8480. +}
  8481. +
  8482. +int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
  8483. + int bsize)
  8484. +{
  8485. + int pos = nval_find(xb, xb_size, name, NULL);
  8486. + int size;
  8487. +
  8488. + if (pos >= 0 && pos < xb_size) {
  8489. +
  8490. + memcpy(&size, xb + pos, sizeof(int));
  8491. + pos += sizeof(int); /* advance past record length */
  8492. + size -= sizeof(int);
  8493. +
  8494. + /* Advance over name string */
  8495. + while (xb[pos] && size > 0 && pos < xb_size) {
  8496. + pos++;
  8497. + size--;
  8498. + }
  8499. + /*Advance over NUL */
  8500. + pos++;
  8501. + size--;
  8502. +
  8503. + /* If bsize is zero then this is a size query.
  8504. + * Return the size, but don't copy.
  8505. + */
  8506. + if (!bsize)
  8507. + return size;
  8508. +
  8509. + if (size <= bsize) {
  8510. + memcpy(buf, xb + pos, size);
  8511. + return size;
  8512. + }
  8513. + }
  8514. + if (pos >= 0)
  8515. + return -ERANGE;
  8516. +
  8517. + return -ENODATA;
  8518. +}
  8519. +
  8520. +int nval_list(const char *xb, int xb_size, char *buf, int bsize)
  8521. +{
  8522. + int pos = 0;
  8523. + int size;
  8524. + int name_len;
  8525. + int ncopied = 0;
  8526. + int filled = 0;
  8527. +
  8528. + memcpy(&size, xb + pos, sizeof(int));
  8529. + while (size > sizeof(int) &&
  8530. + size <= xb_size &&
  8531. + (pos + size) < xb_size &&
  8532. + !filled) {
  8533. + pos += sizeof(int);
  8534. + size -= sizeof(int);
  8535. + name_len = strnlen((YCHAR *) (xb + pos), size);
  8536. + if (ncopied + name_len + 1 < bsize) {
  8537. + memcpy(buf, xb + pos, name_len * sizeof(YCHAR));
  8538. + buf += name_len;
  8539. + *buf = '\0';
  8540. + buf++;
  8541. + if (sizeof(YCHAR) > 1) {
  8542. + *buf = '\0';
  8543. + buf++;
  8544. + }
  8545. + ncopied += (name_len + 1);
  8546. + } else {
  8547. + filled = 1;
  8548. + }
  8549. + pos += size;
  8550. + if (pos < xb_size - sizeof(int))
  8551. + memcpy(&size, xb + pos, sizeof(int));
  8552. + else
  8553. + size = 0;
  8554. + }
  8555. + return ncopied;
  8556. +}
  8557. +
  8558. +int nval_hasvalues(const char *xb, int xb_size)
  8559. +{
  8560. + return nval_used(xb, xb_size) > 0;
  8561. +}
  8562. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_nameval.h linux-3.18.14/fs/yaffs2/yaffs_nameval.h
  8563. --- linux-3.18.14.orig/fs/yaffs2/yaffs_nameval.h 1970-01-01 01:00:00.000000000 +0100
  8564. +++ linux-3.18.14/fs/yaffs2/yaffs_nameval.h 2015-06-14 21:23:22.000000000 +0200
  8565. @@ -0,0 +1,28 @@
  8566. +/*
  8567. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  8568. + *
  8569. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8570. + * for Toby Churchill Ltd and Brightstar Engineering
  8571. + *
  8572. + * Created by Charles Manning <charles@aleph1.co.uk>
  8573. + *
  8574. + * This program is free software; you can redistribute it and/or modify
  8575. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  8576. + * published by the Free Software Foundation.
  8577. + *
  8578. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  8579. + */
  8580. +
  8581. +#ifndef __NAMEVAL_H__
  8582. +#define __NAMEVAL_H__
  8583. +
  8584. +#include "yportenv.h"
  8585. +
  8586. +int nval_del(char *xb, int xb_size, const YCHAR * name);
  8587. +int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf,
  8588. + int bsize, int flags);
  8589. +int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
  8590. + int bsize);
  8591. +int nval_list(const char *xb, int xb_size, char *buf, int bsize);
  8592. +int nval_hasvalues(const char *xb, int xb_size);
  8593. +#endif
  8594. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_nand.c linux-3.18.14/fs/yaffs2/yaffs_nand.c
  8595. --- linux-3.18.14.orig/fs/yaffs2/yaffs_nand.c 1970-01-01 01:00:00.000000000 +0100
  8596. +++ linux-3.18.14/fs/yaffs2/yaffs_nand.c 2015-06-14 21:23:22.000000000 +0200
  8597. @@ -0,0 +1,122 @@
  8598. +/*
  8599. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  8600. + *
  8601. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8602. + * for Toby Churchill Ltd and Brightstar Engineering
  8603. + *
  8604. + * Created by Charles Manning <charles@aleph1.co.uk>
  8605. + *
  8606. + * This program is free software; you can redistribute it and/or modify
  8607. + * it under the terms of the GNU General Public License version 2 as
  8608. + * published by the Free Software Foundation.
  8609. + */
  8610. +
  8611. +#include "yaffs_nand.h"
  8612. +#include "yaffs_tagscompat.h"
  8613. +
  8614. +#include "yaffs_getblockinfo.h"
  8615. +#include "yaffs_summary.h"
  8616. +
  8617. +static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
  8618. +{
  8619. + return chunk - dev->chunk_offset;
  8620. +}
  8621. +
  8622. +int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
  8623. + u8 *buffer, struct yaffs_ext_tags *tags)
  8624. +{
  8625. + int result;
  8626. + struct yaffs_ext_tags local_tags;
  8627. + int flash_chunk = apply_chunk_offset(dev, nand_chunk);
  8628. +
  8629. + dev->n_page_reads++;
  8630. +
  8631. + /* If there are no tags provided use local tags. */
  8632. + if (!tags)
  8633. + tags = &local_tags;
  8634. +
  8635. + result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags);
  8636. + if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {
  8637. +
  8638. + struct yaffs_block_info *bi;
  8639. + bi = yaffs_get_block_info(dev,
  8640. + nand_chunk /
  8641. + dev->param.chunks_per_block);
  8642. + yaffs_handle_chunk_error(dev, bi);
  8643. + }
  8644. + return result;
  8645. +}
  8646. +
  8647. +int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
  8648. + int nand_chunk,
  8649. + const u8 *buffer, struct yaffs_ext_tags *tags)
  8650. +{
  8651. + int result;
  8652. + int flash_chunk = apply_chunk_offset(dev, nand_chunk);
  8653. +
  8654. + dev->n_page_writes++;
  8655. +
  8656. + if (!tags) {
  8657. + yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags");
  8658. + BUG();
  8659. + return YAFFS_FAIL;
  8660. + }
  8661. +
  8662. + tags->seq_number = dev->seq_number;
  8663. + tags->chunk_used = 1;
  8664. + yaffs_trace(YAFFS_TRACE_WRITE,
  8665. + "Writing chunk %d tags %d %d",
  8666. + nand_chunk, tags->obj_id, tags->chunk_id);
  8667. +
  8668. + result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk,
  8669. + buffer, tags);
  8670. +
  8671. + yaffs_summary_add(dev, tags, nand_chunk);
  8672. +
  8673. + return result;
  8674. +}
  8675. +
  8676. +int yaffs_mark_bad(struct yaffs_dev *dev, int block_no)
  8677. +{
  8678. + block_no -= dev->block_offset;
  8679. + dev->n_bad_markings++;
  8680. +
  8681. + if (dev->param.disable_bad_block_marking)
  8682. + return YAFFS_OK;
  8683. +
  8684. + return dev->tagger.mark_bad_fn(dev, block_no);
  8685. +}
  8686. +
  8687. +
  8688. +int yaffs_query_init_block_state(struct yaffs_dev *dev,
  8689. + int block_no,
  8690. + enum yaffs_block_state *state,
  8691. + u32 *seq_number)
  8692. +{
  8693. + block_no -= dev->block_offset;
  8694. + return dev->tagger.query_block_fn(dev, block_no, state, seq_number);
  8695. +}
  8696. +
  8697. +int yaffs_erase_block(struct yaffs_dev *dev, int block_no)
  8698. +{
  8699. + int result;
  8700. +
  8701. + block_no -= dev->block_offset;
  8702. + dev->n_erasures++;
  8703. + result = dev->drv.drv_erase_fn(dev, block_no);
  8704. + return result;
  8705. +}
  8706. +
  8707. +int yaffs_init_nand(struct yaffs_dev *dev)
  8708. +{
  8709. + if (dev->drv.drv_initialise_fn)
  8710. + return dev->drv.drv_initialise_fn(dev);
  8711. + return YAFFS_OK;
  8712. +}
  8713. +
  8714. +int yaffs_deinit_nand(struct yaffs_dev *dev)
  8715. +{
  8716. + if (dev->drv.drv_deinitialise_fn)
  8717. + return dev->drv.drv_deinitialise_fn(dev);
  8718. + return YAFFS_OK;
  8719. +}
  8720. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_nand.h linux-3.18.14/fs/yaffs2/yaffs_nand.h
  8721. --- linux-3.18.14.orig/fs/yaffs2/yaffs_nand.h 1970-01-01 01:00:00.000000000 +0100
  8722. +++ linux-3.18.14/fs/yaffs2/yaffs_nand.h 2015-06-14 21:23:22.000000000 +0200
  8723. @@ -0,0 +1,39 @@
  8724. +/*
  8725. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  8726. + *
  8727. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8728. + * for Toby Churchill Ltd and Brightstar Engineering
  8729. + *
  8730. + * Created by Charles Manning <charles@aleph1.co.uk>
  8731. + *
  8732. + * This program is free software; you can redistribute it and/or modify
  8733. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  8734. + * published by the Free Software Foundation.
  8735. + *
  8736. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  8737. + */
  8738. +
  8739. +#ifndef __YAFFS_NAND_H__
  8740. +#define __YAFFS_NAND_H__
  8741. +#include "yaffs_guts.h"
  8742. +
  8743. +int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
  8744. + u8 *buffer, struct yaffs_ext_tags *tags);
  8745. +
  8746. +int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
  8747. + int nand_chunk,
  8748. + const u8 *buffer, struct yaffs_ext_tags *tags);
  8749. +
  8750. +int yaffs_mark_bad(struct yaffs_dev *dev, int block_no);
  8751. +
  8752. +int yaffs_query_init_block_state(struct yaffs_dev *dev,
  8753. + int block_no,
  8754. + enum yaffs_block_state *state,
  8755. + unsigned *seq_number);
  8756. +
  8757. +int yaffs_erase_block(struct yaffs_dev *dev, int flash_block);
  8758. +
  8759. +int yaffs_init_nand(struct yaffs_dev *dev);
  8760. +int yaffs_deinit_nand(struct yaffs_dev *dev);
  8761. +
  8762. +#endif
  8763. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags1.c linux-3.18.14/fs/yaffs2/yaffs_packedtags1.c
  8764. --- linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags1.c 1970-01-01 01:00:00.000000000 +0100
  8765. +++ linux-3.18.14/fs/yaffs2/yaffs_packedtags1.c 2015-06-14 21:23:22.000000000 +0200
  8766. @@ -0,0 +1,56 @@
  8767. +/*
  8768. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  8769. + *
  8770. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8771. + * for Toby Churchill Ltd and Brightstar Engineering
  8772. + *
  8773. + * Created by Charles Manning <charles@aleph1.co.uk>
  8774. + *
  8775. + * This program is free software; you can redistribute it and/or modify
  8776. + * it under the terms of the GNU General Public License version 2 as
  8777. + * published by the Free Software Foundation.
  8778. + */
  8779. +
  8780. +#include "yaffs_packedtags1.h"
  8781. +#include "yportenv.h"
  8782. +
  8783. +static const u8 all_ff[20] = {
  8784. + 0xff, 0xff, 0xff, 0xff,
  8785. + 0xff, 0xff, 0xff, 0xff,
  8786. + 0xff, 0xff, 0xff, 0xff,
  8787. + 0xff, 0xff, 0xff, 0xff,
  8788. + 0xff, 0xff, 0xff, 0xff
  8789. +};
  8790. +
  8791. +void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
  8792. + const struct yaffs_ext_tags *t)
  8793. +{
  8794. + pt->chunk_id = t->chunk_id;
  8795. + pt->serial_number = t->serial_number;
  8796. + pt->n_bytes = t->n_bytes;
  8797. + pt->obj_id = t->obj_id;
  8798. + pt->ecc = 0;
  8799. + pt->deleted = (t->is_deleted) ? 0 : 1;
  8800. + pt->unused_stuff = 0;
  8801. + pt->should_be_ff = 0xffffffff;
  8802. +}
  8803. +
  8804. +void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
  8805. + const struct yaffs_packed_tags1 *pt)
  8806. +{
  8807. +
  8808. + if (memcmp(all_ff, pt, sizeof(struct yaffs_packed_tags1))) {
  8809. + t->block_bad = 0;
  8810. + if (pt->should_be_ff != 0xffffffff)
  8811. + t->block_bad = 1;
  8812. + t->chunk_used = 1;
  8813. + t->obj_id = pt->obj_id;
  8814. + t->chunk_id = pt->chunk_id;
  8815. + t->n_bytes = pt->n_bytes;
  8816. + t->ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  8817. + t->is_deleted = (pt->deleted) ? 0 : 1;
  8818. + t->serial_number = pt->serial_number;
  8819. + } else {
  8820. + memset(t, 0, sizeof(struct yaffs_ext_tags));
  8821. + }
  8822. +}
  8823. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags1.h linux-3.18.14/fs/yaffs2/yaffs_packedtags1.h
  8824. --- linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags1.h 1970-01-01 01:00:00.000000000 +0100
  8825. +++ linux-3.18.14/fs/yaffs2/yaffs_packedtags1.h 2015-06-14 21:23:22.000000000 +0200
  8826. @@ -0,0 +1,39 @@
  8827. +/*
  8828. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  8829. + *
  8830. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8831. + * for Toby Churchill Ltd and Brightstar Engineering
  8832. + *
  8833. + * Created by Charles Manning <charles@aleph1.co.uk>
  8834. + *
  8835. + * This program is free software; you can redistribute it and/or modify
  8836. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  8837. + * published by the Free Software Foundation.
  8838. + *
  8839. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  8840. + */
  8841. +
  8842. +/* This is used to pack YAFFS1 tags, not YAFFS2 tags. */
  8843. +
  8844. +#ifndef __YAFFS_PACKEDTAGS1_H__
  8845. +#define __YAFFS_PACKEDTAGS1_H__
  8846. +
  8847. +#include "yaffs_guts.h"
  8848. +
  8849. +struct yaffs_packed_tags1 {
  8850. + u32 chunk_id:20;
  8851. + u32 serial_number:2;
  8852. + u32 n_bytes:10;
  8853. + u32 obj_id:18;
  8854. + u32 ecc:12;
  8855. + u32 deleted:1;
  8856. + u32 unused_stuff:1;
  8857. + unsigned should_be_ff;
  8858. +
  8859. +};
  8860. +
  8861. +void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
  8862. + const struct yaffs_ext_tags *t);
  8863. +void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
  8864. + const struct yaffs_packed_tags1 *pt);
  8865. +#endif
  8866. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags2.c linux-3.18.14/fs/yaffs2/yaffs_packedtags2.c
  8867. --- linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags2.c 1970-01-01 01:00:00.000000000 +0100
  8868. +++ linux-3.18.14/fs/yaffs2/yaffs_packedtags2.c 2015-06-14 21:23:22.000000000 +0200
  8869. @@ -0,0 +1,197 @@
  8870. +/*
  8871. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  8872. + *
  8873. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8874. + * for Toby Churchill Ltd and Brightstar Engineering
  8875. + *
  8876. + * Created by Charles Manning <charles@aleph1.co.uk>
  8877. + *
  8878. + * This program is free software; you can redistribute it and/or modify
  8879. + * it under the terms of the GNU General Public License version 2 as
  8880. + * published by the Free Software Foundation.
  8881. + */
  8882. +
  8883. +#include "yaffs_packedtags2.h"
  8884. +#include "yportenv.h"
  8885. +#include "yaffs_trace.h"
  8886. +
  8887. +/* This code packs a set of extended tags into a binary structure for
  8888. + * NAND storage
  8889. + */
  8890. +
  8891. +/* Some of the information is "extra" struff which can be packed in to
  8892. + * speed scanning
  8893. + * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
  8894. + */
  8895. +
  8896. +/* Extra flags applied to chunk_id */
  8897. +
  8898. +#define EXTRA_HEADER_INFO_FLAG 0x80000000
  8899. +#define EXTRA_SHRINK_FLAG 0x40000000
  8900. +#define EXTRA_SHADOWS_FLAG 0x20000000
  8901. +#define EXTRA_SPARE_FLAGS 0x10000000
  8902. +
  8903. +#define ALL_EXTRA_FLAGS 0xf0000000
  8904. +
  8905. +/* Also, the top 4 bits of the object Id are set to the object type. */
  8906. +#define EXTRA_OBJECT_TYPE_SHIFT (28)
  8907. +#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT)
  8908. +
  8909. +static void yaffs_dump_packed_tags2_tags_only(
  8910. + const struct yaffs_packed_tags2_tags_only *ptt)
  8911. +{
  8912. + yaffs_trace(YAFFS_TRACE_MTD,
  8913. + "packed tags obj %d chunk %d byte %d seq %d",
  8914. + ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number);
  8915. +}
  8916. +
  8917. +static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt)
  8918. +{
  8919. + yaffs_dump_packed_tags2_tags_only(&pt->t);
  8920. +}
  8921. +
  8922. +static void yaffs_dump_tags2(const struct yaffs_ext_tags *t)
  8923. +{
  8924. + yaffs_trace(YAFFS_TRACE_MTD,
  8925. + "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d",
  8926. + t->ecc_result, t->block_bad, t->chunk_used, t->obj_id,
  8927. + t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number,
  8928. + t->seq_number);
  8929. +
  8930. +}
  8931. +
  8932. +static int yaffs_check_tags_extra_packable(const struct yaffs_ext_tags *t)
  8933. +{
  8934. + if (t->chunk_id != 0 || !t->extra_available)
  8935. + return 0;
  8936. +
  8937. + /* Check if the file size is too long to store */
  8938. + if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE &&
  8939. + (t->extra_file_size >> 31) != 0)
  8940. + return 0;
  8941. + return 1;
  8942. +}
  8943. +
  8944. +void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *ptt,
  8945. + const struct yaffs_ext_tags *t)
  8946. +{
  8947. + ptt->chunk_id = t->chunk_id;
  8948. + ptt->seq_number = t->seq_number;
  8949. + ptt->n_bytes = t->n_bytes;
  8950. + ptt->obj_id = t->obj_id;
  8951. +
  8952. + /* Only store extra tags for object headers.
  8953. + * If it is a file then only store if the file size is short\
  8954. + * enough to fit.
  8955. + */
  8956. + if (yaffs_check_tags_extra_packable(t)) {
  8957. + /* Store the extra header info instead */
  8958. + /* We save the parent object in the chunk_id */
  8959. + ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id;
  8960. + if (t->extra_is_shrink)
  8961. + ptt->chunk_id |= EXTRA_SHRINK_FLAG;
  8962. + if (t->extra_shadows)
  8963. + ptt->chunk_id |= EXTRA_SHADOWS_FLAG;
  8964. +
  8965. + ptt->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
  8966. + ptt->obj_id |= (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT);
  8967. +
  8968. + if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
  8969. + ptt->n_bytes = t->extra_equiv_id;
  8970. + else if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
  8971. + ptt->n_bytes = (unsigned) t->extra_file_size;
  8972. + else
  8973. + ptt->n_bytes = 0;
  8974. + }
  8975. +
  8976. + yaffs_dump_packed_tags2_tags_only(ptt);
  8977. + yaffs_dump_tags2(t);
  8978. +}
  8979. +
  8980. +void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt,
  8981. + const struct yaffs_ext_tags *t, int tags_ecc)
  8982. +{
  8983. + yaffs_pack_tags2_tags_only(&pt->t, t);
  8984. +
  8985. + if (tags_ecc)
  8986. + yaffs_ecc_calc_other((unsigned char *)&pt->t,
  8987. + sizeof(struct yaffs_packed_tags2_tags_only),
  8988. + &pt->ecc);
  8989. +}
  8990. +
  8991. +void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
  8992. + struct yaffs_packed_tags2_tags_only *ptt)
  8993. +{
  8994. + memset(t, 0, sizeof(struct yaffs_ext_tags));
  8995. +
  8996. + if (ptt->seq_number == 0xffffffff)
  8997. + return;
  8998. +
  8999. + t->block_bad = 0;
  9000. + t->chunk_used = 1;
  9001. + t->obj_id = ptt->obj_id;
  9002. + t->chunk_id = ptt->chunk_id;
  9003. + t->n_bytes = ptt->n_bytes;
  9004. + t->is_deleted = 0;
  9005. + t->serial_number = 0;
  9006. + t->seq_number = ptt->seq_number;
  9007. +
  9008. + /* Do extra header info stuff */
  9009. + if (ptt->chunk_id & EXTRA_HEADER_INFO_FLAG) {
  9010. + t->chunk_id = 0;
  9011. + t->n_bytes = 0;
  9012. +
  9013. + t->extra_available = 1;
  9014. + t->extra_parent_id = ptt->chunk_id & (~(ALL_EXTRA_FLAGS));
  9015. + t->extra_is_shrink = ptt->chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0;
  9016. + t->extra_shadows = ptt->chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0;
  9017. + t->extra_obj_type = ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT;
  9018. + t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
  9019. +
  9020. + if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
  9021. + t->extra_equiv_id = ptt->n_bytes;
  9022. + else
  9023. + t->extra_file_size = ptt->n_bytes;
  9024. + }
  9025. + yaffs_dump_packed_tags2_tags_only(ptt);
  9026. + yaffs_dump_tags2(t);
  9027. +}
  9028. +
  9029. +void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
  9030. + int tags_ecc)
  9031. +{
  9032. + enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  9033. +
  9034. + if (pt->t.seq_number != 0xffffffff && tags_ecc) {
  9035. + /* Chunk is in use and we need to do ECC */
  9036. +
  9037. + struct yaffs_ecc_other ecc;
  9038. + int result;
  9039. + yaffs_ecc_calc_other((unsigned char *)&pt->t,
  9040. + sizeof(struct yaffs_packed_tags2_tags_only),
  9041. + &ecc);
  9042. + result =
  9043. + yaffs_ecc_correct_other((unsigned char *)&pt->t,
  9044. + sizeof(struct yaffs_packed_tags2_tags_only),
  9045. + &pt->ecc, &ecc);
  9046. + switch (result) {
  9047. + case 0:
  9048. + ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  9049. + break;
  9050. + case 1:
  9051. + ecc_result = YAFFS_ECC_RESULT_FIXED;
  9052. + break;
  9053. + case -1:
  9054. + ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  9055. + break;
  9056. + default:
  9057. + ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
  9058. + }
  9059. + }
  9060. + yaffs_unpack_tags2_tags_only(t, &pt->t);
  9061. +
  9062. + t->ecc_result = ecc_result;
  9063. +
  9064. + yaffs_dump_packed_tags2(pt);
  9065. + yaffs_dump_tags2(t);
  9066. +}
  9067. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags2.h linux-3.18.14/fs/yaffs2/yaffs_packedtags2.h
  9068. --- linux-3.18.14.orig/fs/yaffs2/yaffs_packedtags2.h 1970-01-01 01:00:00.000000000 +0100
  9069. +++ linux-3.18.14/fs/yaffs2/yaffs_packedtags2.h 2015-06-14 21:23:22.000000000 +0200
  9070. @@ -0,0 +1,47 @@
  9071. +/*
  9072. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9073. + *
  9074. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9075. + * for Toby Churchill Ltd and Brightstar Engineering
  9076. + *
  9077. + * Created by Charles Manning <charles@aleph1.co.uk>
  9078. + *
  9079. + * This program is free software; you can redistribute it and/or modify
  9080. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9081. + * published by the Free Software Foundation.
  9082. + *
  9083. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9084. + */
  9085. +
  9086. +/* This is used to pack YAFFS2 tags, not YAFFS1tags. */
  9087. +
  9088. +#ifndef __YAFFS_PACKEDTAGS2_H__
  9089. +#define __YAFFS_PACKEDTAGS2_H__
  9090. +
  9091. +#include "yaffs_guts.h"
  9092. +#include "yaffs_ecc.h"
  9093. +
  9094. +struct yaffs_packed_tags2_tags_only {
  9095. + unsigned seq_number;
  9096. + unsigned obj_id;
  9097. + unsigned chunk_id;
  9098. + unsigned n_bytes;
  9099. +};
  9100. +
  9101. +struct yaffs_packed_tags2 {
  9102. + struct yaffs_packed_tags2_tags_only t;
  9103. + struct yaffs_ecc_other ecc;
  9104. +};
  9105. +
  9106. +/* Full packed tags with ECC, used for oob tags */
  9107. +void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt,
  9108. + const struct yaffs_ext_tags *t, int tags_ecc);
  9109. +void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
  9110. + int tags_ecc);
  9111. +
  9112. +/* Only the tags part (no ECC for use with inband tags */
  9113. +void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *pt,
  9114. + const struct yaffs_ext_tags *t);
  9115. +void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
  9116. + struct yaffs_packed_tags2_tags_only *pt);
  9117. +#endif
  9118. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_summary.c linux-3.18.14/fs/yaffs2/yaffs_summary.c
  9119. --- linux-3.18.14.orig/fs/yaffs2/yaffs_summary.c 1970-01-01 01:00:00.000000000 +0100
  9120. +++ linux-3.18.14/fs/yaffs2/yaffs_summary.c 2015-06-14 21:23:22.000000000 +0200
  9121. @@ -0,0 +1,312 @@
  9122. +/*
  9123. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9124. + *
  9125. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9126. + * for Toby Churchill Ltd and Brightstar Engineering
  9127. + *
  9128. + * Created by Charles Manning <charles@aleph1.co.uk>
  9129. + *
  9130. + * This program is free software; you can redistribute it and/or modify
  9131. + * it under the terms of the GNU General Public License version 2 as
  9132. + * published by the Free Software Foundation.
  9133. + */
  9134. +
  9135. +/* Summaries write the useful part of the tags for the chunks in a block into an
  9136. + * an array which is written to the last n chunks of the block.
  9137. + * Reading the summaries gives all the tags for the block in one read. Much
  9138. + * faster.
  9139. + *
  9140. + * Chunks holding summaries are marked with tags making it look like
  9141. + * they are part of a fake file.
  9142. + *
  9143. + * The summary could also be used during gc.
  9144. + *
  9145. + */
  9146. +
  9147. +#include "yaffs_summary.h"
  9148. +#include "yaffs_packedtags2.h"
  9149. +#include "yaffs_nand.h"
  9150. +#include "yaffs_getblockinfo.h"
  9151. +#include "yaffs_bitmap.h"
  9152. +
  9153. +/*
  9154. + * The summary is built up in an array of summary tags.
  9155. + * This gets written to the last one or two (maybe more) chunks in a block.
  9156. + * A summary header is written as the first part of each chunk of summary data.
  9157. + * The summary header must match or the summary is rejected.
  9158. + */
  9159. +
  9160. +/* Summary tags don't need the sequence number because that is redundant. */
  9161. +struct yaffs_summary_tags {
  9162. + unsigned obj_id;
  9163. + unsigned chunk_id;
  9164. + unsigned n_bytes;
  9165. +};
  9166. +
  9167. +/* Summary header */
  9168. +struct yaffs_summary_header {
  9169. + unsigned version; /* Must match current version */
  9170. + unsigned block; /* Must be this block */
  9171. + unsigned seq; /* Must be this sequence number */
  9172. + unsigned sum; /* Just add up all the bytes in the tags */
  9173. +};
  9174. +
  9175. +
  9176. +static void yaffs_summary_clear(struct yaffs_dev *dev)
  9177. +{
  9178. + if (!dev->sum_tags)
  9179. + return;
  9180. + memset(dev->sum_tags, 0, dev->chunks_per_summary *
  9181. + sizeof(struct yaffs_summary_tags));
  9182. +}
  9183. +
  9184. +
  9185. +void yaffs_summary_deinit(struct yaffs_dev *dev)
  9186. +{
  9187. + kfree(dev->sum_tags);
  9188. + dev->sum_tags = NULL;
  9189. + kfree(dev->gc_sum_tags);
  9190. + dev->gc_sum_tags = NULL;
  9191. + dev->chunks_per_summary = 0;
  9192. +}
  9193. +
  9194. +int yaffs_summary_init(struct yaffs_dev *dev)
  9195. +{
  9196. + int sum_bytes;
  9197. + int chunks_used; /* Number of chunks used by summary */
  9198. + int sum_tags_bytes;
  9199. +
  9200. + sum_bytes = dev->param.chunks_per_block *
  9201. + sizeof(struct yaffs_summary_tags);
  9202. +
  9203. + chunks_used = (sum_bytes + dev->data_bytes_per_chunk - 1)/
  9204. + (dev->data_bytes_per_chunk -
  9205. + sizeof(struct yaffs_summary_header));
  9206. +
  9207. + dev->chunks_per_summary = dev->param.chunks_per_block - chunks_used;
  9208. + sum_tags_bytes = sizeof(struct yaffs_summary_tags) *
  9209. + dev->chunks_per_summary;
  9210. + dev->sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS);
  9211. + dev->gc_sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS);
  9212. + if (!dev->sum_tags || !dev->gc_sum_tags) {
  9213. + yaffs_summary_deinit(dev);
  9214. + return YAFFS_FAIL;
  9215. + }
  9216. +
  9217. + yaffs_summary_clear(dev);
  9218. +
  9219. + return YAFFS_OK;
  9220. +}
  9221. +
  9222. +static unsigned yaffs_summary_sum(struct yaffs_dev *dev)
  9223. +{
  9224. + u8 *sum_buffer = (u8 *)dev->sum_tags;
  9225. + int i;
  9226. + unsigned sum = 0;
  9227. +
  9228. + i = sizeof(struct yaffs_summary_tags) *
  9229. + dev->chunks_per_summary;
  9230. + while (i > 0) {
  9231. + sum += *sum_buffer;
  9232. + sum_buffer++;
  9233. + i--;
  9234. + }
  9235. +
  9236. + return sum;
  9237. +}
  9238. +
  9239. +static int yaffs_summary_write(struct yaffs_dev *dev, int blk)
  9240. +{
  9241. + struct yaffs_ext_tags tags;
  9242. + u8 *buffer;
  9243. + u8 *sum_buffer = (u8 *)dev->sum_tags;
  9244. + int n_bytes;
  9245. + int chunk_in_nand;
  9246. + int chunk_in_block;
  9247. + int result;
  9248. + int this_tx;
  9249. + struct yaffs_summary_header hdr;
  9250. + int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr);
  9251. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
  9252. +
  9253. + buffer = yaffs_get_temp_buffer(dev);
  9254. + n_bytes = sizeof(struct yaffs_summary_tags) *
  9255. + dev->chunks_per_summary;
  9256. + memset(&tags, 0, sizeof(struct yaffs_ext_tags));
  9257. + tags.obj_id = YAFFS_OBJECTID_SUMMARY;
  9258. + tags.chunk_id = 1;
  9259. + chunk_in_block = dev->chunks_per_summary;
  9260. + chunk_in_nand = dev->alloc_block * dev->param.chunks_per_block +
  9261. + dev->chunks_per_summary;
  9262. + hdr.version = YAFFS_SUMMARY_VERSION;
  9263. + hdr.block = blk;
  9264. + hdr.seq = bi->seq_number;
  9265. + hdr.sum = yaffs_summary_sum(dev);
  9266. +
  9267. + do {
  9268. + this_tx = n_bytes;
  9269. + if (this_tx > sum_bytes_per_chunk)
  9270. + this_tx = sum_bytes_per_chunk;
  9271. + memcpy(buffer, &hdr, sizeof(hdr));
  9272. + memcpy(buffer + sizeof(hdr), sum_buffer, this_tx);
  9273. + tags.n_bytes = this_tx + sizeof(hdr);
  9274. + result = yaffs_wr_chunk_tags_nand(dev, chunk_in_nand,
  9275. + buffer, &tags);
  9276. +
  9277. + if (result != YAFFS_OK)
  9278. + break;
  9279. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  9280. + bi->pages_in_use++;
  9281. + dev->n_free_chunks--;
  9282. +
  9283. + n_bytes -= this_tx;
  9284. + sum_buffer += this_tx;
  9285. + chunk_in_nand++;
  9286. + chunk_in_block++;
  9287. + tags.chunk_id++;
  9288. + } while (result == YAFFS_OK && n_bytes > 0);
  9289. + yaffs_release_temp_buffer(dev, buffer);
  9290. +
  9291. +
  9292. + if (result == YAFFS_OK)
  9293. + bi->has_summary = 1;
  9294. +
  9295. +
  9296. + return result;
  9297. +}
  9298. +
  9299. +int yaffs_summary_read(struct yaffs_dev *dev,
  9300. + struct yaffs_summary_tags *st,
  9301. + int blk)
  9302. +{
  9303. + struct yaffs_ext_tags tags;
  9304. + u8 *buffer;
  9305. + u8 *sum_buffer = (u8 *)st;
  9306. + int n_bytes;
  9307. + int chunk_id;
  9308. + int chunk_in_nand;
  9309. + int chunk_in_block;
  9310. + int result;
  9311. + int this_tx;
  9312. + struct yaffs_summary_header hdr;
  9313. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
  9314. + int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr);
  9315. + int sum_tags_bytes;
  9316. +
  9317. + sum_tags_bytes = sizeof(struct yaffs_summary_tags) *
  9318. + dev->chunks_per_summary;
  9319. + buffer = yaffs_get_temp_buffer(dev);
  9320. + n_bytes = sizeof(struct yaffs_summary_tags) * dev->chunks_per_summary;
  9321. + chunk_in_block = dev->chunks_per_summary;
  9322. + chunk_in_nand = blk * dev->param.chunks_per_block +
  9323. + dev->chunks_per_summary;
  9324. + chunk_id = 1;
  9325. + do {
  9326. + this_tx = n_bytes;
  9327. + if (this_tx > sum_bytes_per_chunk)
  9328. + this_tx = sum_bytes_per_chunk;
  9329. + result = yaffs_rd_chunk_tags_nand(dev, chunk_in_nand,
  9330. + buffer, &tags);
  9331. +
  9332. + if (tags.chunk_id != chunk_id ||
  9333. + tags.obj_id != YAFFS_OBJECTID_SUMMARY ||
  9334. + tags.chunk_used == 0 ||
  9335. + tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
  9336. + tags.n_bytes != (this_tx + sizeof(hdr)))
  9337. + result = YAFFS_FAIL;
  9338. + if (result != YAFFS_OK)
  9339. + break;
  9340. +
  9341. + if (st == dev->sum_tags) {
  9342. + /* If we're scanning then update the block info */
  9343. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  9344. + bi->pages_in_use++;
  9345. + }
  9346. + memcpy(&hdr, buffer, sizeof(hdr));
  9347. + memcpy(sum_buffer, buffer + sizeof(hdr), this_tx);
  9348. + n_bytes -= this_tx;
  9349. + sum_buffer += this_tx;
  9350. + chunk_in_nand++;
  9351. + chunk_in_block++;
  9352. + chunk_id++;
  9353. + } while (result == YAFFS_OK && n_bytes > 0);
  9354. + yaffs_release_temp_buffer(dev, buffer);
  9355. +
  9356. + if (result == YAFFS_OK) {
  9357. + /* Verify header */
  9358. + if (hdr.version != YAFFS_SUMMARY_VERSION ||
  9359. + hdr.seq != bi->seq_number ||
  9360. + hdr.sum != yaffs_summary_sum(dev))
  9361. + result = YAFFS_FAIL;
  9362. + }
  9363. +
  9364. + if (st == dev->sum_tags && result == YAFFS_OK)
  9365. + bi->has_summary = 1;
  9366. +
  9367. + return result;
  9368. +}
  9369. +
  9370. +int yaffs_summary_add(struct yaffs_dev *dev,
  9371. + struct yaffs_ext_tags *tags,
  9372. + int chunk_in_nand)
  9373. +{
  9374. + struct yaffs_packed_tags2_tags_only tags_only;
  9375. + struct yaffs_summary_tags *sum_tags;
  9376. + int block_in_nand = chunk_in_nand / dev->param.chunks_per_block;
  9377. + int chunk_in_block = chunk_in_nand % dev->param.chunks_per_block;
  9378. +
  9379. + if (!dev->sum_tags)
  9380. + return YAFFS_OK;
  9381. +
  9382. + if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) {
  9383. + yaffs_pack_tags2_tags_only(&tags_only, tags);
  9384. + sum_tags = &dev->sum_tags[chunk_in_block];
  9385. + sum_tags->chunk_id = tags_only.chunk_id;
  9386. + sum_tags->n_bytes = tags_only.n_bytes;
  9387. + sum_tags->obj_id = tags_only.obj_id;
  9388. +
  9389. + if (chunk_in_block == dev->chunks_per_summary - 1) {
  9390. + /* Time to write out the summary */
  9391. + yaffs_summary_write(dev, block_in_nand);
  9392. + yaffs_summary_clear(dev);
  9393. + yaffs_skip_rest_of_block(dev);
  9394. + }
  9395. + }
  9396. + return YAFFS_OK;
  9397. +}
  9398. +
  9399. +int yaffs_summary_fetch(struct yaffs_dev *dev,
  9400. + struct yaffs_ext_tags *tags,
  9401. + int chunk_in_block)
  9402. +{
  9403. + struct yaffs_packed_tags2_tags_only tags_only;
  9404. + struct yaffs_summary_tags *sum_tags;
  9405. + if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) {
  9406. + sum_tags = &dev->sum_tags[chunk_in_block];
  9407. + tags_only.chunk_id = sum_tags->chunk_id;
  9408. + tags_only.n_bytes = sum_tags->n_bytes;
  9409. + tags_only.obj_id = sum_tags->obj_id;
  9410. + yaffs_unpack_tags2_tags_only(tags, &tags_only);
  9411. + return YAFFS_OK;
  9412. + }
  9413. + return YAFFS_FAIL;
  9414. +}
  9415. +
  9416. +void yaffs_summary_gc(struct yaffs_dev *dev, int blk)
  9417. +{
  9418. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
  9419. + int i;
  9420. +
  9421. + if (!bi->has_summary)
  9422. + return;
  9423. +
  9424. + for (i = dev->chunks_per_summary;
  9425. + i < dev->param.chunks_per_block;
  9426. + i++) {
  9427. + if (yaffs_check_chunk_bit(dev, blk, i)) {
  9428. + yaffs_clear_chunk_bit(dev, blk, i);
  9429. + bi->pages_in_use--;
  9430. + dev->n_free_chunks++;
  9431. + }
  9432. + }
  9433. +}
  9434. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_summary.h linux-3.18.14/fs/yaffs2/yaffs_summary.h
  9435. --- linux-3.18.14.orig/fs/yaffs2/yaffs_summary.h 1970-01-01 01:00:00.000000000 +0100
  9436. +++ linux-3.18.14/fs/yaffs2/yaffs_summary.h 2015-06-14 21:23:22.000000000 +0200
  9437. @@ -0,0 +1,37 @@
  9438. +/*
  9439. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9440. + *
  9441. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9442. + * for Toby Churchill Ltd and Brightstar Engineering
  9443. + *
  9444. + * Created by Charles Manning <charles@aleph1.co.uk>
  9445. + *
  9446. + * This program is free software; you can redistribute it and/or modify
  9447. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9448. + * published by the Free Software Foundation.
  9449. + *
  9450. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9451. + */
  9452. +
  9453. +#ifndef __YAFFS_SUMMARY_H__
  9454. +#define __YAFFS_SUMMARY_H__
  9455. +
  9456. +#include "yaffs_packedtags2.h"
  9457. +
  9458. +
  9459. +int yaffs_summary_init(struct yaffs_dev *dev);
  9460. +void yaffs_summary_deinit(struct yaffs_dev *dev);
  9461. +
  9462. +int yaffs_summary_add(struct yaffs_dev *dev,
  9463. + struct yaffs_ext_tags *tags,
  9464. + int chunk_in_block);
  9465. +int yaffs_summary_fetch(struct yaffs_dev *dev,
  9466. + struct yaffs_ext_tags *tags,
  9467. + int chunk_in_block);
  9468. +int yaffs_summary_read(struct yaffs_dev *dev,
  9469. + struct yaffs_summary_tags *st,
  9470. + int blk);
  9471. +void yaffs_summary_gc(struct yaffs_dev *dev, int blk);
  9472. +
  9473. +
  9474. +#endif
  9475. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_tagscompat.c linux-3.18.14/fs/yaffs2/yaffs_tagscompat.c
  9476. --- linux-3.18.14.orig/fs/yaffs2/yaffs_tagscompat.c 1970-01-01 01:00:00.000000000 +0100
  9477. +++ linux-3.18.14/fs/yaffs2/yaffs_tagscompat.c 2015-06-14 21:23:22.000000000 +0200
  9478. @@ -0,0 +1,381 @@
  9479. +/*
  9480. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9481. + *
  9482. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9483. + * for Toby Churchill Ltd and Brightstar Engineering
  9484. + *
  9485. + * Created by Charles Manning <charles@aleph1.co.uk>
  9486. + *
  9487. + * This program is free software; you can redistribute it and/or modify
  9488. + * it under the terms of the GNU General Public License version 2 as
  9489. + * published by the Free Software Foundation.
  9490. + */
  9491. +
  9492. +#include "yaffs_guts.h"
  9493. +#include "yaffs_tagscompat.h"
  9494. +#include "yaffs_ecc.h"
  9495. +#include "yaffs_getblockinfo.h"
  9496. +#include "yaffs_trace.h"
  9497. +
  9498. +static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
  9499. +
  9500. +
  9501. +/********** Tags ECC calculations *********/
  9502. +
  9503. +
  9504. +void yaffs_calc_tags_ecc(struct yaffs_tags *tags)
  9505. +{
  9506. + /* Calculate an ecc */
  9507. + unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes;
  9508. + unsigned i, j;
  9509. + unsigned ecc = 0;
  9510. + unsigned bit = 0;
  9511. +
  9512. + tags->ecc = 0;
  9513. +
  9514. + for (i = 0; i < 8; i++) {
  9515. + for (j = 1; j & 0xff; j <<= 1) {
  9516. + bit++;
  9517. + if (b[i] & j)
  9518. + ecc ^= bit;
  9519. + }
  9520. + }
  9521. + tags->ecc = ecc;
  9522. +}
  9523. +
  9524. +int yaffs_check_tags_ecc(struct yaffs_tags *tags)
  9525. +{
  9526. + unsigned ecc = tags->ecc;
  9527. +
  9528. + yaffs_calc_tags_ecc(tags);
  9529. +
  9530. + ecc ^= tags->ecc;
  9531. +
  9532. + if (ecc && ecc <= 64) {
  9533. + /* TODO: Handle the failure better. Retire? */
  9534. + unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes;
  9535. +
  9536. + ecc--;
  9537. +
  9538. + b[ecc / 8] ^= (1 << (ecc & 7));
  9539. +
  9540. + /* Now recvalc the ecc */
  9541. + yaffs_calc_tags_ecc(tags);
  9542. +
  9543. + return 1; /* recovered error */
  9544. + } else if (ecc) {
  9545. + /* Wierd ecc failure value */
  9546. + /* TODO Need to do somethiong here */
  9547. + return -1; /* unrecovered error */
  9548. + }
  9549. + return 0;
  9550. +}
  9551. +
  9552. +/********** Tags **********/
  9553. +
  9554. +static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
  9555. + struct yaffs_tags *tags_ptr)
  9556. +{
  9557. + union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
  9558. +
  9559. + yaffs_calc_tags_ecc(tags_ptr);
  9560. +
  9561. + spare_ptr->tb0 = tu->as_bytes[0];
  9562. + spare_ptr->tb1 = tu->as_bytes[1];
  9563. + spare_ptr->tb2 = tu->as_bytes[2];
  9564. + spare_ptr->tb3 = tu->as_bytes[3];
  9565. + spare_ptr->tb4 = tu->as_bytes[4];
  9566. + spare_ptr->tb5 = tu->as_bytes[5];
  9567. + spare_ptr->tb6 = tu->as_bytes[6];
  9568. + spare_ptr->tb7 = tu->as_bytes[7];
  9569. +}
  9570. +
  9571. +static void yaffs_get_tags_from_spare(struct yaffs_dev *dev,
  9572. + struct yaffs_spare *spare_ptr,
  9573. + struct yaffs_tags *tags_ptr)
  9574. +{
  9575. + union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
  9576. + int result;
  9577. +
  9578. + tu->as_bytes[0] = spare_ptr->tb0;
  9579. + tu->as_bytes[1] = spare_ptr->tb1;
  9580. + tu->as_bytes[2] = spare_ptr->tb2;
  9581. + tu->as_bytes[3] = spare_ptr->tb3;
  9582. + tu->as_bytes[4] = spare_ptr->tb4;
  9583. + tu->as_bytes[5] = spare_ptr->tb5;
  9584. + tu->as_bytes[6] = spare_ptr->tb6;
  9585. + tu->as_bytes[7] = spare_ptr->tb7;
  9586. +
  9587. + result = yaffs_check_tags_ecc(tags_ptr);
  9588. + if (result > 0)
  9589. + dev->n_tags_ecc_fixed++;
  9590. + else if (result < 0)
  9591. + dev->n_tags_ecc_unfixed++;
  9592. +}
  9593. +
  9594. +static void yaffs_spare_init(struct yaffs_spare *spare)
  9595. +{
  9596. + memset(spare, 0xff, sizeof(struct yaffs_spare));
  9597. +}
  9598. +
  9599. +static int yaffs_wr_nand(struct yaffs_dev *dev,
  9600. + int nand_chunk, const u8 *data,
  9601. + struct yaffs_spare *spare)
  9602. +{
  9603. + int data_size = dev->data_bytes_per_chunk;
  9604. +
  9605. + return dev->drv.drv_write_chunk_fn(dev, nand_chunk,
  9606. + data, data_size,
  9607. + (u8 *) spare, sizeof(*spare));
  9608. +}
  9609. +
  9610. +static int yaffs_rd_chunk_nand(struct yaffs_dev *dev,
  9611. + int nand_chunk,
  9612. + u8 *data,
  9613. + struct yaffs_spare *spare,
  9614. + enum yaffs_ecc_result *ecc_result,
  9615. + int correct_errors)
  9616. +{
  9617. + int ret_val;
  9618. + struct yaffs_spare local_spare;
  9619. + int data_size;
  9620. + int spare_size;
  9621. + int ecc_result1, ecc_result2;
  9622. + u8 calc_ecc[3];
  9623. +
  9624. + if (!spare) {
  9625. + /* If we don't have a real spare, then we use a local one. */
  9626. + /* Need this for the calculation of the ecc */
  9627. + spare = &local_spare;
  9628. + }
  9629. + data_size = dev->data_bytes_per_chunk;
  9630. + spare_size = sizeof(struct yaffs_spare);
  9631. +
  9632. + if (dev->param.use_nand_ecc)
  9633. + return dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  9634. + data, data_size,
  9635. + (u8 *) spare, spare_size,
  9636. + ecc_result);
  9637. +
  9638. +
  9639. + /* Handle the ECC at this level. */
  9640. +
  9641. + ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  9642. + data, data_size,
  9643. + (u8 *)spare, spare_size,
  9644. + NULL);
  9645. + if (!data || !correct_errors)
  9646. + return ret_val;
  9647. +
  9648. + /* Do ECC correction if needed. */
  9649. + yaffs_ecc_calc(data, calc_ecc);
  9650. + ecc_result1 = yaffs_ecc_correct(data, spare->ecc1, calc_ecc);
  9651. + yaffs_ecc_calc(&data[256], calc_ecc);
  9652. + ecc_result2 = yaffs_ecc_correct(&data[256], spare->ecc2, calc_ecc);
  9653. +
  9654. + if (ecc_result1 > 0) {
  9655. + yaffs_trace(YAFFS_TRACE_ERROR,
  9656. + "**>>yaffs ecc error fix performed on chunk %d:0",
  9657. + nand_chunk);
  9658. + dev->n_ecc_fixed++;
  9659. + } else if (ecc_result1 < 0) {
  9660. + yaffs_trace(YAFFS_TRACE_ERROR,
  9661. + "**>>yaffs ecc error unfixed on chunk %d:0",
  9662. + nand_chunk);
  9663. + dev->n_ecc_unfixed++;
  9664. + }
  9665. +
  9666. + if (ecc_result2 > 0) {
  9667. + yaffs_trace(YAFFS_TRACE_ERROR,
  9668. + "**>>yaffs ecc error fix performed on chunk %d:1",
  9669. + nand_chunk);
  9670. + dev->n_ecc_fixed++;
  9671. + } else if (ecc_result2 < 0) {
  9672. + yaffs_trace(YAFFS_TRACE_ERROR,
  9673. + "**>>yaffs ecc error unfixed on chunk %d:1",
  9674. + nand_chunk);
  9675. + dev->n_ecc_unfixed++;
  9676. + }
  9677. +
  9678. + if (ecc_result1 || ecc_result2) {
  9679. + /* We had a data problem on this page */
  9680. + yaffs_handle_rd_data_error(dev, nand_chunk);
  9681. + }
  9682. +
  9683. + if (ecc_result1 < 0 || ecc_result2 < 0)
  9684. + *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  9685. + else if (ecc_result1 > 0 || ecc_result2 > 0)
  9686. + *ecc_result = YAFFS_ECC_RESULT_FIXED;
  9687. + else
  9688. + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  9689. +
  9690. + return ret_val;
  9691. +}
  9692. +
  9693. +/*
  9694. + * Functions for robustisizing
  9695. + */
  9696. +
  9697. +static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk)
  9698. +{
  9699. + int flash_block = nand_chunk / dev->param.chunks_per_block;
  9700. +
  9701. + /* Mark the block for retirement */
  9702. + yaffs_get_block_info(dev, flash_block + dev->block_offset)->
  9703. + needs_retiring = 1;
  9704. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  9705. + "**>>Block %d marked for retirement",
  9706. + flash_block);
  9707. +
  9708. + /* TODO:
  9709. + * Just do a garbage collection on the affected block
  9710. + * then retire the block
  9711. + * NB recursion
  9712. + */
  9713. +}
  9714. +
  9715. +static int yaffs_tags_compat_wr(struct yaffs_dev *dev,
  9716. + int nand_chunk,
  9717. + const u8 *data, const struct yaffs_ext_tags *ext_tags)
  9718. +{
  9719. + struct yaffs_spare spare;
  9720. + struct yaffs_tags tags;
  9721. +
  9722. + yaffs_spare_init(&spare);
  9723. +
  9724. + if (ext_tags->is_deleted)
  9725. + spare.page_status = 0;
  9726. + else {
  9727. + tags.obj_id = ext_tags->obj_id;
  9728. + tags.chunk_id = ext_tags->chunk_id;
  9729. +
  9730. + tags.n_bytes_lsb = ext_tags->n_bytes & (1024 - 1);
  9731. +
  9732. + if (dev->data_bytes_per_chunk >= 1024)
  9733. + tags.n_bytes_msb = (ext_tags->n_bytes >> 10) & 3;
  9734. + else
  9735. + tags.n_bytes_msb = 3;
  9736. +
  9737. + tags.serial_number = ext_tags->serial_number;
  9738. +
  9739. + if (!dev->param.use_nand_ecc && data) {
  9740. + yaffs_ecc_calc(data, spare.ecc1);
  9741. + yaffs_ecc_calc(&data[256], spare.ecc2);
  9742. + }
  9743. +
  9744. + yaffs_load_tags_to_spare(&spare, &tags);
  9745. + }
  9746. + return yaffs_wr_nand(dev, nand_chunk, data, &spare);
  9747. +}
  9748. +
  9749. +static int yaffs_tags_compat_rd(struct yaffs_dev *dev,
  9750. + int nand_chunk,
  9751. + u8 *data, struct yaffs_ext_tags *ext_tags)
  9752. +{
  9753. + struct yaffs_spare spare;
  9754. + struct yaffs_tags tags;
  9755. + enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
  9756. + static struct yaffs_spare spare_ff;
  9757. + static int init;
  9758. + int deleted;
  9759. +
  9760. + if (!init) {
  9761. + memset(&spare_ff, 0xff, sizeof(spare_ff));
  9762. + init = 1;
  9763. + }
  9764. +
  9765. + if (!yaffs_rd_chunk_nand(dev, nand_chunk,
  9766. + data, &spare, &ecc_result, 1))
  9767. + return YAFFS_FAIL;
  9768. +
  9769. + /* ext_tags may be NULL */
  9770. + if (!ext_tags)
  9771. + return YAFFS_OK;
  9772. +
  9773. + deleted = (hweight8(spare.page_status) < 7) ? 1 : 0;
  9774. +
  9775. + ext_tags->is_deleted = deleted;
  9776. + ext_tags->ecc_result = ecc_result;
  9777. + ext_tags->block_bad = 0; /* We're reading it */
  9778. + /* therefore it is not a bad block */
  9779. + ext_tags->chunk_used =
  9780. + memcmp(&spare_ff, &spare, sizeof(spare_ff)) ? 1 : 0;
  9781. +
  9782. + if (ext_tags->chunk_used) {
  9783. + yaffs_get_tags_from_spare(dev, &spare, &tags);
  9784. + ext_tags->obj_id = tags.obj_id;
  9785. + ext_tags->chunk_id = tags.chunk_id;
  9786. + ext_tags->n_bytes = tags.n_bytes_lsb;
  9787. +
  9788. + if (dev->data_bytes_per_chunk >= 1024)
  9789. + ext_tags->n_bytes |=
  9790. + (((unsigned)tags.n_bytes_msb) << 10);
  9791. +
  9792. + ext_tags->serial_number = tags.serial_number;
  9793. + }
  9794. +
  9795. + return YAFFS_OK;
  9796. +}
  9797. +
  9798. +static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block)
  9799. +{
  9800. + struct yaffs_spare spare;
  9801. +
  9802. + memset(&spare, 0xff, sizeof(struct yaffs_spare));
  9803. +
  9804. + spare.block_status = 'Y';
  9805. +
  9806. + yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block, NULL,
  9807. + &spare);
  9808. + yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block + 1,
  9809. + NULL, &spare);
  9810. +
  9811. + return YAFFS_OK;
  9812. +}
  9813. +
  9814. +static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
  9815. + int block_no,
  9816. + enum yaffs_block_state *state,
  9817. + u32 *seq_number)
  9818. +{
  9819. + struct yaffs_spare spare0, spare1;
  9820. + static struct yaffs_spare spare_ff;
  9821. + static int init;
  9822. + enum yaffs_ecc_result dummy;
  9823. +
  9824. + if (!init) {
  9825. + memset(&spare_ff, 0xff, sizeof(spare_ff));
  9826. + init = 1;
  9827. + }
  9828. +
  9829. + *seq_number = 0;
  9830. +
  9831. + /* Look for bad block markers in the first two chunks */
  9832. + yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block,
  9833. + NULL, &spare0, &dummy, 0);
  9834. + yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1,
  9835. + NULL, &spare1, &dummy, 0);
  9836. +
  9837. + if (hweight8(spare0.block_status & spare1.block_status) < 7)
  9838. + *state = YAFFS_BLOCK_STATE_DEAD;
  9839. + else if (memcmp(&spare_ff, &spare0, sizeof(spare_ff)) == 0)
  9840. + *state = YAFFS_BLOCK_STATE_EMPTY;
  9841. + else
  9842. + *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
  9843. +
  9844. + return YAFFS_OK;
  9845. +}
  9846. +
  9847. +void yaffs_tags_compat_install(struct yaffs_dev *dev)
  9848. +{
  9849. + if(dev->param.is_yaffs2)
  9850. + return;
  9851. + if(!dev->tagger.write_chunk_tags_fn)
  9852. + dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr;
  9853. + if(!dev->tagger.read_chunk_tags_fn)
  9854. + dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd;
  9855. + if(!dev->tagger.query_block_fn)
  9856. + dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
  9857. + if(!dev->tagger.mark_bad_fn)
  9858. + dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
  9859. +}
  9860. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_tagscompat.h linux-3.18.14/fs/yaffs2/yaffs_tagscompat.h
  9861. --- linux-3.18.14.orig/fs/yaffs2/yaffs_tagscompat.h 1970-01-01 01:00:00.000000000 +0100
  9862. +++ linux-3.18.14/fs/yaffs2/yaffs_tagscompat.h 2015-06-14 21:23:22.000000000 +0200
  9863. @@ -0,0 +1,44 @@
  9864. +/*
  9865. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9866. + *
  9867. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9868. + * for Toby Churchill Ltd and Brightstar Engineering
  9869. + *
  9870. + * Created by Charles Manning <charles@aleph1.co.uk>
  9871. + *
  9872. + * This program is free software; you can redistribute it and/or modify
  9873. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9874. + * published by the Free Software Foundation.
  9875. + *
  9876. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9877. + */
  9878. +
  9879. +#ifndef __YAFFS_TAGSCOMPAT_H__
  9880. +#define __YAFFS_TAGSCOMPAT_H__
  9881. +
  9882. +
  9883. +#include "yaffs_guts.h"
  9884. +
  9885. +#if 0
  9886. +
  9887. +
  9888. +int yaffs_tags_compat_wr(struct yaffs_dev *dev,
  9889. + int nand_chunk,
  9890. + const u8 *data, const struct yaffs_ext_tags *tags);
  9891. +int yaffs_tags_compat_rd(struct yaffs_dev *dev,
  9892. + int nand_chunk,
  9893. + u8 *data, struct yaffs_ext_tags *tags);
  9894. +int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no);
  9895. +int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
  9896. + int block_no,
  9897. + enum yaffs_block_state *state,
  9898. + u32 *seq_number);
  9899. +
  9900. +#endif
  9901. +
  9902. +
  9903. +void yaffs_tags_compat_install(struct yaffs_dev *dev);
  9904. +void yaffs_calc_tags_ecc(struct yaffs_tags *tags);
  9905. +int yaffs_check_tags_ecc(struct yaffs_tags *tags);
  9906. +
  9907. +#endif
  9908. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_tagsmarshall.c linux-3.18.14/fs/yaffs2/yaffs_tagsmarshall.c
  9909. --- linux-3.18.14.orig/fs/yaffs2/yaffs_tagsmarshall.c 1970-01-01 01:00:00.000000000 +0100
  9910. +++ linux-3.18.14/fs/yaffs2/yaffs_tagsmarshall.c 2015-06-14 21:23:22.000000000 +0200
  9911. @@ -0,0 +1,199 @@
  9912. +/*
  9913. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9914. + *
  9915. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9916. + * for Toby Churchill Ltd and Brightstar Engineering
  9917. + *
  9918. + * Created by Charles Manning <charles@aleph1.co.uk>
  9919. + *
  9920. + * This program is free software; you can redistribute it and/or modify
  9921. + * it under the terms of the GNU General Public License version 2 as
  9922. + * published by the Free Software Foundation.
  9923. + */
  9924. +
  9925. +#include "yaffs_guts.h"
  9926. +#include "yaffs_trace.h"
  9927. +#include "yaffs_packedtags2.h"
  9928. +
  9929. +static int yaffs_tags_marshall_write(struct yaffs_dev *dev,
  9930. + int nand_chunk, const u8 *data,
  9931. + const struct yaffs_ext_tags *tags)
  9932. +{
  9933. + struct yaffs_packed_tags2 pt;
  9934. + int retval;
  9935. +
  9936. + int packed_tags_size =
  9937. + dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
  9938. + void *packed_tags_ptr =
  9939. + dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
  9940. +
  9941. + yaffs_trace(YAFFS_TRACE_MTD,
  9942. + "yaffs_tags_marshall_write chunk %d data %p tags %p",
  9943. + nand_chunk, data, tags);
  9944. +
  9945. + /* For yaffs2 writing there must be both data and tags.
  9946. + * If we're using inband tags, then the tags are stuffed into
  9947. + * the end of the data buffer.
  9948. + */
  9949. + if (!data || !tags)
  9950. + BUG();
  9951. + else if (dev->param.inband_tags) {
  9952. + struct yaffs_packed_tags2_tags_only *pt2tp;
  9953. + pt2tp =
  9954. + (struct yaffs_packed_tags2_tags_only *)(data +
  9955. + dev->
  9956. + data_bytes_per_chunk);
  9957. + yaffs_pack_tags2_tags_only(pt2tp, tags);
  9958. + } else {
  9959. + yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
  9960. + }
  9961. +
  9962. + retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
  9963. + data, dev->param.total_bytes_per_chunk,
  9964. + (dev->param.inband_tags) ? NULL : packed_tags_ptr,
  9965. + (dev->param.inband_tags) ? 0 : packed_tags_size);
  9966. +
  9967. + return retval;
  9968. +}
  9969. +
  9970. +static int yaffs_tags_marshall_read(struct yaffs_dev *dev,
  9971. + int nand_chunk, u8 *data,
  9972. + struct yaffs_ext_tags *tags)
  9973. +{
  9974. + int retval = 0;
  9975. + int local_data = 0;
  9976. + u8 spare_buffer[100];
  9977. + enum yaffs_ecc_result ecc_result;
  9978. +
  9979. + struct yaffs_packed_tags2 pt;
  9980. +
  9981. + int packed_tags_size =
  9982. + dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
  9983. + void *packed_tags_ptr =
  9984. + dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
  9985. +
  9986. + yaffs_trace(YAFFS_TRACE_MTD,
  9987. + "yaffs_tags_marshall_read chunk %d data %p tags %p",
  9988. + nand_chunk, data, tags);
  9989. +
  9990. + if (dev->param.inband_tags) {
  9991. + if (!data) {
  9992. + local_data = 1;
  9993. + data = yaffs_get_temp_buffer(dev);
  9994. + }
  9995. + }
  9996. +
  9997. + if (dev->param.inband_tags || (data && !tags))
  9998. + retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  9999. + data, dev->param.total_bytes_per_chunk,
  10000. + NULL, 0,
  10001. + &ecc_result);
  10002. + else if (tags)
  10003. + retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  10004. + data, dev->param.total_bytes_per_chunk,
  10005. + spare_buffer, packed_tags_size,
  10006. + &ecc_result);
  10007. + else
  10008. + BUG();
  10009. +
  10010. +
  10011. + if (dev->param.inband_tags) {
  10012. + if (tags) {
  10013. + struct yaffs_packed_tags2_tags_only *pt2tp;
  10014. + pt2tp =
  10015. + (struct yaffs_packed_tags2_tags_only *)
  10016. + &data[dev->data_bytes_per_chunk];
  10017. + yaffs_unpack_tags2_tags_only(tags, pt2tp);
  10018. + }
  10019. + } else if (tags) {
  10020. + memcpy(packed_tags_ptr, spare_buffer, packed_tags_size);
  10021. + yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
  10022. + }
  10023. +
  10024. + if (local_data)
  10025. + yaffs_release_temp_buffer(dev, data);
  10026. +
  10027. + if (tags && ecc_result == YAFFS_ECC_RESULT_UNFIXED) {
  10028. + tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  10029. + dev->n_ecc_unfixed++;
  10030. + }
  10031. +
  10032. + if (tags && ecc_result == -YAFFS_ECC_RESULT_FIXED) {
  10033. + if (tags->ecc_result <= YAFFS_ECC_RESULT_NO_ERROR)
  10034. + tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
  10035. + dev->n_ecc_fixed++;
  10036. + }
  10037. +
  10038. + if (ecc_result < YAFFS_ECC_RESULT_UNFIXED)
  10039. + return YAFFS_OK;
  10040. + else
  10041. + return YAFFS_FAIL;
  10042. +}
  10043. +
  10044. +static int yaffs_tags_marshall_query_block(struct yaffs_dev *dev, int block_no,
  10045. + enum yaffs_block_state *state,
  10046. + u32 *seq_number)
  10047. +{
  10048. + int retval;
  10049. +
  10050. + yaffs_trace(YAFFS_TRACE_MTD, "yaffs_tags_marshall_query_block %d",
  10051. + block_no);
  10052. +
  10053. + retval = dev->drv.drv_check_bad_fn(dev, block_no);
  10054. +
  10055. + if (retval== YAFFS_FAIL) {
  10056. + yaffs_trace(YAFFS_TRACE_MTD, "block is bad");
  10057. +
  10058. + *state = YAFFS_BLOCK_STATE_DEAD;
  10059. + *seq_number = 0;
  10060. + } else {
  10061. + struct yaffs_ext_tags t;
  10062. +
  10063. + yaffs_tags_marshall_read(dev,
  10064. + block_no * dev->param.chunks_per_block,
  10065. + NULL, &t);
  10066. +
  10067. + if (t.chunk_used) {
  10068. + *seq_number = t.seq_number;
  10069. + *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
  10070. + } else {
  10071. + *seq_number = 0;
  10072. + *state = YAFFS_BLOCK_STATE_EMPTY;
  10073. + }
  10074. + }
  10075. +
  10076. + yaffs_trace(YAFFS_TRACE_MTD,
  10077. + "block query returns seq %d state %d",
  10078. + *seq_number, *state);
  10079. +
  10080. + if (retval == 0)
  10081. + return YAFFS_OK;
  10082. + else
  10083. + return YAFFS_FAIL;
  10084. +}
  10085. +
  10086. +static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no)
  10087. +{
  10088. + return dev->drv.drv_mark_bad_fn(dev, block_no);
  10089. +
  10090. +}
  10091. +
  10092. +
  10093. +void yaffs_tags_marshall_install(struct yaffs_dev *dev)
  10094. +{
  10095. + if (!dev->param.is_yaffs2)
  10096. + return;
  10097. +
  10098. + if (!dev->tagger.write_chunk_tags_fn)
  10099. + dev->tagger.write_chunk_tags_fn = yaffs_tags_marshall_write;
  10100. +
  10101. + if (!dev->tagger.read_chunk_tags_fn)
  10102. + dev->tagger.read_chunk_tags_fn = yaffs_tags_marshall_read;
  10103. +
  10104. + if (!dev->tagger.query_block_fn)
  10105. + dev->tagger.query_block_fn = yaffs_tags_marshall_query_block;
  10106. +
  10107. + if (!dev->tagger.mark_bad_fn)
  10108. + dev->tagger.mark_bad_fn = yaffs_tags_marshall_mark_bad;
  10109. +
  10110. +}
  10111. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_tagsmarshall.h linux-3.18.14/fs/yaffs2/yaffs_tagsmarshall.h
  10112. --- linux-3.18.14.orig/fs/yaffs2/yaffs_tagsmarshall.h 1970-01-01 01:00:00.000000000 +0100
  10113. +++ linux-3.18.14/fs/yaffs2/yaffs_tagsmarshall.h 2015-06-14 21:23:22.000000000 +0200
  10114. @@ -0,0 +1,22 @@
  10115. +/*
  10116. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  10117. + *
  10118. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10119. + * for Toby Churchill Ltd and Brightstar Engineering
  10120. + *
  10121. + * Created by Charles Manning <charles@aleph1.co.uk>
  10122. + *
  10123. + * This program is free software; you can redistribute it and/or modify
  10124. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  10125. + * published by the Free Software Foundation.
  10126. + *
  10127. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  10128. + */
  10129. +
  10130. +#ifndef __YAFFS_TAGSMARSHALL_H__
  10131. +#define __YAFFS_TAGSMARSHALL_H__
  10132. +
  10133. +#include "yaffs_guts.h"
  10134. +void yaffs_tags_marshall_install(struct yaffs_dev *dev);
  10135. +
  10136. +#endif
  10137. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_trace.h linux-3.18.14/fs/yaffs2/yaffs_trace.h
  10138. --- linux-3.18.14.orig/fs/yaffs2/yaffs_trace.h 1970-01-01 01:00:00.000000000 +0100
  10139. +++ linux-3.18.14/fs/yaffs2/yaffs_trace.h 2015-06-14 21:23:22.000000000 +0200
  10140. @@ -0,0 +1,57 @@
  10141. +/*
  10142. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  10143. + *
  10144. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10145. + * for Toby Churchill Ltd and Brightstar Engineering
  10146. + *
  10147. + * Created by Charles Manning <charles@aleph1.co.uk>
  10148. + *
  10149. + * This program is free software; you can redistribute it and/or modify
  10150. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  10151. + * published by the Free Software Foundation.
  10152. + *
  10153. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  10154. + */
  10155. +
  10156. +#ifndef __YTRACE_H__
  10157. +#define __YTRACE_H__
  10158. +
  10159. +extern unsigned int yaffs_trace_mask;
  10160. +extern unsigned int yaffs_wr_attempts;
  10161. +
  10162. +/*
  10163. + * Tracing flags.
  10164. + * The flags masked in YAFFS_TRACE_ALWAYS are always traced.
  10165. + */
  10166. +
  10167. +#define YAFFS_TRACE_OS 0x00000002
  10168. +#define YAFFS_TRACE_ALLOCATE 0x00000004
  10169. +#define YAFFS_TRACE_SCAN 0x00000008
  10170. +#define YAFFS_TRACE_BAD_BLOCKS 0x00000010
  10171. +#define YAFFS_TRACE_ERASE 0x00000020
  10172. +#define YAFFS_TRACE_GC 0x00000040
  10173. +#define YAFFS_TRACE_WRITE 0x00000080
  10174. +#define YAFFS_TRACE_TRACING 0x00000100
  10175. +#define YAFFS_TRACE_DELETION 0x00000200
  10176. +#define YAFFS_TRACE_BUFFERS 0x00000400
  10177. +#define YAFFS_TRACE_NANDACCESS 0x00000800
  10178. +#define YAFFS_TRACE_GC_DETAIL 0x00001000
  10179. +#define YAFFS_TRACE_SCAN_DEBUG 0x00002000
  10180. +#define YAFFS_TRACE_MTD 0x00004000
  10181. +#define YAFFS_TRACE_CHECKPOINT 0x00008000
  10182. +
  10183. +#define YAFFS_TRACE_VERIFY 0x00010000
  10184. +#define YAFFS_TRACE_VERIFY_NAND 0x00020000
  10185. +#define YAFFS_TRACE_VERIFY_FULL 0x00040000
  10186. +#define YAFFS_TRACE_VERIFY_ALL 0x000f0000
  10187. +
  10188. +#define YAFFS_TRACE_SYNC 0x00100000
  10189. +#define YAFFS_TRACE_BACKGROUND 0x00200000
  10190. +#define YAFFS_TRACE_LOCK 0x00400000
  10191. +#define YAFFS_TRACE_MOUNT 0x00800000
  10192. +
  10193. +#define YAFFS_TRACE_ERROR 0x40000000
  10194. +#define YAFFS_TRACE_BUG 0x80000000
  10195. +#define YAFFS_TRACE_ALWAYS 0xf0000000
  10196. +
  10197. +#endif
  10198. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_verify.c linux-3.18.14/fs/yaffs2/yaffs_verify.c
  10199. --- linux-3.18.14.orig/fs/yaffs2/yaffs_verify.c 1970-01-01 01:00:00.000000000 +0100
  10200. +++ linux-3.18.14/fs/yaffs2/yaffs_verify.c 2015-06-14 21:23:22.000000000 +0200
  10201. @@ -0,0 +1,529 @@
  10202. +/*
  10203. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  10204. + *
  10205. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10206. + * for Toby Churchill Ltd and Brightstar Engineering
  10207. + *
  10208. + * Created by Charles Manning <charles@aleph1.co.uk>
  10209. + *
  10210. + * This program is free software; you can redistribute it and/or modify
  10211. + * it under the terms of the GNU General Public License version 2 as
  10212. + * published by the Free Software Foundation.
  10213. + */
  10214. +
  10215. +#include "yaffs_verify.h"
  10216. +#include "yaffs_trace.h"
  10217. +#include "yaffs_bitmap.h"
  10218. +#include "yaffs_getblockinfo.h"
  10219. +#include "yaffs_nand.h"
  10220. +
  10221. +int yaffs_skip_verification(struct yaffs_dev *dev)
  10222. +{
  10223. + (void) dev;
  10224. + return !(yaffs_trace_mask &
  10225. + (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
  10226. +}
  10227. +
  10228. +static int yaffs_skip_full_verification(struct yaffs_dev *dev)
  10229. +{
  10230. + (void) dev;
  10231. + return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_FULL));
  10232. +}
  10233. +
  10234. +static int yaffs_skip_nand_verification(struct yaffs_dev *dev)
  10235. +{
  10236. + (void) dev;
  10237. + return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND));
  10238. +}
  10239. +
  10240. +static const char * const block_state_name[] = {
  10241. + "Unknown",
  10242. + "Needs scan",
  10243. + "Scanning",
  10244. + "Empty",
  10245. + "Allocating",
  10246. + "Full",
  10247. + "Dirty",
  10248. + "Checkpoint",
  10249. + "Collecting",
  10250. + "Dead"
  10251. +};
  10252. +
  10253. +void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n)
  10254. +{
  10255. + int actually_used;
  10256. + int in_use;
  10257. +
  10258. + if (yaffs_skip_verification(dev))
  10259. + return;
  10260. +
  10261. + /* Report illegal runtime states */
  10262. + if (bi->block_state >= YAFFS_NUMBER_OF_BLOCK_STATES)
  10263. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10264. + "Block %d has undefined state %d",
  10265. + n, bi->block_state);
  10266. +
  10267. + switch (bi->block_state) {
  10268. + case YAFFS_BLOCK_STATE_UNKNOWN:
  10269. + case YAFFS_BLOCK_STATE_SCANNING:
  10270. + case YAFFS_BLOCK_STATE_NEEDS_SCAN:
  10271. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10272. + "Block %d has bad run-state %s",
  10273. + n, block_state_name[bi->block_state]);
  10274. + }
  10275. +
  10276. + /* Check pages in use and soft deletions are legal */
  10277. +
  10278. + actually_used = bi->pages_in_use - bi->soft_del_pages;
  10279. +
  10280. + if (bi->pages_in_use < 0 ||
  10281. + bi->pages_in_use > dev->param.chunks_per_block ||
  10282. + bi->soft_del_pages < 0 ||
  10283. + bi->soft_del_pages > dev->param.chunks_per_block ||
  10284. + actually_used < 0 || actually_used > dev->param.chunks_per_block)
  10285. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10286. + "Block %d has illegal values pages_in_used %d soft_del_pages %d",
  10287. + n, bi->pages_in_use, bi->soft_del_pages);
  10288. +
  10289. + /* Check chunk bitmap legal */
  10290. + in_use = yaffs_count_chunk_bits(dev, n);
  10291. + if (in_use != bi->pages_in_use)
  10292. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10293. + "Block %d has inconsistent values pages_in_use %d counted chunk bits %d",
  10294. + n, bi->pages_in_use, in_use);
  10295. +}
  10296. +
  10297. +void yaffs_verify_collected_blk(struct yaffs_dev *dev,
  10298. + struct yaffs_block_info *bi, int n)
  10299. +{
  10300. + yaffs_verify_blk(dev, bi, n);
  10301. +
  10302. + /* After collection the block should be in the erased state */
  10303. +
  10304. + if (bi->block_state != YAFFS_BLOCK_STATE_COLLECTING &&
  10305. + bi->block_state != YAFFS_BLOCK_STATE_EMPTY) {
  10306. + yaffs_trace(YAFFS_TRACE_ERROR,
  10307. + "Block %d is in state %d after gc, should be erased",
  10308. + n, bi->block_state);
  10309. + }
  10310. +}
  10311. +
  10312. +void yaffs_verify_blocks(struct yaffs_dev *dev)
  10313. +{
  10314. + int i;
  10315. + int state_count[YAFFS_NUMBER_OF_BLOCK_STATES];
  10316. + int illegal_states = 0;
  10317. +
  10318. + if (yaffs_skip_verification(dev))
  10319. + return;
  10320. +
  10321. + memset(state_count, 0, sizeof(state_count));
  10322. +
  10323. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  10324. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
  10325. + yaffs_verify_blk(dev, bi, i);
  10326. +
  10327. + if (bi->block_state < YAFFS_NUMBER_OF_BLOCK_STATES)
  10328. + state_count[bi->block_state]++;
  10329. + else
  10330. + illegal_states++;
  10331. + }
  10332. +
  10333. + yaffs_trace(YAFFS_TRACE_VERIFY, "Block summary");
  10334. +
  10335. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10336. + "%d blocks have illegal states",
  10337. + illegal_states);
  10338. + if (state_count[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
  10339. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10340. + "Too many allocating blocks");
  10341. +
  10342. + for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++)
  10343. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10344. + "%s %d blocks",
  10345. + block_state_name[i], state_count[i]);
  10346. +
  10347. + if (dev->blocks_in_checkpt != state_count[YAFFS_BLOCK_STATE_CHECKPOINT])
  10348. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10349. + "Checkpoint block count wrong dev %d count %d",
  10350. + dev->blocks_in_checkpt,
  10351. + state_count[YAFFS_BLOCK_STATE_CHECKPOINT]);
  10352. +
  10353. + if (dev->n_erased_blocks != state_count[YAFFS_BLOCK_STATE_EMPTY])
  10354. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10355. + "Erased block count wrong dev %d count %d",
  10356. + dev->n_erased_blocks,
  10357. + state_count[YAFFS_BLOCK_STATE_EMPTY]);
  10358. +
  10359. + if (state_count[YAFFS_BLOCK_STATE_COLLECTING] > 1)
  10360. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10361. + "Too many collecting blocks %d (max is 1)",
  10362. + state_count[YAFFS_BLOCK_STATE_COLLECTING]);
  10363. +}
  10364. +
  10365. +/*
  10366. + * Verify the object header. oh must be valid, but obj and tags may be NULL in
  10367. + * which case those tests will not be performed.
  10368. + */
  10369. +void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
  10370. + struct yaffs_ext_tags *tags, int parent_check)
  10371. +{
  10372. + if (obj && yaffs_skip_verification(obj->my_dev))
  10373. + return;
  10374. +
  10375. + if (!(tags && obj && oh)) {
  10376. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10377. + "Verifying object header tags %p obj %p oh %p",
  10378. + tags, obj, oh);
  10379. + return;
  10380. + }
  10381. +
  10382. + if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
  10383. + oh->type > YAFFS_OBJECT_TYPE_MAX)
  10384. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10385. + "Obj %d header type is illegal value 0x%x",
  10386. + tags->obj_id, oh->type);
  10387. +
  10388. + if (tags->obj_id != obj->obj_id)
  10389. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10390. + "Obj %d header mismatch obj_id %d",
  10391. + tags->obj_id, obj->obj_id);
  10392. +
  10393. + /*
  10394. + * Check that the object's parent ids match if parent_check requested.
  10395. + *
  10396. + * Tests do not apply to the root object.
  10397. + */
  10398. +
  10399. + if (parent_check && tags->obj_id > 1 && !obj->parent)
  10400. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10401. + "Obj %d header mismatch parent_id %d obj->parent is NULL",
  10402. + tags->obj_id, oh->parent_obj_id);
  10403. +
  10404. + if (parent_check && obj->parent &&
  10405. + oh->parent_obj_id != obj->parent->obj_id &&
  10406. + (oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED ||
  10407. + obj->parent->obj_id != YAFFS_OBJECTID_DELETED))
  10408. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10409. + "Obj %d header mismatch parent_id %d parent_obj_id %d",
  10410. + tags->obj_id, oh->parent_obj_id,
  10411. + obj->parent->obj_id);
  10412. +
  10413. + if (tags->obj_id > 1 && oh->name[0] == 0) /* Null name */
  10414. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10415. + "Obj %d header name is NULL",
  10416. + obj->obj_id);
  10417. +
  10418. + if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff) /* Junk name */
  10419. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10420. + "Obj %d header name is 0xff",
  10421. + obj->obj_id);
  10422. +}
  10423. +
  10424. +void yaffs_verify_file(struct yaffs_obj *obj)
  10425. +{
  10426. + u32 x;
  10427. + int required_depth;
  10428. + int actual_depth;
  10429. + int last_chunk;
  10430. + u32 offset_in_chunk;
  10431. + u32 the_chunk;
  10432. +
  10433. + u32 i;
  10434. + struct yaffs_dev *dev;
  10435. + struct yaffs_ext_tags tags;
  10436. + struct yaffs_tnode *tn;
  10437. + u32 obj_id;
  10438. +
  10439. + if (!obj)
  10440. + return;
  10441. +
  10442. + if (yaffs_skip_verification(obj->my_dev))
  10443. + return;
  10444. +
  10445. + dev = obj->my_dev;
  10446. + obj_id = obj->obj_id;
  10447. +
  10448. +
  10449. + /* Check file size is consistent with tnode depth */
  10450. + yaffs_addr_to_chunk(dev, obj->variant.file_variant.file_size,
  10451. + &last_chunk, &offset_in_chunk);
  10452. + last_chunk++;
  10453. + x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS;
  10454. + required_depth = 0;
  10455. + while (x > 0) {
  10456. + x >>= YAFFS_TNODES_INTERNAL_BITS;
  10457. + required_depth++;
  10458. + }
  10459. +
  10460. + actual_depth = obj->variant.file_variant.top_level;
  10461. +
  10462. + /* Check that the chunks in the tnode tree are all correct.
  10463. + * We do this by scanning through the tnode tree and
  10464. + * checking the tags for every chunk match.
  10465. + */
  10466. +
  10467. + if (yaffs_skip_nand_verification(dev))
  10468. + return;
  10469. +
  10470. + for (i = 1; i <= last_chunk; i++) {
  10471. + tn = yaffs_find_tnode_0(dev, &obj->variant.file_variant, i);
  10472. +
  10473. + if (!tn)
  10474. + continue;
  10475. +
  10476. + the_chunk = yaffs_get_group_base(dev, tn, i);
  10477. + if (the_chunk > 0) {
  10478. + yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
  10479. + &tags);
  10480. + if (tags.obj_id != obj_id || tags.chunk_id != i)
  10481. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10482. + "Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)",
  10483. + obj_id, i, the_chunk,
  10484. + tags.obj_id, tags.chunk_id);
  10485. + }
  10486. + }
  10487. +}
  10488. +
  10489. +void yaffs_verify_link(struct yaffs_obj *obj)
  10490. +{
  10491. + if (obj && yaffs_skip_verification(obj->my_dev))
  10492. + return;
  10493. +
  10494. + /* Verify sane equivalent object */
  10495. +}
  10496. +
  10497. +void yaffs_verify_symlink(struct yaffs_obj *obj)
  10498. +{
  10499. + if (obj && yaffs_skip_verification(obj->my_dev))
  10500. + return;
  10501. +
  10502. + /* Verify symlink string */
  10503. +}
  10504. +
  10505. +void yaffs_verify_special(struct yaffs_obj *obj)
  10506. +{
  10507. + if (obj && yaffs_skip_verification(obj->my_dev))
  10508. + return;
  10509. +}
  10510. +
  10511. +void yaffs_verify_obj(struct yaffs_obj *obj)
  10512. +{
  10513. + struct yaffs_dev *dev;
  10514. + u32 chunk_min;
  10515. + u32 chunk_max;
  10516. + u32 chunk_id_ok;
  10517. + u32 chunk_in_range;
  10518. + u32 chunk_wrongly_deleted;
  10519. + u32 chunk_valid;
  10520. +
  10521. + if (!obj)
  10522. + return;
  10523. +
  10524. + if (obj->being_created)
  10525. + return;
  10526. +
  10527. + dev = obj->my_dev;
  10528. +
  10529. + if (yaffs_skip_verification(dev))
  10530. + return;
  10531. +
  10532. + /* Check sane object header chunk */
  10533. +
  10534. + chunk_min = dev->internal_start_block * dev->param.chunks_per_block;
  10535. + chunk_max =
  10536. + (dev->internal_end_block + 1) * dev->param.chunks_per_block - 1;
  10537. +
  10538. + chunk_in_range = (((unsigned)(obj->hdr_chunk)) >= chunk_min &&
  10539. + ((unsigned)(obj->hdr_chunk)) <= chunk_max);
  10540. + chunk_id_ok = chunk_in_range || (obj->hdr_chunk == 0);
  10541. + chunk_valid = chunk_in_range &&
  10542. + yaffs_check_chunk_bit(dev,
  10543. + obj->hdr_chunk / dev->param.chunks_per_block,
  10544. + obj->hdr_chunk % dev->param.chunks_per_block);
  10545. + chunk_wrongly_deleted = chunk_in_range && !chunk_valid;
  10546. +
  10547. + if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted))
  10548. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10549. + "Obj %d has chunk_id %d %s %s",
  10550. + obj->obj_id, obj->hdr_chunk,
  10551. + chunk_id_ok ? "" : ",out of range",
  10552. + chunk_wrongly_deleted ? ",marked as deleted" : "");
  10553. +
  10554. + if (chunk_valid && !yaffs_skip_nand_verification(dev)) {
  10555. + struct yaffs_ext_tags tags;
  10556. + struct yaffs_obj_hdr *oh;
  10557. + u8 *buffer = yaffs_get_temp_buffer(dev);
  10558. +
  10559. + oh = (struct yaffs_obj_hdr *)buffer;
  10560. +
  10561. + yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, buffer, &tags);
  10562. +
  10563. + yaffs_verify_oh(obj, oh, &tags, 1);
  10564. +
  10565. + yaffs_release_temp_buffer(dev, buffer);
  10566. + }
  10567. +
  10568. + /* Verify it has a parent */
  10569. + if (obj && !obj->fake && (!obj->parent || obj->parent->my_dev != dev)) {
  10570. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10571. + "Obj %d has parent pointer %p which does not look like an object",
  10572. + obj->obj_id, obj->parent);
  10573. + }
  10574. +
  10575. + /* Verify parent is a directory */
  10576. + if (obj->parent &&
  10577. + obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  10578. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10579. + "Obj %d's parent is not a directory (type %d)",
  10580. + obj->obj_id, obj->parent->variant_type);
  10581. + }
  10582. +
  10583. + switch (obj->variant_type) {
  10584. + case YAFFS_OBJECT_TYPE_FILE:
  10585. + yaffs_verify_file(obj);
  10586. + break;
  10587. + case YAFFS_OBJECT_TYPE_SYMLINK:
  10588. + yaffs_verify_symlink(obj);
  10589. + break;
  10590. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  10591. + yaffs_verify_dir(obj);
  10592. + break;
  10593. + case YAFFS_OBJECT_TYPE_HARDLINK:
  10594. + yaffs_verify_link(obj);
  10595. + break;
  10596. + case YAFFS_OBJECT_TYPE_SPECIAL:
  10597. + yaffs_verify_special(obj);
  10598. + break;
  10599. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  10600. + default:
  10601. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10602. + "Obj %d has illegaltype %d",
  10603. + obj->obj_id, obj->variant_type);
  10604. + break;
  10605. + }
  10606. +}
  10607. +
  10608. +void yaffs_verify_objects(struct yaffs_dev *dev)
  10609. +{
  10610. + struct yaffs_obj *obj;
  10611. + int i;
  10612. + struct list_head *lh;
  10613. +
  10614. + if (yaffs_skip_verification(dev))
  10615. + return;
  10616. +
  10617. + /* Iterate through the objects in each hash entry */
  10618. +
  10619. + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
  10620. + list_for_each(lh, &dev->obj_bucket[i].list) {
  10621. + obj = list_entry(lh, struct yaffs_obj, hash_link);
  10622. + yaffs_verify_obj(obj);
  10623. + }
  10624. + }
  10625. +}
  10626. +
  10627. +void yaffs_verify_obj_in_dir(struct yaffs_obj *obj)
  10628. +{
  10629. + struct list_head *lh;
  10630. + struct yaffs_obj *list_obj;
  10631. + int count = 0;
  10632. +
  10633. + if (!obj) {
  10634. + yaffs_trace(YAFFS_TRACE_ALWAYS, "No object to verify");
  10635. + BUG();
  10636. + return;
  10637. + }
  10638. +
  10639. + if (yaffs_skip_verification(obj->my_dev))
  10640. + return;
  10641. +
  10642. + if (!obj->parent) {
  10643. + yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent");
  10644. + BUG();
  10645. + return;
  10646. + }
  10647. +
  10648. + if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  10649. + yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory");
  10650. + BUG();
  10651. + }
  10652. +
  10653. + /* Iterate through the objects in each hash entry */
  10654. +
  10655. + list_for_each(lh, &obj->parent->variant.dir_variant.children) {
  10656. + list_obj = list_entry(lh, struct yaffs_obj, siblings);
  10657. + yaffs_verify_obj(list_obj);
  10658. + if (obj == list_obj)
  10659. + count++;
  10660. + }
  10661. +
  10662. + if (count != 1) {
  10663. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  10664. + "Object in directory %d times",
  10665. + count);
  10666. + BUG();
  10667. + }
  10668. +}
  10669. +
  10670. +void yaffs_verify_dir(struct yaffs_obj *directory)
  10671. +{
  10672. + struct list_head *lh;
  10673. + struct yaffs_obj *list_obj;
  10674. +
  10675. + if (!directory) {
  10676. + BUG();
  10677. + return;
  10678. + }
  10679. +
  10680. + if (yaffs_skip_full_verification(directory->my_dev))
  10681. + return;
  10682. +
  10683. + if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  10684. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  10685. + "Directory has wrong type: %d",
  10686. + directory->variant_type);
  10687. + BUG();
  10688. + }
  10689. +
  10690. + /* Iterate through the objects in each hash entry */
  10691. +
  10692. + list_for_each(lh, &directory->variant.dir_variant.children) {
  10693. + list_obj = list_entry(lh, struct yaffs_obj, siblings);
  10694. + if (list_obj->parent != directory) {
  10695. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  10696. + "Object in directory list has wrong parent %p",
  10697. + list_obj->parent);
  10698. + BUG();
  10699. + }
  10700. + yaffs_verify_obj_in_dir(list_obj);
  10701. + }
  10702. +}
  10703. +
  10704. +static int yaffs_free_verification_failures;
  10705. +
  10706. +void yaffs_verify_free_chunks(struct yaffs_dev *dev)
  10707. +{
  10708. + int counted;
  10709. + int difference;
  10710. +
  10711. + if (yaffs_skip_verification(dev))
  10712. + return;
  10713. +
  10714. + counted = yaffs_count_free_chunks(dev);
  10715. +
  10716. + difference = dev->n_free_chunks - counted;
  10717. +
  10718. + if (difference) {
  10719. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  10720. + "Freechunks verification failure %d %d %d",
  10721. + dev->n_free_chunks, counted, difference);
  10722. + yaffs_free_verification_failures++;
  10723. + }
  10724. +}
  10725. +
  10726. +int yaffs_verify_file_sane(struct yaffs_obj *in)
  10727. +{
  10728. + (void) in;
  10729. + return YAFFS_OK;
  10730. +}
  10731. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_verify.h linux-3.18.14/fs/yaffs2/yaffs_verify.h
  10732. --- linux-3.18.14.orig/fs/yaffs2/yaffs_verify.h 1970-01-01 01:00:00.000000000 +0100
  10733. +++ linux-3.18.14/fs/yaffs2/yaffs_verify.h 2015-06-14 21:23:22.000000000 +0200
  10734. @@ -0,0 +1,43 @@
  10735. +/*
  10736. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  10737. + *
  10738. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10739. + * for Toby Churchill Ltd and Brightstar Engineering
  10740. + *
  10741. + * Created by Charles Manning <charles@aleph1.co.uk>
  10742. + *
  10743. + * This program is free software; you can redistribute it and/or modify
  10744. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  10745. + * published by the Free Software Foundation.
  10746. + *
  10747. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  10748. + */
  10749. +
  10750. +#ifndef __YAFFS_VERIFY_H__
  10751. +#define __YAFFS_VERIFY_H__
  10752. +
  10753. +#include "yaffs_guts.h"
  10754. +
  10755. +void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi,
  10756. + int n);
  10757. +void yaffs_verify_collected_blk(struct yaffs_dev *dev,
  10758. + struct yaffs_block_info *bi, int n);
  10759. +void yaffs_verify_blocks(struct yaffs_dev *dev);
  10760. +
  10761. +void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
  10762. + struct yaffs_ext_tags *tags, int parent_check);
  10763. +void yaffs_verify_file(struct yaffs_obj *obj);
  10764. +void yaffs_verify_link(struct yaffs_obj *obj);
  10765. +void yaffs_verify_symlink(struct yaffs_obj *obj);
  10766. +void yaffs_verify_special(struct yaffs_obj *obj);
  10767. +void yaffs_verify_obj(struct yaffs_obj *obj);
  10768. +void yaffs_verify_objects(struct yaffs_dev *dev);
  10769. +void yaffs_verify_obj_in_dir(struct yaffs_obj *obj);
  10770. +void yaffs_verify_dir(struct yaffs_obj *directory);
  10771. +void yaffs_verify_free_chunks(struct yaffs_dev *dev);
  10772. +
  10773. +int yaffs_verify_file_sane(struct yaffs_obj *obj);
  10774. +
  10775. +int yaffs_skip_verification(struct yaffs_dev *dev);
  10776. +
  10777. +#endif
  10778. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_vfs.c linux-3.18.14/fs/yaffs2/yaffs_vfs.c
  10779. --- linux-3.18.14.orig/fs/yaffs2/yaffs_vfs.c 1970-01-01 01:00:00.000000000 +0100
  10780. +++ linux-3.18.14/fs/yaffs2/yaffs_vfs.c 2015-06-15 18:42:09.000000000 +0200
  10781. @@ -0,0 +1,3658 @@
  10782. +/*
  10783. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  10784. + *
  10785. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10786. + * for Toby Churchill Ltd and Brightstar Engineering
  10787. + *
  10788. + * Created by Charles Manning <charles@aleph1.co.uk>
  10789. + * Acknowledgements:
  10790. + * Luc van OostenRyck for numerous patches.
  10791. + * Nick Bane for numerous patches.
  10792. + * Nick Bane for 2.5/2.6 integration.
  10793. + * Andras Toth for mknod rdev issue.
  10794. + * Michael Fischer for finding the problem with inode inconsistency.
  10795. + * Some code bodily lifted from JFFS
  10796. + *
  10797. + * This program is free software; you can redistribute it and/or modify
  10798. + * it under the terms of the GNU General Public License version 2 as
  10799. + * published by the Free Software Foundation.
  10800. + */
  10801. +
  10802. +/*
  10803. + *
  10804. + * This is the file system front-end to YAFFS that hooks it up to
  10805. + * the VFS.
  10806. + *
  10807. + * Special notes:
  10808. + * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with
  10809. + * this superblock
  10810. + * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this
  10811. + * superblock
  10812. + * >> inode->u.generic_ip points to the associated struct yaffs_obj.
  10813. + */
  10814. +
  10815. +/*
  10816. + * There are two variants of the VFS glue code. This variant should compile
  10817. + * for any version of Linux.
  10818. + */
  10819. +#include <linux/version.h>
  10820. +
  10821. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
  10822. +#define YAFFS_COMPILE_BACKGROUND
  10823. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23))
  10824. +#define YAFFS_COMPILE_FREEZER
  10825. +#endif
  10826. +#endif
  10827. +
  10828. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
  10829. +#define YAFFS_COMPILE_EXPORTFS
  10830. +#endif
  10831. +
  10832. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
  10833. +#define YAFFS_USE_SETATTR_COPY
  10834. +#define YAFFS_USE_TRUNCATE_SETSIZE
  10835. +#endif
  10836. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
  10837. +#define YAFFS_HAS_EVICT_INODE
  10838. +#endif
  10839. +
  10840. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
  10841. +#define YAFFS_NEW_FOLLOW_LINK 1
  10842. +#else
  10843. +#define YAFFS_NEW_FOLLOW_LINK 0
  10844. +#endif
  10845. +
  10846. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
  10847. +#define YAFFS_HAS_WRITE_SUPER
  10848. +#endif
  10849. +
  10850. +
  10851. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  10852. +#include <linux/config.h>
  10853. +#endif
  10854. +
  10855. +#include <linux/kernel.h>
  10856. +#include <linux/module.h>
  10857. +#include <linux/slab.h>
  10858. +#include <linux/init.h>
  10859. +#include <linux/fs.h>
  10860. +#include <linux/proc_fs.h>
  10861. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
  10862. +#include <linux/smp_lock.h>
  10863. +#endif
  10864. +#include <linux/pagemap.h>
  10865. +#include <linux/mtd/mtd.h>
  10866. +#include <linux/interrupt.h>
  10867. +#include <linux/string.h>
  10868. +#include <linux/ctype.h>
  10869. +
  10870. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  10871. +#include <linux/namei.h>
  10872. +#endif
  10873. +
  10874. +#ifdef YAFFS_COMPILE_EXPORTFS
  10875. +#include <linux/exportfs.h>
  10876. +#endif
  10877. +
  10878. +#ifdef YAFFS_COMPILE_BACKGROUND
  10879. +#include <linux/kthread.h>
  10880. +#include <linux/delay.h>
  10881. +#endif
  10882. +#ifdef YAFFS_COMPILE_FREEZER
  10883. +#include <linux/freezer.h>
  10884. +#endif
  10885. +
  10886. +#include <asm/div64.h>
  10887. +
  10888. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  10889. +
  10890. +#include <linux/statfs.h>
  10891. +
  10892. +#define UnlockPage(p) unlock_page(p)
  10893. +#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
  10894. +
  10895. +/* FIXME: use sb->s_id instead ? */
  10896. +#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
  10897. +
  10898. +#else
  10899. +
  10900. +#include <linux/locks.h>
  10901. +#define BDEVNAME_SIZE 0
  10902. +#define yaffs_devname(sb, buf) kdevname(sb->s_dev)
  10903. +
  10904. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
  10905. +/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
  10906. +#define __user
  10907. +#endif
  10908. +
  10909. +#endif
  10910. +
  10911. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
  10912. +#define YPROC_ROOT (&proc_root)
  10913. +#else
  10914. +#define YPROC_ROOT NULL
  10915. +#endif
  10916. +
  10917. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
  10918. +#define Y_INIT_TIMER(a) init_timer(a)
  10919. +#else
  10920. +#define Y_INIT_TIMER(a) init_timer_on_stack(a)
  10921. +#endif
  10922. +
  10923. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
  10924. +#define YAFFS_USE_WRITE_BEGIN_END 1
  10925. +#else
  10926. +#define YAFFS_USE_WRITE_BEGIN_END 0
  10927. +#endif
  10928. +
  10929. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
  10930. +#define YAFFS_SUPER_HAS_DIRTY
  10931. +#endif
  10932. +
  10933. +
  10934. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
  10935. +#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0)
  10936. +#endif
  10937. +
  10938. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
  10939. +static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
  10940. +{
  10941. + uint64_t result = partition_size;
  10942. + do_div(result, block_size);
  10943. + return (uint32_t) result;
  10944. +}
  10945. +#else
  10946. +#define YCALCBLOCKS(s, b) ((s)/(b))
  10947. +#endif
  10948. +
  10949. +#include <linux/uaccess.h>
  10950. +#include <linux/mtd/mtd.h>
  10951. +
  10952. +#include "yportenv.h"
  10953. +#include "yaffs_trace.h"
  10954. +#include "yaffs_guts.h"
  10955. +#include "yaffs_attribs.h"
  10956. +
  10957. +#include "yaffs_linux.h"
  10958. +
  10959. +#include "yaffs_mtdif.h"
  10960. +#include "yaffs_packedtags2.h"
  10961. +#include "yaffs_getblockinfo.h"
  10962. +
  10963. +unsigned int yaffs_trace_mask =
  10964. + YAFFS_TRACE_BAD_BLOCKS |
  10965. + YAFFS_TRACE_ALWAYS |
  10966. + 0;
  10967. +
  10968. +unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
  10969. +unsigned int yaffs_auto_checkpoint = 1;
  10970. +unsigned int yaffs_gc_control = 1;
  10971. +unsigned int yaffs_bg_enable = 1;
  10972. +unsigned int yaffs_auto_select = 1;
  10973. +/* Module Parameters */
  10974. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  10975. +module_param(yaffs_trace_mask, uint, 0644);
  10976. +module_param(yaffs_wr_attempts, uint, 0644);
  10977. +module_param(yaffs_auto_checkpoint, uint, 0644);
  10978. +module_param(yaffs_gc_control, uint, 0644);
  10979. +module_param(yaffs_bg_enable, uint, 0644);
  10980. +#else
  10981. +MODULE_PARM(yaffs_trace_mask, "i");
  10982. +MODULE_PARM(yaffs_wr_attempts, "i");
  10983. +MODULE_PARM(yaffs_auto_checkpoint, "i");
  10984. +MODULE_PARM(yaffs_gc_control, "i");
  10985. +#endif
  10986. +
  10987. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
  10988. +/* use iget and read_inode */
  10989. +#define Y_IGET(sb, inum) iget((sb), (inum))
  10990. +
  10991. +#else
  10992. +/* Call local equivalent */
  10993. +#define YAFFS_USE_OWN_IGET
  10994. +#define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
  10995. +
  10996. +#endif
  10997. +
  10998. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
  10999. +#define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private)
  11000. +#else
  11001. +#define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
  11002. +#endif
  11003. +
  11004. +#define yaffs_inode_to_obj(iptr) \
  11005. + ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
  11006. +#define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode)
  11007. +
  11008. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11009. +#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info)
  11010. +#else
  11011. +#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp)
  11012. +#endif
  11013. +
  11014. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  11015. +#define Y_CLEAR_INODE(i) clear_inode(i)
  11016. +#else
  11017. +#define Y_CLEAR_INODE(i) end_writeback(i)
  11018. +#endif
  11019. +
  11020. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  11021. +#define YAFFS_USE_DIR_ITERATE
  11022. +#endif
  11023. +
  11024. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
  11025. +#define YAFFS_NEW_PROCFS
  11026. +#include <linux/seq_file.h>
  11027. +#endif
  11028. +
  11029. +
  11030. +#define update_dir_time(dir) do {\
  11031. + (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
  11032. + } while (0)
  11033. +
  11034. +static void yaffs_fill_inode_from_obj(struct inode *inode,
  11035. + struct yaffs_obj *obj);
  11036. +
  11037. +
  11038. +static void yaffs_gross_lock(struct yaffs_dev *dev)
  11039. +{
  11040. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locking %p", current);
  11041. + mutex_lock(&(yaffs_dev_to_lc(dev)->gross_lock));
  11042. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locked %p", current);
  11043. +}
  11044. +
  11045. +static void yaffs_gross_unlock(struct yaffs_dev *dev)
  11046. +{
  11047. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current);
  11048. + mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock));
  11049. +}
  11050. +
  11051. +
  11052. +static int yaffs_readpage_nolock(struct file *f, struct page *pg)
  11053. +{
  11054. + /* Lifted from jffs2 */
  11055. +
  11056. + struct yaffs_obj *obj;
  11057. + unsigned char *pg_buf;
  11058. + int ret;
  11059. + loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
  11060. + struct yaffs_dev *dev;
  11061. +
  11062. + yaffs_trace(YAFFS_TRACE_OS,
  11063. + "yaffs_readpage_nolock at %lld, size %08x",
  11064. + (long long)pos,
  11065. + (unsigned)PAGE_CACHE_SIZE);
  11066. +
  11067. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11068. +
  11069. + dev = obj->my_dev;
  11070. +
  11071. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11072. + BUG_ON(!PageLocked(pg));
  11073. +#else
  11074. + if (!PageLocked(pg))
  11075. + PAGE_BUG(pg);
  11076. +#endif
  11077. +
  11078. + pg_buf = kmap(pg);
  11079. + /* FIXME: Can kmap fail? */
  11080. +
  11081. + yaffs_gross_lock(dev);
  11082. +
  11083. + ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE);
  11084. +
  11085. + yaffs_gross_unlock(dev);
  11086. +
  11087. + if (ret >= 0)
  11088. + ret = 0;
  11089. +
  11090. + if (ret) {
  11091. + ClearPageUptodate(pg);
  11092. + SetPageError(pg);
  11093. + } else {
  11094. + SetPageUptodate(pg);
  11095. + ClearPageError(pg);
  11096. + }
  11097. +
  11098. + flush_dcache_page(pg);
  11099. + kunmap(pg);
  11100. +
  11101. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done");
  11102. + return ret;
  11103. +}
  11104. +
  11105. +static int yaffs_readpage_unlock(struct file *f, struct page *pg)
  11106. +{
  11107. + int ret = yaffs_readpage_nolock(f, pg);
  11108. + UnlockPage(pg);
  11109. + return ret;
  11110. +}
  11111. +
  11112. +static int yaffs_readpage(struct file *f, struct page *pg)
  11113. +{
  11114. + int ret;
  11115. +
  11116. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage");
  11117. + ret = yaffs_readpage_unlock(f, pg);
  11118. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done");
  11119. + return ret;
  11120. +}
  11121. +
  11122. +
  11123. +static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
  11124. +{
  11125. + struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
  11126. +
  11127. + if (lc)
  11128. + lc->dirty = val;
  11129. +
  11130. +# ifdef YAFFS_SUPER_HAS_DIRTY
  11131. + {
  11132. + struct super_block *sb = lc->super;
  11133. +
  11134. + if (sb)
  11135. + sb->s_dirt = val;
  11136. + }
  11137. +#endif
  11138. +
  11139. +}
  11140. +
  11141. +static void yaffs_set_super_dirty(struct yaffs_dev *dev)
  11142. +{
  11143. + yaffs_set_super_dirty_val(dev, 1);
  11144. +}
  11145. +
  11146. +static void yaffs_clear_super_dirty(struct yaffs_dev *dev)
  11147. +{
  11148. + yaffs_set_super_dirty_val(dev, 0);
  11149. +}
  11150. +
  11151. +static int yaffs_check_super_dirty(struct yaffs_dev *dev)
  11152. +{
  11153. + struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
  11154. +
  11155. + if (lc && lc->dirty)
  11156. + return 1;
  11157. +
  11158. +# ifdef YAFFS_SUPER_HAS_DIRTY
  11159. + {
  11160. + struct super_block *sb = lc->super;
  11161. +
  11162. + if (sb && sb->s_dirt)
  11163. + return 1;
  11164. + }
  11165. +#endif
  11166. + return 0;
  11167. +
  11168. +}
  11169. +
  11170. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11171. +static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
  11172. +#else
  11173. +static int yaffs_writepage(struct page *page)
  11174. +#endif
  11175. +{
  11176. + struct yaffs_dev *dev;
  11177. + struct address_space *mapping = page->mapping;
  11178. + struct inode *inode;
  11179. + unsigned long end_index;
  11180. + char *buffer;
  11181. + struct yaffs_obj *obj;
  11182. + int n_written = 0;
  11183. + unsigned n_bytes;
  11184. + loff_t i_size;
  11185. +
  11186. + if (!mapping)
  11187. + BUG();
  11188. + inode = mapping->host;
  11189. + if (!inode)
  11190. + BUG();
  11191. + i_size = i_size_read(inode);
  11192. +
  11193. + end_index = i_size >> PAGE_CACHE_SHIFT;
  11194. +
  11195. + if (page->index < end_index)
  11196. + n_bytes = PAGE_CACHE_SIZE;
  11197. + else {
  11198. + n_bytes = i_size & (PAGE_CACHE_SIZE - 1);
  11199. +
  11200. + if (page->index > end_index || !n_bytes) {
  11201. + yaffs_trace(YAFFS_TRACE_OS,
  11202. + "yaffs_writepage at %lld, inode size = %lld!!",
  11203. + ((loff_t)page->index) << PAGE_CACHE_SHIFT,
  11204. + inode->i_size);
  11205. + yaffs_trace(YAFFS_TRACE_OS,
  11206. + " -> don't care!!");
  11207. +
  11208. + zero_user_segment(page, 0, PAGE_CACHE_SIZE);
  11209. + set_page_writeback(page);
  11210. + unlock_page(page);
  11211. + end_page_writeback(page);
  11212. + return 0;
  11213. + }
  11214. + }
  11215. +
  11216. + if (n_bytes != PAGE_CACHE_SIZE)
  11217. + zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE);
  11218. +
  11219. + get_page(page);
  11220. +
  11221. + buffer = kmap(page);
  11222. +
  11223. + obj = yaffs_inode_to_obj(inode);
  11224. + dev = obj->my_dev;
  11225. + yaffs_gross_lock(dev);
  11226. +
  11227. + yaffs_trace(YAFFS_TRACE_OS,
  11228. + "yaffs_writepage at %lld, size %08x",
  11229. + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes);
  11230. + yaffs_trace(YAFFS_TRACE_OS,
  11231. + "writepag0: obj = %lld, ino = %lld",
  11232. + obj->variant.file_variant.file_size, inode->i_size);
  11233. +
  11234. + n_written = yaffs_wr_file(obj, buffer,
  11235. + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0);
  11236. +
  11237. + yaffs_set_super_dirty(dev);
  11238. +
  11239. + yaffs_trace(YAFFS_TRACE_OS,
  11240. + "writepag1: obj = %lld, ino = %lld",
  11241. + obj->variant.file_variant.file_size, inode->i_size);
  11242. +
  11243. + yaffs_gross_unlock(dev);
  11244. +
  11245. + kunmap(page);
  11246. + set_page_writeback(page);
  11247. + unlock_page(page);
  11248. + end_page_writeback(page);
  11249. + put_page(page);
  11250. +
  11251. + return (n_written == n_bytes) ? 0 : -ENOSPC;
  11252. +}
  11253. +
  11254. +/* Space holding and freeing is done to ensure we have space available for write_begin/end */
  11255. +/* For now we just assume few parallel writes and check against a small number. */
  11256. +/* Todo: need to do this with a counter to handle parallel reads better */
  11257. +
  11258. +static ssize_t yaffs_hold_space(struct file *f)
  11259. +{
  11260. + struct yaffs_obj *obj;
  11261. + struct yaffs_dev *dev;
  11262. +
  11263. + int n_free_chunks;
  11264. +
  11265. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11266. +
  11267. + dev = obj->my_dev;
  11268. +
  11269. + yaffs_gross_lock(dev);
  11270. +
  11271. + n_free_chunks = yaffs_get_n_free_chunks(dev);
  11272. +
  11273. + yaffs_gross_unlock(dev);
  11274. +
  11275. + return (n_free_chunks > 20) ? 1 : 0;
  11276. +}
  11277. +
  11278. +static void yaffs_release_space(struct file *f)
  11279. +{
  11280. + struct yaffs_obj *obj;
  11281. + struct yaffs_dev *dev;
  11282. +
  11283. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11284. +
  11285. + dev = obj->my_dev;
  11286. +
  11287. + yaffs_gross_lock(dev);
  11288. +
  11289. + yaffs_gross_unlock(dev);
  11290. +}
  11291. +
  11292. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  11293. +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
  11294. + loff_t pos, unsigned len, unsigned flags,
  11295. + struct page **pagep, void **fsdata)
  11296. +{
  11297. + struct page *pg = NULL;
  11298. + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  11299. +
  11300. + int ret = 0;
  11301. + int space_held = 0;
  11302. +
  11303. + /* Get a page */
  11304. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
  11305. + pg = grab_cache_page_write_begin(mapping, index, flags);
  11306. +#else
  11307. + pg = __grab_cache_page(mapping, index);
  11308. +#endif
  11309. +
  11310. + *pagep = pg;
  11311. + if (!pg) {
  11312. + ret = -ENOMEM;
  11313. + goto out;
  11314. + }
  11315. + yaffs_trace(YAFFS_TRACE_OS,
  11316. + "start yaffs_write_begin index %d(%x) uptodate %d",
  11317. + (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0);
  11318. +
  11319. + /* Get fs space */
  11320. + space_held = yaffs_hold_space(filp);
  11321. +
  11322. + if (!space_held) {
  11323. + ret = -ENOSPC;
  11324. + goto out;
  11325. + }
  11326. +
  11327. + /* Update page if required */
  11328. +
  11329. + if (!Page_Uptodate(pg))
  11330. + ret = yaffs_readpage_nolock(filp, pg);
  11331. +
  11332. + if (ret)
  11333. + goto out;
  11334. +
  11335. + /* Happy path return */
  11336. + yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok");
  11337. +
  11338. + return 0;
  11339. +
  11340. +out:
  11341. + yaffs_trace(YAFFS_TRACE_OS,
  11342. + "end yaffs_write_begin fail returning %d", ret);
  11343. + if (space_held)
  11344. + yaffs_release_space(filp);
  11345. + if (pg) {
  11346. + unlock_page(pg);
  11347. + page_cache_release(pg);
  11348. + }
  11349. + return ret;
  11350. +}
  11351. +
  11352. +#else
  11353. +
  11354. +static int yaffs_prepare_write(struct file *f, struct page *pg,
  11355. + unsigned offset, unsigned to)
  11356. +{
  11357. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write");
  11358. +
  11359. + if (!Page_Uptodate(pg))
  11360. + return yaffs_readpage_nolock(f, pg);
  11361. + return 0;
  11362. +}
  11363. +#endif
  11364. +
  11365. +
  11366. +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
  11367. + loff_t * pos)
  11368. +{
  11369. + struct yaffs_obj *obj;
  11370. + int n_written;
  11371. + loff_t ipos;
  11372. + struct inode *inode;
  11373. + struct yaffs_dev *dev;
  11374. +
  11375. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11376. +
  11377. + if (!obj) {
  11378. + yaffs_trace(YAFFS_TRACE_OS,
  11379. + "yaffs_file_write: hey obj is null!");
  11380. + return -EINVAL;
  11381. + }
  11382. +
  11383. + dev = obj->my_dev;
  11384. +
  11385. + yaffs_gross_lock(dev);
  11386. +
  11387. + inode = f->f_dentry->d_inode;
  11388. +
  11389. + if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
  11390. + ipos = inode->i_size;
  11391. + else
  11392. + ipos = *pos;
  11393. +
  11394. + yaffs_trace(YAFFS_TRACE_OS,
  11395. + "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
  11396. + (unsigned)n, (unsigned)n, obj->obj_id, ipos);
  11397. +
  11398. + n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
  11399. +
  11400. + yaffs_set_super_dirty(dev);
  11401. +
  11402. + yaffs_trace(YAFFS_TRACE_OS,
  11403. + "yaffs_file_write: %d(%x) bytes written",
  11404. + (unsigned)n, (unsigned)n);
  11405. +
  11406. + if (n_written > 0) {
  11407. + ipos += n_written;
  11408. + *pos = ipos;
  11409. + if (ipos > inode->i_size) {
  11410. + inode->i_size = ipos;
  11411. + inode->i_blocks = (ipos + 511) >> 9;
  11412. +
  11413. + yaffs_trace(YAFFS_TRACE_OS,
  11414. + "yaffs_file_write size updated to %lld bytes, %d blocks",
  11415. + ipos, (int)(inode->i_blocks));
  11416. + }
  11417. +
  11418. + }
  11419. + yaffs_gross_unlock(dev);
  11420. + return (n_written == 0) && (n > 0) ? -ENOSPC : n_written;
  11421. +}
  11422. +
  11423. +
  11424. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  11425. +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
  11426. + loff_t pos, unsigned len, unsigned copied,
  11427. + struct page *pg, void *fsdadata)
  11428. +{
  11429. + int ret = 0;
  11430. + void *addr, *kva;
  11431. + uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
  11432. +
  11433. + kva = kmap(pg);
  11434. + addr = kva + offset_into_page;
  11435. +
  11436. + yaffs_trace(YAFFS_TRACE_OS,
  11437. + "yaffs_write_end addr %p pos %lld n_bytes %d",
  11438. + addr, pos, copied);
  11439. +
  11440. + ret = yaffs_file_write(filp, addr, copied, &pos);
  11441. +
  11442. + if (ret != copied) {
  11443. + yaffs_trace(YAFFS_TRACE_OS,
  11444. + "yaffs_write_end not same size ret %d copied %d",
  11445. + ret, copied);
  11446. + SetPageError(pg);
  11447. + }
  11448. +
  11449. + kunmap(pg);
  11450. +
  11451. + yaffs_release_space(filp);
  11452. + unlock_page(pg);
  11453. + page_cache_release(pg);
  11454. + return ret;
  11455. +}
  11456. +#else
  11457. +
  11458. +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
  11459. + unsigned to)
  11460. +{
  11461. + void *addr, *kva;
  11462. +
  11463. + loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
  11464. + int n_bytes = to - offset;
  11465. + int n_written;
  11466. +
  11467. + kva = kmap(pg);
  11468. + addr = kva + offset;
  11469. +
  11470. + yaffs_trace(YAFFS_TRACE_OS,
  11471. + "yaffs_commit_write addr %p pos %lld n_bytes %d",
  11472. + addr, pos, n_bytes);
  11473. +
  11474. + n_written = yaffs_file_write(f, addr, n_bytes, &pos);
  11475. +
  11476. + if (n_written != n_bytes) {
  11477. + yaffs_trace(YAFFS_TRACE_OS,
  11478. + "yaffs_commit_write not same size n_written %d n_bytes %d",
  11479. + n_written, n_bytes);
  11480. + SetPageError(pg);
  11481. + }
  11482. + kunmap(pg);
  11483. +
  11484. + yaffs_trace(YAFFS_TRACE_OS,
  11485. + "yaffs_commit_write returning %d",
  11486. + n_written == n_bytes ? 0 : n_written);
  11487. +
  11488. + return n_written == n_bytes ? 0 : n_written;
  11489. +}
  11490. +#endif
  11491. +
  11492. +static struct address_space_operations yaffs_file_address_operations = {
  11493. + .readpage = yaffs_readpage,
  11494. + .writepage = yaffs_writepage,
  11495. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  11496. + .write_begin = yaffs_write_begin,
  11497. + .write_end = yaffs_write_end,
  11498. +#else
  11499. + .prepare_write = yaffs_prepare_write,
  11500. + .commit_write = yaffs_commit_write,
  11501. +#endif
  11502. +};
  11503. +
  11504. +
  11505. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  11506. +static int yaffs_file_flush(struct file *file, fl_owner_t id)
  11507. +#else
  11508. +static int yaffs_file_flush(struct file *file)
  11509. +#endif
  11510. +{
  11511. + struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
  11512. +
  11513. + struct yaffs_dev *dev = obj->my_dev;
  11514. +
  11515. + yaffs_trace(YAFFS_TRACE_OS,
  11516. + "yaffs_file_flush object %d (%s)",
  11517. + obj->obj_id,
  11518. + obj->dirty ? "dirty" : "clean");
  11519. +
  11520. + yaffs_gross_lock(dev);
  11521. +
  11522. + yaffs_flush_file(obj, 1, 0, 0);
  11523. +
  11524. + yaffs_gross_unlock(dev);
  11525. +
  11526. + return 0;
  11527. +}
  11528. +
  11529. +
  11530. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  11531. +static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync)
  11532. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
  11533. +static int yaffs_sync_object(struct file *file, int datasync)
  11534. +#else
  11535. +static int yaffs_sync_object(struct file *file, struct dentry *dentry,
  11536. + int datasync)
  11537. +#endif
  11538. +{
  11539. + struct yaffs_obj *obj;
  11540. + struct yaffs_dev *dev;
  11541. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
  11542. + struct dentry *dentry = file->f_path.dentry;
  11543. +#endif
  11544. +
  11545. + obj = yaffs_dentry_to_obj(dentry);
  11546. +
  11547. + dev = obj->my_dev;
  11548. +
  11549. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
  11550. + "yaffs_sync_object");
  11551. + yaffs_gross_lock(dev);
  11552. + yaffs_flush_file(obj, 1, datasync, 0);
  11553. + yaffs_gross_unlock(dev);
  11554. + return 0;
  11555. +}
  11556. +
  11557. +
  11558. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
  11559. +static const struct file_operations yaffs_file_operations = {
  11560. + .read = do_sync_read,
  11561. + .write = do_sync_write,
  11562. + .read_iter = generic_file_read_iter,
  11563. + .write_iter = generic_file_write_iter,
  11564. + .mmap = generic_file_mmap,
  11565. + .flush = yaffs_file_flush,
  11566. + .fsync = yaffs_sync_object,
  11567. + .splice_read = generic_file_splice_read,
  11568. + .splice_write = iter_file_splice_write,
  11569. + .llseek = generic_file_llseek,
  11570. +};
  11571. +
  11572. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
  11573. +
  11574. +static const struct file_operations yaffs_file_operations = {
  11575. + .read = do_sync_read,
  11576. + .write = do_sync_write,
  11577. + .aio_read = generic_file_aio_read,
  11578. + .aio_write = generic_file_aio_write,
  11579. + .mmap = generic_file_mmap,
  11580. + .flush = yaffs_file_flush,
  11581. + .fsync = yaffs_sync_object,
  11582. + .sendfile = generic_file_sendfile,
  11583. +};
  11584. +
  11585. +#else
  11586. +
  11587. +static const struct file_operations yaffs_file_operations = {
  11588. + .read = generic_file_read,
  11589. + .write = generic_file_write,
  11590. + .mmap = generic_file_mmap,
  11591. + .flush = yaffs_file_flush,
  11592. + .fsync = yaffs_sync_object,
  11593. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11594. + .sendfile = generic_file_sendfile,
  11595. +#endif
  11596. +};
  11597. +#endif
  11598. +
  11599. +
  11600. +
  11601. +
  11602. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
  11603. +static void zero_user_segment(struct page *page, unsigned start, unsigned end)
  11604. +{
  11605. + void *kaddr = kmap_atomic(page, KM_USER0);
  11606. + memset(kaddr + start, 0, end - start);
  11607. + kunmap_atomic(kaddr, KM_USER0);
  11608. + flush_dcache_page(page);
  11609. +}
  11610. +#endif
  11611. +
  11612. +
  11613. +static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
  11614. +{
  11615. +#ifdef YAFFS_USE_TRUNCATE_SETSIZE
  11616. + truncate_setsize(inode, newsize);
  11617. + return 0;
  11618. +#else
  11619. + truncate_inode_pages(&inode->i_data, newsize);
  11620. + return 0;
  11621. +#endif
  11622. +
  11623. +}
  11624. +
  11625. +
  11626. +static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
  11627. +{
  11628. +#ifdef YAFFS_USE_SETATTR_COPY
  11629. + setattr_copy(inode, attr);
  11630. + return 0;
  11631. +#else
  11632. + return inode_setattr(inode, attr);
  11633. +#endif
  11634. +
  11635. +}
  11636. +
  11637. +static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
  11638. +{
  11639. + struct inode *inode = dentry->d_inode;
  11640. + int error = 0;
  11641. + struct yaffs_dev *dev;
  11642. +
  11643. + yaffs_trace(YAFFS_TRACE_OS,
  11644. + "yaffs_setattr of object %d",
  11645. + yaffs_inode_to_obj(inode)->obj_id);
  11646. +#if 0
  11647. + /* Fail if a requested resize >= 2GB */
  11648. + if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
  11649. + error = -EINVAL;
  11650. +#endif
  11651. +
  11652. + if (error == 0)
  11653. + error = inode_change_ok(inode, attr);
  11654. + if (error == 0) {
  11655. + int result;
  11656. + if (!error) {
  11657. + error = yaffs_vfs_setattr(inode, attr);
  11658. + yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called");
  11659. + if (attr->ia_valid & ATTR_SIZE) {
  11660. + yaffs_vfs_setsize(inode, attr->ia_size);
  11661. + inode->i_blocks = (inode->i_size + 511) >> 9;
  11662. + }
  11663. + }
  11664. + dev = yaffs_inode_to_obj(inode)->my_dev;
  11665. + if (attr->ia_valid & ATTR_SIZE) {
  11666. + yaffs_trace(YAFFS_TRACE_OS,
  11667. + "resize to %d(%x)",
  11668. + (int)(attr->ia_size),
  11669. + (int)(attr->ia_size));
  11670. + }
  11671. + yaffs_gross_lock(dev);
  11672. + result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr);
  11673. + if (result == YAFFS_OK) {
  11674. + error = 0;
  11675. + } else {
  11676. + error = -EPERM;
  11677. + }
  11678. + yaffs_gross_unlock(dev);
  11679. +
  11680. + }
  11681. +
  11682. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error);
  11683. +
  11684. + return error;
  11685. +}
  11686. +
  11687. +static int yaffs_setxattr(struct dentry *dentry, const char *name,
  11688. + const void *value, size_t size, int flags)
  11689. +{
  11690. + struct inode *inode = dentry->d_inode;
  11691. + int error = 0;
  11692. + struct yaffs_dev *dev;
  11693. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  11694. +
  11695. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id);
  11696. +
  11697. + if (error == 0) {
  11698. + int result;
  11699. + dev = obj->my_dev;
  11700. + yaffs_gross_lock(dev);
  11701. + result = yaffs_set_xattrib(obj, name, value, size, flags);
  11702. + if (result == YAFFS_OK)
  11703. + error = 0;
  11704. + else if (result < 0)
  11705. + error = result;
  11706. + yaffs_gross_unlock(dev);
  11707. +
  11708. + }
  11709. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error);
  11710. +
  11711. + return error;
  11712. +}
  11713. +
  11714. +static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name,
  11715. + void *buff, size_t size)
  11716. +{
  11717. + struct inode *inode = dentry->d_inode;
  11718. + int error = 0;
  11719. + struct yaffs_dev *dev;
  11720. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  11721. +
  11722. + yaffs_trace(YAFFS_TRACE_OS,
  11723. + "yaffs_getxattr \"%s\" from object %d",
  11724. + name, obj->obj_id);
  11725. +
  11726. + if (error == 0) {
  11727. + dev = obj->my_dev;
  11728. + yaffs_gross_lock(dev);
  11729. + error = yaffs_get_xattrib(obj, name, buff, size);
  11730. + yaffs_gross_unlock(dev);
  11731. +
  11732. + }
  11733. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error);
  11734. +
  11735. + return error;
  11736. +}
  11737. +
  11738. +static int yaffs_removexattr(struct dentry *dentry, const char *name)
  11739. +{
  11740. + struct inode *inode = dentry->d_inode;
  11741. + int error = 0;
  11742. + struct yaffs_dev *dev;
  11743. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  11744. +
  11745. + yaffs_trace(YAFFS_TRACE_OS,
  11746. + "yaffs_removexattr of object %d", obj->obj_id);
  11747. +
  11748. + if (error == 0) {
  11749. + int result;
  11750. + dev = obj->my_dev;
  11751. + yaffs_gross_lock(dev);
  11752. + result = yaffs_remove_xattrib(obj, name);
  11753. + if (result == YAFFS_OK)
  11754. + error = 0;
  11755. + else if (result < 0)
  11756. + error = result;
  11757. + yaffs_gross_unlock(dev);
  11758. +
  11759. + }
  11760. + yaffs_trace(YAFFS_TRACE_OS,
  11761. + "yaffs_removexattr done returning %d", error);
  11762. +
  11763. + return error;
  11764. +}
  11765. +
  11766. +static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size)
  11767. +{
  11768. + struct inode *inode = dentry->d_inode;
  11769. + int error = 0;
  11770. + struct yaffs_dev *dev;
  11771. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  11772. +
  11773. + yaffs_trace(YAFFS_TRACE_OS,
  11774. + "yaffs_listxattr of object %d", obj->obj_id);
  11775. +
  11776. + if (error == 0) {
  11777. + dev = obj->my_dev;
  11778. + yaffs_gross_lock(dev);
  11779. + error = yaffs_list_xattrib(obj, buff, size);
  11780. + yaffs_gross_unlock(dev);
  11781. +
  11782. + }
  11783. + yaffs_trace(YAFFS_TRACE_OS,
  11784. + "yaffs_listxattr done returning %d", error);
  11785. +
  11786. + return error;
  11787. +}
  11788. +
  11789. +
  11790. +static const struct inode_operations yaffs_file_inode_operations = {
  11791. + .setattr = yaffs_setattr,
  11792. + .setxattr = yaffs_setxattr,
  11793. + .getxattr = yaffs_getxattr,
  11794. + .listxattr = yaffs_listxattr,
  11795. + .removexattr = yaffs_removexattr,
  11796. +};
  11797. +
  11798. +
  11799. +static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
  11800. + int buflen)
  11801. +{
  11802. + unsigned char *alias;
  11803. + int ret;
  11804. +
  11805. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  11806. +
  11807. + yaffs_gross_lock(dev);
  11808. +
  11809. + alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
  11810. +
  11811. + yaffs_gross_unlock(dev);
  11812. +
  11813. + if (!alias)
  11814. + return -ENOMEM;
  11815. +
  11816. +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
  11817. + ret = vfs_readlink(dentry, buffer, buflen, alias);
  11818. +#else
  11819. + ret = readlink_copy(buffer, buflen, alias);
  11820. +#endif
  11821. + kfree(alias);
  11822. + return ret;
  11823. +}
  11824. +
  11825. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  11826. +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
  11827. +{
  11828. + void *ret;
  11829. +#else
  11830. +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
  11831. +{
  11832. + int ret
  11833. +#endif
  11834. + unsigned char *alias;
  11835. + int ret_int = 0;
  11836. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  11837. +
  11838. + yaffs_gross_lock(dev);
  11839. +
  11840. + alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
  11841. + yaffs_gross_unlock(dev);
  11842. +
  11843. + if (!alias) {
  11844. + ret_int = -ENOMEM;
  11845. + goto out;
  11846. + }
  11847. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  11848. + nd_set_link(nd, alias);
  11849. + ret = alias;
  11850. +out:
  11851. + if (ret_int)
  11852. + ret = ERR_PTR(ret_int);
  11853. + return ret;
  11854. +#else
  11855. + ret = vfs_follow_link(nd, alias);
  11856. + kfree(alias);
  11857. +out:
  11858. + if (ret_int)
  11859. + ret = ret_int;
  11860. + return ret;
  11861. +#endif
  11862. +}
  11863. +
  11864. +
  11865. +#ifdef YAFFS_HAS_PUT_INODE
  11866. +
  11867. +/* For now put inode is just for debugging
  11868. + * Put inode is called when the inode **structure** is put.
  11869. + */
  11870. +static void yaffs_put_inode(struct inode *inode)
  11871. +{
  11872. + yaffs_trace(YAFFS_TRACE_OS,
  11873. + "yaffs_put_inode: ino %d, count %d"),
  11874. + (int)inode->i_ino, atomic_read(&inode->i_count);
  11875. +
  11876. +}
  11877. +#endif
  11878. +
  11879. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  11880. +void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias)
  11881. +{
  11882. + kfree(alias);
  11883. +}
  11884. +#endif
  11885. +
  11886. +static const struct inode_operations yaffs_symlink_inode_operations = {
  11887. + .readlink = yaffs_readlink,
  11888. + .follow_link = yaffs_follow_link,
  11889. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  11890. + .put_link = yaffs_put_link,
  11891. +#endif
  11892. + .setattr = yaffs_setattr,
  11893. + .setxattr = yaffs_setxattr,
  11894. + .getxattr = yaffs_getxattr,
  11895. + .listxattr = yaffs_listxattr,
  11896. + .removexattr = yaffs_removexattr,
  11897. +};
  11898. +
  11899. +#ifdef YAFFS_USE_OWN_IGET
  11900. +
  11901. +static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
  11902. +{
  11903. + struct inode *inode;
  11904. + struct yaffs_obj *obj;
  11905. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  11906. +
  11907. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino);
  11908. +
  11909. + inode = iget_locked(sb, ino);
  11910. + if (!inode)
  11911. + return ERR_PTR(-ENOMEM);
  11912. + if (!(inode->i_state & I_NEW))
  11913. + return inode;
  11914. +
  11915. + /* NB This is called as a side effect of other functions, but
  11916. + * we had to release the lock to prevent deadlocks, so
  11917. + * need to lock again.
  11918. + */
  11919. +
  11920. + yaffs_gross_lock(dev);
  11921. +
  11922. + obj = yaffs_find_by_number(dev, inode->i_ino);
  11923. +
  11924. + yaffs_fill_inode_from_obj(inode, obj);
  11925. +
  11926. + yaffs_gross_unlock(dev);
  11927. +
  11928. + unlock_new_inode(inode);
  11929. + return inode;
  11930. +}
  11931. +
  11932. +#else
  11933. +
  11934. +static void yaffs_read_inode(struct inode *inode)
  11935. +{
  11936. + /* NB This is called as a side effect of other functions, but
  11937. + * we had to release the lock to prevent deadlocks, so
  11938. + * need to lock again.
  11939. + */
  11940. +
  11941. + struct yaffs_obj *obj;
  11942. + struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb);
  11943. +
  11944. + yaffs_trace(YAFFS_TRACE_OS,
  11945. + "yaffs_read_inode for %d", (int)inode->i_ino);
  11946. +
  11947. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  11948. + yaffs_gross_lock(dev);
  11949. +
  11950. + obj = yaffs_find_by_number(dev, inode->i_ino);
  11951. +
  11952. + yaffs_fill_inode_from_obj(inode, obj);
  11953. +
  11954. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  11955. + yaffs_gross_unlock(dev);
  11956. +}
  11957. +
  11958. +#endif
  11959. +
  11960. +
  11961. +
  11962. +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
  11963. + struct yaffs_obj *obj)
  11964. +{
  11965. + struct inode *inode;
  11966. +
  11967. + if (!sb) {
  11968. + yaffs_trace(YAFFS_TRACE_OS,
  11969. + "yaffs_get_inode for NULL super_block!!");
  11970. + return NULL;
  11971. +
  11972. + }
  11973. +
  11974. + if (!obj) {
  11975. + yaffs_trace(YAFFS_TRACE_OS,
  11976. + "yaffs_get_inode for NULL object!!");
  11977. + return NULL;
  11978. +
  11979. + }
  11980. +
  11981. + yaffs_trace(YAFFS_TRACE_OS,
  11982. + "yaffs_get_inode for object %d", obj->obj_id);
  11983. +
  11984. + inode = Y_IGET(sb, obj->obj_id);
  11985. + if (IS_ERR(inode))
  11986. + return NULL;
  11987. +
  11988. + /* NB Side effect: iget calls back to yaffs_read_inode(). */
  11989. + /* iget also increments the inode's i_count */
  11990. + /* NB You can't be holding gross_lock or deadlock will happen! */
  11991. +
  11992. + return inode;
  11993. +}
  11994. +
  11995. +
  11996. +
  11997. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
  11998. +#define YCRED(x) x
  11999. +#else
  12000. +#define YCRED(x) (x->cred)
  12001. +#endif
  12002. +
  12003. +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
  12004. +#define YPROC_uid(p) (YCRED(p)->fsuid)
  12005. +#define YPROC_gid(p) (YCRED(p)->fsgid)
  12006. +#define EXTRACT_gid(x) x
  12007. +#define EXTRACT_uid(x) x
  12008. +#define MAKE_gid(x) x
  12009. +#define MAKE_uid(x) x
  12010. +#else
  12011. +#define YPROC_uid(p) from_kuid(&init_user_ns, YCRED(p)->fsuid)
  12012. +#define YPROC_gid(p) from_kgid(&init_user_ns, YCRED(p)->fsgid)
  12013. +#define EXTRACT_gid(x) from_kgid(&init_user_ns, x)
  12014. +#define EXTRACT_uid(x) from_kuid(&init_user_ns, x)
  12015. +#define MAKE_gid(x) make_kgid(&init_user_ns, x)
  12016. +#define MAKE_uid(x) make_kuid(&init_user_ns, x)
  12017. +#endif
  12018. +
  12019. +
  12020. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  12021. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
  12022. + dev_t rdev)
  12023. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12024. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
  12025. + dev_t rdev)
  12026. +#else
  12027. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
  12028. + int rdev)
  12029. +#endif
  12030. +{
  12031. + struct inode *inode;
  12032. +
  12033. + struct yaffs_obj *obj = NULL;
  12034. + struct yaffs_dev *dev;
  12035. +
  12036. + struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
  12037. +
  12038. + int error = -ENOSPC;
  12039. + uid_t uid = YPROC_uid(current);
  12040. + gid_t gid =
  12041. + (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
  12042. +
  12043. + if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
  12044. + mode |= S_ISGID;
  12045. +
  12046. + if (parent) {
  12047. + yaffs_trace(YAFFS_TRACE_OS,
  12048. + "yaffs_mknod: parent object %d type %d",
  12049. + parent->obj_id, parent->variant_type);
  12050. + } else {
  12051. + yaffs_trace(YAFFS_TRACE_OS,
  12052. + "yaffs_mknod: could not get parent object");
  12053. + return -EPERM;
  12054. + }
  12055. +
  12056. + yaffs_trace(YAFFS_TRACE_OS,
  12057. + "yaffs_mknod: making oject for %s, mode %x dev %x",
  12058. + dentry->d_name.name, mode, rdev);
  12059. +
  12060. + dev = parent->my_dev;
  12061. +
  12062. + yaffs_gross_lock(dev);
  12063. +
  12064. + switch (mode & S_IFMT) {
  12065. + default:
  12066. + /* Special (socket, fifo, device...) */
  12067. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making special");
  12068. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12069. + obj =
  12070. + yaffs_create_special(parent, dentry->d_name.name, mode, uid,
  12071. + gid, old_encode_dev(rdev));
  12072. +#else
  12073. + obj =
  12074. + yaffs_create_special(parent, dentry->d_name.name, mode, uid,
  12075. + gid, rdev);
  12076. +#endif
  12077. + break;
  12078. + case S_IFREG: /* file */
  12079. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making file");
  12080. + obj = yaffs_create_file(parent, dentry->d_name.name, mode, uid,
  12081. + gid);
  12082. + break;
  12083. + case S_IFDIR: /* directory */
  12084. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making directory");
  12085. + obj = yaffs_create_dir(parent, dentry->d_name.name, mode,
  12086. + uid, gid);
  12087. + break;
  12088. + case S_IFLNK: /* symlink */
  12089. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink");
  12090. + obj = NULL; /* Do we ever get here? */
  12091. + break;
  12092. + }
  12093. +
  12094. + /* Can not call yaffs_get_inode() with gross lock held */
  12095. + yaffs_gross_unlock(dev);
  12096. +
  12097. + if (obj) {
  12098. + inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
  12099. + d_instantiate(dentry, inode);
  12100. + update_dir_time(dir);
  12101. + yaffs_trace(YAFFS_TRACE_OS,
  12102. + "yaffs_mknod created object %d count = %d",
  12103. + obj->obj_id, atomic_read(&inode->i_count));
  12104. + error = 0;
  12105. + yaffs_fill_inode_from_obj(dir, parent);
  12106. + } else {
  12107. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object");
  12108. + error = -ENOMEM;
  12109. + }
  12110. +
  12111. + return error;
  12112. +}
  12113. +
  12114. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  12115. +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  12116. +#else
  12117. +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  12118. +#endif
  12119. +{
  12120. + int ret_val;
  12121. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir");
  12122. + ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
  12123. + return ret_val;
  12124. +}
  12125. +
  12126. +
  12127. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  12128. +static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  12129. + bool dummy)
  12130. +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  12131. +static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  12132. + struct nameidata *n)
  12133. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12134. +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
  12135. + struct nameidata *n)
  12136. +#else
  12137. +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
  12138. +#endif
  12139. +{
  12140. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_create");
  12141. + return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
  12142. +}
  12143. +
  12144. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  12145. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
  12146. + unsigned int dummy)
  12147. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12148. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
  12149. + struct nameidata *n)
  12150. +#else
  12151. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
  12152. +#endif
  12153. +{
  12154. + struct yaffs_obj *obj;
  12155. + struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */
  12156. +
  12157. + struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev;
  12158. +
  12159. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  12160. + yaffs_gross_lock(dev);
  12161. +
  12162. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s",
  12163. + yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name);
  12164. +
  12165. + obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name);
  12166. +
  12167. + obj = yaffs_get_equivalent_obj(obj); /* in case it was a hardlink */
  12168. +
  12169. + /* Can't hold gross lock when calling yaffs_get_inode() */
  12170. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  12171. + yaffs_gross_unlock(dev);
  12172. +
  12173. + if (obj) {
  12174. + yaffs_trace(YAFFS_TRACE_OS,
  12175. + "yaffs_lookup found %d", obj->obj_id);
  12176. +
  12177. + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
  12178. + } else {
  12179. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found");
  12180. +
  12181. + }
  12182. +
  12183. +/* added NCB for 2.5/6 compatability - forces add even if inode is
  12184. + * NULL which creates dentry hash */
  12185. + d_add(dentry, inode);
  12186. +
  12187. + return NULL;
  12188. +}
  12189. +
  12190. +/*
  12191. + * Create a link...
  12192. + */
  12193. +static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
  12194. + struct dentry *dentry)
  12195. +{
  12196. + struct inode *inode = old_dentry->d_inode;
  12197. + struct yaffs_obj *obj = NULL;
  12198. + struct yaffs_obj *link = NULL;
  12199. + struct yaffs_dev *dev;
  12200. +
  12201. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_link");
  12202. +
  12203. + obj = yaffs_inode_to_obj(inode);
  12204. + dev = obj->my_dev;
  12205. +
  12206. + yaffs_gross_lock(dev);
  12207. +
  12208. + if (!S_ISDIR(inode->i_mode)) /* Don't link directories */
  12209. + link =
  12210. + yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name,
  12211. + obj);
  12212. +
  12213. + if (link) {
  12214. + set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj));
  12215. + d_instantiate(dentry, old_dentry->d_inode);
  12216. + atomic_inc(&old_dentry->d_inode->i_count);
  12217. + yaffs_trace(YAFFS_TRACE_OS,
  12218. + "yaffs_link link count %d i_count %d",
  12219. + old_dentry->d_inode->i_nlink,
  12220. + atomic_read(&old_dentry->d_inode->i_count));
  12221. + }
  12222. +
  12223. + yaffs_gross_unlock(dev);
  12224. +
  12225. + if (link) {
  12226. + update_dir_time(dir);
  12227. + return 0;
  12228. + }
  12229. +
  12230. + return -EPERM;
  12231. +}
  12232. +
  12233. +static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
  12234. + const char *symname)
  12235. +{
  12236. + struct yaffs_obj *obj;
  12237. + struct yaffs_dev *dev;
  12238. + uid_t uid = YPROC_uid(current);
  12239. + gid_t gid =
  12240. + (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
  12241. +
  12242. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
  12243. +
  12244. + if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) >
  12245. + YAFFS_MAX_NAME_LENGTH)
  12246. + return -ENAMETOOLONG;
  12247. +
  12248. + if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) >
  12249. + YAFFS_MAX_ALIAS_LENGTH)
  12250. + return -ENAMETOOLONG;
  12251. +
  12252. + dev = yaffs_inode_to_obj(dir)->my_dev;
  12253. + yaffs_gross_lock(dev);
  12254. + obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name,
  12255. + S_IFLNK | S_IRWXUGO, uid, gid, symname);
  12256. + yaffs_gross_unlock(dev);
  12257. +
  12258. + if (obj) {
  12259. + struct inode *inode;
  12260. +
  12261. + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
  12262. + d_instantiate(dentry, inode);
  12263. + update_dir_time(dir);
  12264. + yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
  12265. + return 0;
  12266. + } else {
  12267. + yaffs_trace(YAFFS_TRACE_OS, "symlink not created");
  12268. + }
  12269. +
  12270. + return -ENOMEM;
  12271. +}
  12272. +
  12273. +/*
  12274. + * The VFS layer already does all the dentry stuff for rename.
  12275. + *
  12276. + * NB: POSIX says you can rename an object over an old object of the same name
  12277. + */
  12278. +static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
  12279. + struct inode *new_dir, struct dentry *new_dentry)
  12280. +{
  12281. + struct yaffs_dev *dev;
  12282. + int ret_val = YAFFS_FAIL;
  12283. + struct yaffs_obj *target;
  12284. +
  12285. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename");
  12286. + dev = yaffs_inode_to_obj(old_dir)->my_dev;
  12287. +
  12288. + yaffs_gross_lock(dev);
  12289. +
  12290. + /* Check if the target is an existing directory that is not empty. */
  12291. + target = yaffs_find_by_name(yaffs_inode_to_obj(new_dir),
  12292. + new_dentry->d_name.name);
  12293. +
  12294. + if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
  12295. + !list_empty(&target->variant.dir_variant.children)) {
  12296. +
  12297. + yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir");
  12298. +
  12299. + ret_val = YAFFS_FAIL;
  12300. + } else {
  12301. + /* Now does unlinking internally using shadowing mechanism */
  12302. + yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj");
  12303. +
  12304. + ret_val = yaffs_rename_obj(yaffs_inode_to_obj(old_dir),
  12305. + old_dentry->d_name.name,
  12306. + yaffs_inode_to_obj(new_dir),
  12307. + new_dentry->d_name.name);
  12308. + }
  12309. + yaffs_gross_unlock(dev);
  12310. +
  12311. + if (ret_val == YAFFS_OK) {
  12312. + if (target)
  12313. + inode_dec_link_count(new_dentry->d_inode);
  12314. +
  12315. + update_dir_time(old_dir);
  12316. + if (old_dir != new_dir)
  12317. + update_dir_time(new_dir);
  12318. + return 0;
  12319. + } else {
  12320. + return -ENOTEMPTY;
  12321. + }
  12322. +}
  12323. +
  12324. +
  12325. +
  12326. +
  12327. +static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
  12328. +{
  12329. + int ret_val;
  12330. +
  12331. + struct yaffs_dev *dev;
  12332. + struct yaffs_obj *obj;
  12333. +
  12334. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_unlink %d:%s",
  12335. + (int)(dir->i_ino), dentry->d_name.name);
  12336. + obj = yaffs_inode_to_obj(dir);
  12337. + dev = obj->my_dev;
  12338. +
  12339. + yaffs_gross_lock(dev);
  12340. +
  12341. + ret_val = yaffs_unlinker(obj, dentry->d_name.name);
  12342. +
  12343. + if (ret_val == YAFFS_OK) {
  12344. + inode_dec_link_count(dentry->d_inode);
  12345. + dir->i_version++;
  12346. + yaffs_gross_unlock(dev);
  12347. + update_dir_time(dir);
  12348. + return 0;
  12349. + }
  12350. + yaffs_gross_unlock(dev);
  12351. + return -ENOTEMPTY;
  12352. +}
  12353. +
  12354. +
  12355. +
  12356. +static const struct inode_operations yaffs_dir_inode_operations = {
  12357. + .create = yaffs_create,
  12358. + .lookup = yaffs_lookup,
  12359. + .link = yaffs_link,
  12360. + .unlink = yaffs_unlink,
  12361. + .symlink = yaffs_symlink,
  12362. + .mkdir = yaffs_mkdir,
  12363. + .rmdir = yaffs_unlink,
  12364. + .mknod = yaffs_mknod,
  12365. + .rename = yaffs_rename,
  12366. + .setattr = yaffs_setattr,
  12367. + .setxattr = yaffs_setxattr,
  12368. + .getxattr = yaffs_getxattr,
  12369. + .listxattr = yaffs_listxattr,
  12370. + .removexattr = yaffs_removexattr,
  12371. +};
  12372. +
  12373. +/*-----------------------------------------------------------------*/
  12374. +/* Directory search context allows us to unlock access to yaffs during
  12375. + * filldir without causing problems with the directory being modified.
  12376. + * This is similar to the tried and tested mechanism used in yaffs direct.
  12377. + *
  12378. + * A search context iterates along a doubly linked list of siblings in the
  12379. + * directory. If the iterating object is deleted then this would corrupt
  12380. + * the list iteration, likely causing a crash. The search context avoids
  12381. + * this by using the remove_obj_fn to move the search context to the
  12382. + * next object before the object is deleted.
  12383. + *
  12384. + * Many readdirs (and thus seach conexts) may be alive simulateously so
  12385. + * each struct yaffs_dev has a list of these.
  12386. + *
  12387. + * A seach context lives for the duration of a readdir.
  12388. + *
  12389. + * All these functions must be called while yaffs is locked.
  12390. + */
  12391. +
  12392. +struct yaffs_search_context {
  12393. + struct yaffs_dev *dev;
  12394. + struct yaffs_obj *dir_obj;
  12395. + struct yaffs_obj *next_return;
  12396. + struct list_head others;
  12397. +};
  12398. +
  12399. +/*
  12400. + * yaffs_new_search() creates a new search context, initialises it and
  12401. + * adds it to the device's search context list.
  12402. + *
  12403. + * Called at start of readdir.
  12404. + */
  12405. +static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir)
  12406. +{
  12407. + struct yaffs_dev *dev = dir->my_dev;
  12408. + struct yaffs_search_context *sc =
  12409. + kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS);
  12410. + if (sc) {
  12411. + sc->dir_obj = dir;
  12412. + sc->dev = dev;
  12413. + if (list_empty(&sc->dir_obj->variant.dir_variant.children))
  12414. + sc->next_return = NULL;
  12415. + else
  12416. + sc->next_return =
  12417. + list_entry(dir->variant.dir_variant.children.next,
  12418. + struct yaffs_obj, siblings);
  12419. + INIT_LIST_HEAD(&sc->others);
  12420. + list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts));
  12421. + }
  12422. + return sc;
  12423. +}
  12424. +
  12425. +/*
  12426. + * yaffs_search_end() disposes of a search context and cleans up.
  12427. + */
  12428. +static void yaffs_search_end(struct yaffs_search_context *sc)
  12429. +{
  12430. + if (sc) {
  12431. + list_del(&sc->others);
  12432. + kfree(sc);
  12433. + }
  12434. +}
  12435. +
  12436. +/*
  12437. + * yaffs_search_advance() moves a search context to the next object.
  12438. + * Called when the search iterates or when an object removal causes
  12439. + * the search context to be moved to the next object.
  12440. + */
  12441. +static void yaffs_search_advance(struct yaffs_search_context *sc)
  12442. +{
  12443. + if (!sc)
  12444. + return;
  12445. +
  12446. + if (sc->next_return == NULL ||
  12447. + list_empty(&sc->dir_obj->variant.dir_variant.children))
  12448. + sc->next_return = NULL;
  12449. + else {
  12450. + struct list_head *next = sc->next_return->siblings.next;
  12451. +
  12452. + if (next == &sc->dir_obj->variant.dir_variant.children)
  12453. + sc->next_return = NULL; /* end of list */
  12454. + else
  12455. + sc->next_return =
  12456. + list_entry(next, struct yaffs_obj, siblings);
  12457. + }
  12458. +}
  12459. +
  12460. +/*
  12461. + * yaffs_remove_obj_callback() is called when an object is unlinked.
  12462. + * We check open search contexts and advance any which are currently
  12463. + * on the object being iterated.
  12464. + */
  12465. +static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
  12466. +{
  12467. +
  12468. + struct list_head *i;
  12469. + struct yaffs_search_context *sc;
  12470. + struct list_head *search_contexts =
  12471. + &(yaffs_dev_to_lc(obj->my_dev)->search_contexts);
  12472. +
  12473. + /* Iterate through the directory search contexts.
  12474. + * If any are currently on the object being removed, then advance
  12475. + * the search context to the next object to prevent a hanging pointer.
  12476. + */
  12477. + list_for_each(i, search_contexts) {
  12478. + sc = list_entry(i, struct yaffs_search_context, others);
  12479. + if (sc->next_return == obj)
  12480. + yaffs_search_advance(sc);
  12481. + }
  12482. +
  12483. +}
  12484. +
  12485. +
  12486. +/*-----------------------------------------------------------------*/
  12487. +
  12488. +#ifdef YAFFS_USE_DIR_ITERATE
  12489. +static int yaffs_iterate(struct file *f, struct dir_context *dc)
  12490. +{
  12491. + struct yaffs_obj *obj;
  12492. + struct yaffs_dev *dev;
  12493. + struct yaffs_search_context *sc;
  12494. + unsigned long curoffs;
  12495. + struct yaffs_obj *l;
  12496. + int ret_val = 0;
  12497. +
  12498. + char name[YAFFS_MAX_NAME_LENGTH + 1];
  12499. +
  12500. + obj = yaffs_dentry_to_obj(f->f_dentry);
  12501. + dev = obj->my_dev;
  12502. +
  12503. + yaffs_gross_lock(dev);
  12504. +
  12505. + yaffs_dev_to_lc(dev)->readdir_process = current;
  12506. +
  12507. + sc = yaffs_new_search(obj);
  12508. + if (!sc) {
  12509. + ret_val = -ENOMEM;
  12510. + goto out;
  12511. + }
  12512. +
  12513. + if (!dir_emit_dots(f, dc))
  12514. + return 0;
  12515. +
  12516. + curoffs = 1;
  12517. +
  12518. + while (sc->next_return) {
  12519. + curoffs++;
  12520. + l = sc->next_return;
  12521. + if (curoffs >= dc->pos) {
  12522. + int this_inode = yaffs_get_obj_inode(l);
  12523. + int this_type = yaffs_get_obj_type(l);
  12524. +
  12525. + yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
  12526. + yaffs_trace(YAFFS_TRACE_OS,
  12527. + "yaffs_readdir: %s inode %d",
  12528. + name, yaffs_get_obj_inode(l));
  12529. +
  12530. + yaffs_gross_unlock(dev);
  12531. +
  12532. + if (!dir_emit(dc,
  12533. + name,
  12534. + strlen(name),
  12535. + this_inode,
  12536. + this_type)) {
  12537. + yaffs_gross_lock(dev);
  12538. + goto out;
  12539. + }
  12540. +
  12541. + yaffs_gross_lock(dev);
  12542. +
  12543. + dc->pos++;
  12544. + f->f_pos++;
  12545. + }
  12546. + yaffs_search_advance(sc);
  12547. + }
  12548. +
  12549. +out:
  12550. + yaffs_search_end(sc);
  12551. + yaffs_dev_to_lc(dev)->readdir_process = NULL;
  12552. + yaffs_gross_unlock(dev);
  12553. +
  12554. + return ret_val;
  12555. +}
  12556. +
  12557. +#else
  12558. +
  12559. +static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
  12560. +{
  12561. + struct yaffs_obj *obj;
  12562. + struct yaffs_dev *dev;
  12563. + struct yaffs_search_context *sc;
  12564. + struct inode *inode = f->f_dentry->d_inode;
  12565. + unsigned long offset, curoffs;
  12566. + struct yaffs_obj *l;
  12567. + int ret_val = 0;
  12568. +
  12569. + char name[YAFFS_MAX_NAME_LENGTH + 1];
  12570. +
  12571. + obj = yaffs_dentry_to_obj(f->f_dentry);
  12572. + dev = obj->my_dev;
  12573. +
  12574. + yaffs_gross_lock(dev);
  12575. +
  12576. + yaffs_dev_to_lc(dev)->readdir_process = current;
  12577. +
  12578. + offset = f->f_pos;
  12579. +
  12580. + sc = yaffs_new_search(obj);
  12581. + if (!sc) {
  12582. + ret_val = -ENOMEM;
  12583. + goto out;
  12584. + }
  12585. +
  12586. + yaffs_trace(YAFFS_TRACE_OS,
  12587. + "yaffs_readdir: starting at %d", (int)offset);
  12588. +
  12589. + if (offset == 0) {
  12590. + yaffs_trace(YAFFS_TRACE_OS,
  12591. + "yaffs_readdir: entry . ino %d",
  12592. + (int)inode->i_ino);
  12593. + yaffs_gross_unlock(dev);
  12594. + if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) {
  12595. + yaffs_gross_lock(dev);
  12596. + goto out;
  12597. + }
  12598. + yaffs_gross_lock(dev);
  12599. + offset++;
  12600. + f->f_pos++;
  12601. + }
  12602. + if (offset == 1) {
  12603. + yaffs_trace(YAFFS_TRACE_OS,
  12604. + "yaffs_readdir: entry .. ino %d",
  12605. + (int)f->f_dentry->d_parent->d_inode->i_ino);
  12606. + yaffs_gross_unlock(dev);
  12607. + if (filldir(dirent, "..", 2, offset,
  12608. + f->f_dentry->d_parent->d_inode->i_ino,
  12609. + DT_DIR) < 0) {
  12610. + yaffs_gross_lock(dev);
  12611. + goto out;
  12612. + }
  12613. + yaffs_gross_lock(dev);
  12614. + offset++;
  12615. + f->f_pos++;
  12616. + }
  12617. +
  12618. + curoffs = 1;
  12619. +
  12620. + /* If the directory has changed since the open or last call to
  12621. + readdir, rewind to after the 2 canned entries. */
  12622. + if (f->f_version != inode->i_version) {
  12623. + offset = 2;
  12624. + f->f_pos = offset;
  12625. + f->f_version = inode->i_version;
  12626. + }
  12627. +
  12628. + while (sc->next_return) {
  12629. + curoffs++;
  12630. + l = sc->next_return;
  12631. + if (curoffs >= offset) {
  12632. + int this_inode = yaffs_get_obj_inode(l);
  12633. + int this_type = yaffs_get_obj_type(l);
  12634. +
  12635. + yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
  12636. + yaffs_trace(YAFFS_TRACE_OS,
  12637. + "yaffs_readdir: %s inode %d",
  12638. + name, yaffs_get_obj_inode(l));
  12639. +
  12640. + yaffs_gross_unlock(dev);
  12641. +
  12642. + if (filldir(dirent,
  12643. + name,
  12644. + strlen(name),
  12645. + offset, this_inode, this_type) < 0) {
  12646. + yaffs_gross_lock(dev);
  12647. + goto out;
  12648. + }
  12649. +
  12650. + yaffs_gross_lock(dev);
  12651. +
  12652. + offset++;
  12653. + f->f_pos++;
  12654. + }
  12655. + yaffs_search_advance(sc);
  12656. + }
  12657. +
  12658. +out:
  12659. + yaffs_search_end(sc);
  12660. + yaffs_dev_to_lc(dev)->readdir_process = NULL;
  12661. + yaffs_gross_unlock(dev);
  12662. +
  12663. + return ret_val;
  12664. +}
  12665. +
  12666. +#endif
  12667. +
  12668. +static const struct file_operations yaffs_dir_operations = {
  12669. + .read = generic_read_dir,
  12670. +#ifdef YAFFS_USE_DIR_ITERATE
  12671. + .iterate = yaffs_iterate,
  12672. +#else
  12673. + .readdir = yaffs_readdir,
  12674. +#endif
  12675. + .fsync = yaffs_sync_object,
  12676. + .llseek = generic_file_llseek,
  12677. +};
  12678. +
  12679. +static void yaffs_fill_inode_from_obj(struct inode *inode,
  12680. + struct yaffs_obj *obj)
  12681. +{
  12682. + if (inode && obj) {
  12683. +
  12684. + /* Check mode against the variant type and attempt to repair if broken. */
  12685. + u32 mode = obj->yst_mode;
  12686. + switch (obj->variant_type) {
  12687. + case YAFFS_OBJECT_TYPE_FILE:
  12688. + if (!S_ISREG(mode)) {
  12689. + obj->yst_mode &= ~S_IFMT;
  12690. + obj->yst_mode |= S_IFREG;
  12691. + }
  12692. +
  12693. + break;
  12694. + case YAFFS_OBJECT_TYPE_SYMLINK:
  12695. + if (!S_ISLNK(mode)) {
  12696. + obj->yst_mode &= ~S_IFMT;
  12697. + obj->yst_mode |= S_IFLNK;
  12698. + }
  12699. +
  12700. + break;
  12701. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  12702. + if (!S_ISDIR(mode)) {
  12703. + obj->yst_mode &= ~S_IFMT;
  12704. + obj->yst_mode |= S_IFDIR;
  12705. + }
  12706. +
  12707. + break;
  12708. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  12709. + case YAFFS_OBJECT_TYPE_HARDLINK:
  12710. + case YAFFS_OBJECT_TYPE_SPECIAL:
  12711. + default:
  12712. + /* TODO? */
  12713. + break;
  12714. + }
  12715. +
  12716. + inode->i_flags |= S_NOATIME;
  12717. +
  12718. + inode->i_ino = obj->obj_id;
  12719. + inode->i_mode = obj->yst_mode;
  12720. + inode->i_uid = MAKE_uid(obj->yst_uid);
  12721. + inode->i_gid = MAKE_gid(obj->yst_gid);
  12722. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  12723. + inode->i_blksize = inode->i_sb->s_blocksize;
  12724. +#endif
  12725. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12726. +
  12727. + inode->i_rdev = old_decode_dev(obj->yst_rdev);
  12728. + inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
  12729. + inode->i_atime.tv_nsec = 0;
  12730. + inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
  12731. + inode->i_mtime.tv_nsec = 0;
  12732. + inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
  12733. + inode->i_ctime.tv_nsec = 0;
  12734. +#else
  12735. + inode->i_rdev = obj->yst_rdev;
  12736. + inode->i_atime = obj->yst_atime;
  12737. + inode->i_mtime = obj->yst_mtime;
  12738. + inode->i_ctime = obj->yst_ctime;
  12739. +#endif
  12740. + inode->i_size = yaffs_get_obj_length(obj);
  12741. + inode->i_blocks = (inode->i_size + 511) >> 9;
  12742. +
  12743. + set_nlink(inode, yaffs_get_obj_link_count(obj));
  12744. +
  12745. + yaffs_trace(YAFFS_TRACE_OS,
  12746. + "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
  12747. + inode->i_mode, obj->yst_uid, obj->yst_gid,
  12748. + inode->i_size, atomic_read(&inode->i_count));
  12749. +
  12750. + switch (obj->yst_mode & S_IFMT) {
  12751. + default: /* fifo, device or socket */
  12752. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12753. + init_special_inode(inode, obj->yst_mode,
  12754. + old_decode_dev(obj->yst_rdev));
  12755. +#else
  12756. + init_special_inode(inode, obj->yst_mode,
  12757. + (dev_t) (obj->yst_rdev));
  12758. +#endif
  12759. + break;
  12760. + case S_IFREG: /* file */
  12761. + inode->i_op = &yaffs_file_inode_operations;
  12762. + inode->i_fop = &yaffs_file_operations;
  12763. + inode->i_mapping->a_ops =
  12764. + &yaffs_file_address_operations;
  12765. + break;
  12766. + case S_IFDIR: /* directory */
  12767. + inode->i_op = &yaffs_dir_inode_operations;
  12768. + inode->i_fop = &yaffs_dir_operations;
  12769. + break;
  12770. + case S_IFLNK: /* symlink */
  12771. + inode->i_op = &yaffs_symlink_inode_operations;
  12772. + break;
  12773. + }
  12774. +
  12775. + yaffs_inode_to_obj_lv(inode) = obj;
  12776. +
  12777. + obj->my_inode = inode;
  12778. +
  12779. + } else {
  12780. + yaffs_trace(YAFFS_TRACE_OS,
  12781. + "yaffs_fill_inode invalid parameters");
  12782. + }
  12783. +
  12784. +}
  12785. +
  12786. +
  12787. +
  12788. +/*
  12789. + * yaffs background thread functions .
  12790. + * yaffs_bg_thread_fn() the thread function
  12791. + * yaffs_bg_start() launches the background thread.
  12792. + * yaffs_bg_stop() cleans up the background thread.
  12793. + *
  12794. + * NB:
  12795. + * The thread should only run after the yaffs is initialised
  12796. + * The thread should be stopped before yaffs is unmounted.
  12797. + * The thread should not do any writing while the fs is in read only.
  12798. + */
  12799. +
  12800. +static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
  12801. +{
  12802. + unsigned erased_chunks =
  12803. + dev->n_erased_blocks * dev->param.chunks_per_block;
  12804. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  12805. + unsigned scattered = 0; /* Free chunks not in an erased block */
  12806. +
  12807. + if (erased_chunks < dev->n_free_chunks)
  12808. + scattered = (dev->n_free_chunks - erased_chunks);
  12809. +
  12810. + if (!context->bg_running)
  12811. + return 0;
  12812. + else if (scattered < (dev->param.chunks_per_block * 2))
  12813. + return 0;
  12814. + else if (erased_chunks > dev->n_free_chunks / 2)
  12815. + return 0;
  12816. + else if (erased_chunks > dev->n_free_chunks / 4)
  12817. + return 1;
  12818. + else
  12819. + return 2;
  12820. +}
  12821. +
  12822. +#ifdef YAFFS_COMPILE_BACKGROUND
  12823. +
  12824. +void yaffs_background_waker(unsigned long data)
  12825. +{
  12826. + wake_up_process((struct task_struct *)data);
  12827. +}
  12828. +
  12829. +static int yaffs_bg_thread_fn(void *data)
  12830. +{
  12831. + struct yaffs_dev *dev = (struct yaffs_dev *)data;
  12832. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  12833. + unsigned long now = jiffies;
  12834. + unsigned long next_dir_update = now;
  12835. + unsigned long next_gc = now;
  12836. + unsigned long expires;
  12837. + unsigned int urgency;
  12838. +
  12839. + int gc_result;
  12840. + struct timer_list timer;
  12841. +
  12842. + yaffs_trace(YAFFS_TRACE_BACKGROUND,
  12843. + "yaffs_background starting for dev %p", (void *)dev);
  12844. +
  12845. +#ifdef YAFFS_COMPILE_FREEZER
  12846. + set_freezable();
  12847. +#endif
  12848. + while (context->bg_running) {
  12849. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background");
  12850. +
  12851. + if (kthread_should_stop())
  12852. + break;
  12853. +
  12854. +#ifdef YAFFS_COMPILE_FREEZER
  12855. + if (try_to_freeze())
  12856. + continue;
  12857. +#endif
  12858. + yaffs_gross_lock(dev);
  12859. +
  12860. + now = jiffies;
  12861. +
  12862. + if (time_after(now, next_dir_update) && yaffs_bg_enable) {
  12863. + yaffs_update_dirty_dirs(dev);
  12864. + next_dir_update = now + HZ;
  12865. + }
  12866. +
  12867. + if (time_after(now, next_gc) && yaffs_bg_enable) {
  12868. + if (!dev->is_checkpointed) {
  12869. + urgency = yaffs_bg_gc_urgency(dev);
  12870. + gc_result = yaffs_bg_gc(dev, urgency);
  12871. + if (urgency > 1)
  12872. + next_gc = now + HZ / 20 + 1;
  12873. + else if (urgency > 0)
  12874. + next_gc = now + HZ / 10 + 1;
  12875. + else
  12876. + next_gc = now + HZ * 2;
  12877. + } else {
  12878. + /*
  12879. + * gc not running so set to next_dir_update
  12880. + * to cut down on wake ups
  12881. + */
  12882. + next_gc = next_dir_update;
  12883. + }
  12884. + }
  12885. + yaffs_gross_unlock(dev);
  12886. +#if 1
  12887. + expires = next_dir_update;
  12888. + if (time_before(next_gc, expires))
  12889. + expires = next_gc;
  12890. + if (time_before(expires, now))
  12891. + expires = now + HZ;
  12892. +
  12893. + Y_INIT_TIMER(&timer);
  12894. + timer.expires = expires + 1;
  12895. + timer.data = (unsigned long)current;
  12896. + timer.function = yaffs_background_waker;
  12897. +
  12898. + set_current_state(TASK_INTERRUPTIBLE);
  12899. + add_timer(&timer);
  12900. + schedule();
  12901. + del_timer_sync(&timer);
  12902. +#else
  12903. + msleep(10);
  12904. +#endif
  12905. + }
  12906. +
  12907. + return 0;
  12908. +}
  12909. +
  12910. +static int yaffs_bg_start(struct yaffs_dev *dev)
  12911. +{
  12912. + int retval = 0;
  12913. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  12914. +
  12915. + if (dev->read_only)
  12916. + return -1;
  12917. +
  12918. + context->bg_running = 1;
  12919. +
  12920. + context->bg_thread = kthread_run(yaffs_bg_thread_fn,
  12921. + (void *)dev, "yaffs-bg-%d",
  12922. + context->mount_id);
  12923. +
  12924. + if (IS_ERR(context->bg_thread)) {
  12925. + retval = PTR_ERR(context->bg_thread);
  12926. + context->bg_thread = NULL;
  12927. + context->bg_running = 0;
  12928. + }
  12929. + return retval;
  12930. +}
  12931. +
  12932. +static void yaffs_bg_stop(struct yaffs_dev *dev)
  12933. +{
  12934. + struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev);
  12935. +
  12936. + ctxt->bg_running = 0;
  12937. +
  12938. + if (ctxt->bg_thread) {
  12939. + kthread_stop(ctxt->bg_thread);
  12940. + ctxt->bg_thread = NULL;
  12941. + }
  12942. +}
  12943. +#else
  12944. +static int yaffs_bg_thread_fn(void *data)
  12945. +{
  12946. + return 0;
  12947. +}
  12948. +
  12949. +static int yaffs_bg_start(struct yaffs_dev *dev)
  12950. +{
  12951. + return 0;
  12952. +}
  12953. +
  12954. +static void yaffs_bg_stop(struct yaffs_dev *dev)
  12955. +{
  12956. +}
  12957. +#endif
  12958. +
  12959. +
  12960. +static void yaffs_flush_inodes(struct super_block *sb)
  12961. +{
  12962. + struct inode *iptr;
  12963. + struct yaffs_obj *obj;
  12964. +
  12965. + list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
  12966. + obj = yaffs_inode_to_obj(iptr);
  12967. + if (obj) {
  12968. + yaffs_trace(YAFFS_TRACE_OS,
  12969. + "flushing obj %d",
  12970. + obj->obj_id);
  12971. + yaffs_flush_file(obj, 1, 0, 0);
  12972. + }
  12973. + }
  12974. +}
  12975. +
  12976. +static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
  12977. +{
  12978. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  12979. + if (!dev)
  12980. + return;
  12981. +
  12982. + yaffs_flush_inodes(sb);
  12983. + yaffs_update_dirty_dirs(dev);
  12984. + yaffs_flush_whole_cache(dev, 1);
  12985. + if (do_checkpoint)
  12986. + yaffs_checkpoint_save(dev);
  12987. +}
  12988. +
  12989. +static LIST_HEAD(yaffs_context_list);
  12990. +struct mutex yaffs_context_lock;
  12991. +
  12992. +static void yaffs_put_super(struct super_block *sb)
  12993. +{
  12994. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  12995. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  12996. +
  12997. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
  12998. + "yaffs_put_super");
  12999. +
  13000. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
  13001. + "Shutting down yaffs background thread");
  13002. + yaffs_bg_stop(dev);
  13003. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
  13004. + "yaffs background thread shut down");
  13005. +
  13006. + yaffs_gross_lock(dev);
  13007. +
  13008. + yaffs_flush_super(sb, 1);
  13009. +
  13010. + yaffs_deinitialise(dev);
  13011. +
  13012. + yaffs_gross_unlock(dev);
  13013. +
  13014. + mutex_lock(&yaffs_context_lock);
  13015. + list_del_init(&(yaffs_dev_to_lc(dev)->context_list));
  13016. + mutex_unlock(&yaffs_context_lock);
  13017. +
  13018. + if (yaffs_dev_to_lc(dev)->spare_buffer) {
  13019. + kfree(yaffs_dev_to_lc(dev)->spare_buffer);
  13020. + yaffs_dev_to_lc(dev)->spare_buffer = NULL;
  13021. + }
  13022. +
  13023. + kfree(dev);
  13024. +
  13025. + yaffs_put_mtd_device(mtd);
  13026. +
  13027. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
  13028. + "yaffs_put_super done");
  13029. +}
  13030. +
  13031. +
  13032. +static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev)
  13033. +{
  13034. + return yaffs_gc_control;
  13035. +}
  13036. +
  13037. +
  13038. +#ifdef YAFFS_COMPILE_EXPORTFS
  13039. +
  13040. +static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
  13041. + uint32_t generation)
  13042. +{
  13043. + return Y_IGET(sb, ino);
  13044. +}
  13045. +
  13046. +static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb,
  13047. + struct fid *fid, int fh_len,
  13048. + int fh_type)
  13049. +{
  13050. + return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  13051. + yaffs2_nfs_get_inode);
  13052. +}
  13053. +
  13054. +static struct dentry *yaffs2_fh_to_parent(struct super_block *sb,
  13055. + struct fid *fid, int fh_len,
  13056. + int fh_type)
  13057. +{
  13058. + return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  13059. + yaffs2_nfs_get_inode);
  13060. +}
  13061. +
  13062. +struct dentry *yaffs2_get_parent(struct dentry *dentry)
  13063. +{
  13064. +
  13065. + struct super_block *sb = dentry->d_inode->i_sb;
  13066. + struct dentry *parent = ERR_PTR(-ENOENT);
  13067. + struct inode *inode;
  13068. + unsigned long parent_ino;
  13069. + struct yaffs_obj *d_obj;
  13070. + struct yaffs_obj *parent_obj;
  13071. +
  13072. + d_obj = yaffs_inode_to_obj(dentry->d_inode);
  13073. +
  13074. + if (d_obj) {
  13075. + parent_obj = d_obj->parent;
  13076. + if (parent_obj) {
  13077. + parent_ino = yaffs_get_obj_inode(parent_obj);
  13078. + inode = Y_IGET(sb, parent_ino);
  13079. +
  13080. + if (IS_ERR(inode)) {
  13081. + parent = ERR_CAST(inode);
  13082. + } else {
  13083. + parent = d_obtain_alias(inode);
  13084. + if (!IS_ERR(parent)) {
  13085. + parent = ERR_PTR(-ENOMEM);
  13086. + iput(inode);
  13087. + }
  13088. + }
  13089. + }
  13090. + }
  13091. +
  13092. + return parent;
  13093. +}
  13094. +
  13095. +/* Just declare a zero structure as a NULL value implies
  13096. + * using the default functions of exportfs.
  13097. + */
  13098. +
  13099. +static struct export_operations yaffs_export_ops = {
  13100. + .fh_to_dentry = yaffs2_fh_to_dentry,
  13101. + .fh_to_parent = yaffs2_fh_to_parent,
  13102. + .get_parent = yaffs2_get_parent,
  13103. +};
  13104. +
  13105. +#endif
  13106. +
  13107. +static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj)
  13108. +{
  13109. + /* Clear the association between the inode and
  13110. + * the struct yaffs_obj.
  13111. + */
  13112. + obj->my_inode = NULL;
  13113. + yaffs_inode_to_obj_lv(inode) = NULL;
  13114. +
  13115. + /* If the object freeing was deferred, then the real
  13116. + * free happens now.
  13117. + * This should fix the inode inconsistency problem.
  13118. + */
  13119. + yaffs_handle_defered_free(obj);
  13120. +}
  13121. +
  13122. +#ifdef YAFFS_HAS_EVICT_INODE
  13123. +/* yaffs_evict_inode combines into one operation what was previously done in
  13124. + * yaffs_clear_inode() and yaffs_delete_inode()
  13125. + *
  13126. + */
  13127. +static void yaffs_evict_inode(struct inode *inode)
  13128. +{
  13129. + struct yaffs_obj *obj;
  13130. + struct yaffs_dev *dev;
  13131. + int deleteme = 0;
  13132. +
  13133. + obj = yaffs_inode_to_obj(inode);
  13134. +
  13135. + yaffs_trace(YAFFS_TRACE_OS,
  13136. + "yaffs_evict_inode: ino %d, count %d %s",
  13137. + (int)inode->i_ino, atomic_read(&inode->i_count),
  13138. + obj ? "object exists" : "null object");
  13139. +
  13140. + if (!inode->i_nlink && !is_bad_inode(inode))
  13141. + deleteme = 1;
  13142. + truncate_inode_pages(&inode->i_data, 0);
  13143. + Y_CLEAR_INODE(inode);
  13144. +
  13145. + if (deleteme && obj) {
  13146. + dev = obj->my_dev;
  13147. + yaffs_gross_lock(dev);
  13148. + yaffs_del_obj(obj);
  13149. + yaffs_gross_unlock(dev);
  13150. + }
  13151. + if (obj) {
  13152. + dev = obj->my_dev;
  13153. + yaffs_gross_lock(dev);
  13154. + yaffs_unstitch_obj(inode, obj);
  13155. + yaffs_gross_unlock(dev);
  13156. + }
  13157. +}
  13158. +#else
  13159. +
  13160. +/* clear is called to tell the fs to release any per-inode data it holds.
  13161. + * The object might still exist on disk and is just being thrown out of the cache
  13162. + * or else the object has actually been deleted and we're being called via
  13163. + * the chain
  13164. + * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
  13165. + */
  13166. +
  13167. +static void yaffs_clear_inode(struct inode *inode)
  13168. +{
  13169. + struct yaffs_obj *obj;
  13170. + struct yaffs_dev *dev;
  13171. +
  13172. + obj = yaffs_inode_to_obj(inode);
  13173. +
  13174. + yaffs_trace(YAFFS_TRACE_OS,
  13175. + "yaffs_clear_inode: ino %d, count %d %s",
  13176. + (int)inode->i_ino, atomic_read(&inode->i_count),
  13177. + obj ? "object exists" : "null object");
  13178. +
  13179. + if (obj) {
  13180. + dev = obj->my_dev;
  13181. + yaffs_gross_lock(dev);
  13182. + yaffs_unstitch_obj(inode, obj);
  13183. + yaffs_gross_unlock(dev);
  13184. + }
  13185. +
  13186. +}
  13187. +
  13188. +/* delete is called when the link count is zero and the inode
  13189. + * is put (ie. nobody wants to know about it anymore, time to
  13190. + * delete the file).
  13191. + * NB Must call clear_inode()
  13192. + */
  13193. +static void yaffs_delete_inode(struct inode *inode)
  13194. +{
  13195. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  13196. + struct yaffs_dev *dev;
  13197. +
  13198. + yaffs_trace(YAFFS_TRACE_OS,
  13199. + "yaffs_delete_inode: ino %d, count %d %s",
  13200. + (int)inode->i_ino, atomic_read(&inode->i_count),
  13201. + obj ? "object exists" : "null object");
  13202. +
  13203. + if (obj) {
  13204. + dev = obj->my_dev;
  13205. + yaffs_gross_lock(dev);
  13206. + yaffs_del_obj(obj);
  13207. + yaffs_gross_unlock(dev);
  13208. + }
  13209. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
  13210. + truncate_inode_pages(&inode->i_data, 0);
  13211. +#endif
  13212. + clear_inode(inode);
  13213. +}
  13214. +#endif
  13215. +
  13216. +
  13217. +
  13218. +
  13219. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13220. +static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
  13221. +{
  13222. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  13223. + struct super_block *sb = dentry->d_sb;
  13224. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  13225. +static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
  13226. +{
  13227. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13228. +#else
  13229. +static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
  13230. +{
  13231. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13232. +#endif
  13233. +
  13234. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs");
  13235. +
  13236. + yaffs_gross_lock(dev);
  13237. +
  13238. + buf->f_type = YAFFS_MAGIC;
  13239. + buf->f_bsize = sb->s_blocksize;
  13240. + buf->f_namelen = 255;
  13241. +
  13242. + if (dev->data_bytes_per_chunk & (dev->data_bytes_per_chunk - 1)) {
  13243. + /* Do this if chunk size is not a power of 2 */
  13244. +
  13245. + uint64_t bytes_in_dev;
  13246. + uint64_t bytes_free;
  13247. +
  13248. + bytes_in_dev =
  13249. + ((uint64_t)
  13250. + ((dev->param.end_block - dev->param.start_block +
  13251. + 1))) * ((uint64_t) (dev->param.chunks_per_block *
  13252. + dev->data_bytes_per_chunk));
  13253. +
  13254. + do_div(bytes_in_dev, sb->s_blocksize); /* bytes_in_dev becomes the number of blocks */
  13255. + buf->f_blocks = bytes_in_dev;
  13256. +
  13257. + bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) *
  13258. + ((uint64_t) (dev->data_bytes_per_chunk));
  13259. +
  13260. + do_div(bytes_free, sb->s_blocksize);
  13261. +
  13262. + buf->f_bfree = bytes_free;
  13263. +
  13264. + } else if (sb->s_blocksize > dev->data_bytes_per_chunk) {
  13265. +
  13266. + buf->f_blocks =
  13267. + (dev->param.end_block - dev->param.start_block + 1) *
  13268. + dev->param.chunks_per_block /
  13269. + (sb->s_blocksize / dev->data_bytes_per_chunk);
  13270. + buf->f_bfree =
  13271. + yaffs_get_n_free_chunks(dev) /
  13272. + (sb->s_blocksize / dev->data_bytes_per_chunk);
  13273. + } else {
  13274. + buf->f_blocks =
  13275. + (dev->param.end_block - dev->param.start_block + 1) *
  13276. + dev->param.chunks_per_block *
  13277. + (dev->data_bytes_per_chunk / sb->s_blocksize);
  13278. +
  13279. + buf->f_bfree =
  13280. + yaffs_get_n_free_chunks(dev) *
  13281. + (dev->data_bytes_per_chunk / sb->s_blocksize);
  13282. + }
  13283. +
  13284. + buf->f_files = 0;
  13285. + buf->f_ffree = 0;
  13286. + buf->f_bavail = buf->f_bfree;
  13287. +
  13288. + yaffs_gross_unlock(dev);
  13289. + return 0;
  13290. +}
  13291. +
  13292. +
  13293. +
  13294. +static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
  13295. +{
  13296. +
  13297. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13298. + unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
  13299. + unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
  13300. + int do_checkpoint;
  13301. + int dirty = yaffs_check_super_dirty(dev);
  13302. +
  13303. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
  13304. + "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
  13305. + gc_urgent,
  13306. + dirty ? "dirty" : "clean",
  13307. + request_checkpoint ? "checkpoint requested" : "no checkpoint",
  13308. + oneshot_checkpoint ? " one-shot" : "");
  13309. +
  13310. + yaffs_gross_lock(dev);
  13311. + do_checkpoint = ((request_checkpoint && !gc_urgent) ||
  13312. + oneshot_checkpoint) && !dev->is_checkpointed;
  13313. +
  13314. + if (dirty || do_checkpoint) {
  13315. + yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
  13316. + yaffs_clear_super_dirty(dev);
  13317. + if (oneshot_checkpoint)
  13318. + yaffs_auto_checkpoint &= ~4;
  13319. + }
  13320. + yaffs_gross_unlock(dev);
  13321. +
  13322. + return 0;
  13323. +}
  13324. +
  13325. +
  13326. +#ifdef YAFFS_HAS_WRITE_SUPER
  13327. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13328. +static void yaffs_write_super(struct super_block *sb)
  13329. +#else
  13330. +static int yaffs_write_super(struct super_block *sb)
  13331. +#endif
  13332. +{
  13333. + unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
  13334. +
  13335. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
  13336. + "yaffs_write_super %s",
  13337. + request_checkpoint ? " checkpt" : "");
  13338. +
  13339. + yaffs_do_sync_fs(sb, request_checkpoint);
  13340. +
  13341. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
  13342. + return 0;
  13343. +#endif
  13344. +}
  13345. +#endif
  13346. +
  13347. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13348. +static int yaffs_sync_fs(struct super_block *sb, int wait)
  13349. +#else
  13350. +static int yaffs_sync_fs(struct super_block *sb)
  13351. +#endif
  13352. +{
  13353. + unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1);
  13354. +
  13355. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
  13356. + "yaffs_sync_fs%s", request_checkpoint ? " checkpt" : "");
  13357. +
  13358. + yaffs_do_sync_fs(sb, request_checkpoint);
  13359. +
  13360. + return 0;
  13361. +}
  13362. +
  13363. +/* the function only is used to change dev->read_only when this file system
  13364. + * is remounted.
  13365. + */
  13366. +static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
  13367. +{
  13368. + int read_only = 0;
  13369. + struct mtd_info *mtd;
  13370. + struct yaffs_dev *dev = 0;
  13371. +
  13372. + /* Get the device */
  13373. + mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
  13374. + if (!mtd) {
  13375. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  13376. + "MTD device #%u doesn't appear to exist",
  13377. + MINOR(sb->s_dev));
  13378. + return 1;
  13379. + }
  13380. +
  13381. + /* Check it's NAND */
  13382. + if (mtd->type != MTD_NANDFLASH) {
  13383. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  13384. + "MTD device is not NAND it's type %d",
  13385. + mtd->type);
  13386. + return 1;
  13387. + }
  13388. +
  13389. + read_only = ((*flags & MS_RDONLY) != 0);
  13390. + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
  13391. + read_only = 1;
  13392. + printk(KERN_INFO
  13393. + "yaffs: mtd is read only, setting superblock read only");
  13394. + *flags |= MS_RDONLY;
  13395. + }
  13396. +
  13397. + dev = sb->s_fs_info;
  13398. + dev->read_only = read_only;
  13399. +
  13400. + return 0;
  13401. +}
  13402. +
  13403. +static const struct super_operations yaffs_super_ops = {
  13404. + .statfs = yaffs_statfs,
  13405. +
  13406. +#ifndef YAFFS_USE_OWN_IGET
  13407. + .read_inode = yaffs_read_inode,
  13408. +#endif
  13409. +#ifdef YAFFS_HAS_PUT_INODE
  13410. + .put_inode = yaffs_put_inode,
  13411. +#endif
  13412. + .put_super = yaffs_put_super,
  13413. +#ifdef YAFFS_HAS_EVICT_INODE
  13414. + .evict_inode = yaffs_evict_inode,
  13415. +#else
  13416. + .delete_inode = yaffs_delete_inode,
  13417. + .clear_inode = yaffs_clear_inode,
  13418. +#endif
  13419. + .sync_fs = yaffs_sync_fs,
  13420. +#ifdef YAFFS_HAS_WRITE_SUPER
  13421. + .write_super = yaffs_write_super,
  13422. +#endif
  13423. + .remount_fs = yaffs_remount_fs,
  13424. +};
  13425. +
  13426. +struct yaffs_options {
  13427. + int inband_tags;
  13428. + int skip_checkpoint_read;
  13429. + int skip_checkpoint_write;
  13430. + int no_cache;
  13431. + int tags_ecc_on;
  13432. + int tags_ecc_overridden;
  13433. + int lazy_loading_enabled;
  13434. + int lazy_loading_overridden;
  13435. + int empty_lost_and_found;
  13436. + int empty_lost_and_found_overridden;
  13437. + int disable_summary;
  13438. +};
  13439. +
  13440. +#define MAX_OPT_LEN 30
  13441. +static int yaffs_parse_options(struct yaffs_options *options,
  13442. + const char *options_str)
  13443. +{
  13444. + char cur_opt[MAX_OPT_LEN + 1];
  13445. + int p;
  13446. + int error = 0;
  13447. +
  13448. + /* Parse through the options which is a comma seperated list */
  13449. +
  13450. + while (options_str && *options_str && !error) {
  13451. + memset(cur_opt, 0, MAX_OPT_LEN + 1);
  13452. + p = 0;
  13453. +
  13454. + while (*options_str == ',')
  13455. + options_str++;
  13456. +
  13457. + while (*options_str && *options_str != ',') {
  13458. + if (p < MAX_OPT_LEN) {
  13459. + cur_opt[p] = *options_str;
  13460. + p++;
  13461. + }
  13462. + options_str++;
  13463. + }
  13464. +
  13465. + if (!strcmp(cur_opt, "inband-tags")) {
  13466. + options->inband_tags = 1;
  13467. + } else if (!strcmp(cur_opt, "tags-ecc-off")) {
  13468. + options->tags_ecc_on = 0;
  13469. + options->tags_ecc_overridden = 1;
  13470. + } else if (!strcmp(cur_opt, "tags-ecc-on")) {
  13471. + options->tags_ecc_on = 1;
  13472. + options->tags_ecc_overridden = 1;
  13473. + } else if (!strcmp(cur_opt, "lazy-loading-off")) {
  13474. + options->lazy_loading_enabled = 0;
  13475. + options->lazy_loading_overridden = 1;
  13476. + } else if (!strcmp(cur_opt, "lazy-loading-on")) {
  13477. + options->lazy_loading_enabled = 1;
  13478. + options->lazy_loading_overridden = 1;
  13479. + } else if (!strcmp(cur_opt, "disable-summary")) {
  13480. + options->disable_summary = 1;
  13481. + } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
  13482. + options->empty_lost_and_found = 0;
  13483. + options->empty_lost_and_found_overridden = 1;
  13484. + } else if (!strcmp(cur_opt, "empty-lost-and-found-on")) {
  13485. + options->empty_lost_and_found = 1;
  13486. + options->empty_lost_and_found_overridden = 1;
  13487. + } else if (!strcmp(cur_opt, "no-cache")) {
  13488. + options->no_cache = 1;
  13489. + } else if (!strcmp(cur_opt, "no-checkpoint-read")) {
  13490. + options->skip_checkpoint_read = 1;
  13491. + } else if (!strcmp(cur_opt, "no-checkpoint-write")) {
  13492. + options->skip_checkpoint_write = 1;
  13493. + } else if (!strcmp(cur_opt, "no-checkpoint")) {
  13494. + options->skip_checkpoint_read = 1;
  13495. + options->skip_checkpoint_write = 1;
  13496. + } else {
  13497. + printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",
  13498. + cur_opt);
  13499. + error = 1;
  13500. + }
  13501. + }
  13502. +
  13503. + return error;
  13504. +}
  13505. +
  13506. +
  13507. +static struct dentry *yaffs_make_root(struct inode *inode)
  13508. +{
  13509. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
  13510. + struct dentry *root = d_alloc_root(inode);
  13511. +
  13512. + if (!root)
  13513. + iput(inode);
  13514. +
  13515. + return root;
  13516. +#else
  13517. + return d_make_root(inode);
  13518. +#endif
  13519. +}
  13520. +
  13521. +
  13522. +
  13523. +
  13524. +static struct super_block *yaffs_internal_read_super(int yaffs_version,
  13525. + struct super_block *sb,
  13526. + void *data, int silent)
  13527. +{
  13528. + int n_blocks;
  13529. + struct inode *inode = NULL;
  13530. + struct dentry *root;
  13531. + struct yaffs_dev *dev = 0;
  13532. + char devname_buf[BDEVNAME_SIZE + 1];
  13533. + struct mtd_info *mtd;
  13534. + int err;
  13535. + char *data_str = (char *)data;
  13536. + struct yaffs_linux_context *context = NULL;
  13537. + struct yaffs_param *param;
  13538. +
  13539. + int read_only = 0;
  13540. + int inband_tags = 0;
  13541. +
  13542. + struct yaffs_options options;
  13543. +
  13544. + unsigned mount_id;
  13545. + int found;
  13546. + struct yaffs_linux_context *context_iterator;
  13547. + struct list_head *l;
  13548. +
  13549. + if (!sb) {
  13550. + printk(KERN_INFO "yaffs: sb is NULL\n");
  13551. + return NULL;
  13552. + }
  13553. +
  13554. + sb->s_magic = YAFFS_MAGIC;
  13555. + sb->s_op = &yaffs_super_ops;
  13556. + sb->s_flags |= MS_NOATIME;
  13557. +
  13558. + read_only = ((sb->s_flags & MS_RDONLY) != 0);
  13559. +
  13560. +#ifdef YAFFS_COMPILE_EXPORTFS
  13561. + sb->s_export_op = &yaffs_export_ops;
  13562. +#endif
  13563. +
  13564. + if (!sb->s_dev)
  13565. + printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
  13566. + else if (!yaffs_devname(sb, devname_buf))
  13567. + printk(KERN_INFO "yaffs: devname is NULL\n");
  13568. + else
  13569. + printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
  13570. + sb->s_dev,
  13571. + yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw");
  13572. +
  13573. + if (!data_str)
  13574. + data_str = "";
  13575. +
  13576. + printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str);
  13577. +
  13578. + memset(&options, 0, sizeof(options));
  13579. +
  13580. + if (yaffs_parse_options(&options, data_str)) {
  13581. + /* Option parsing failed */
  13582. + return NULL;
  13583. + }
  13584. +
  13585. + sb->s_blocksize = PAGE_CACHE_SIZE;
  13586. + sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
  13587. +
  13588. + yaffs_trace(YAFFS_TRACE_OS,
  13589. + "yaffs_read_super: Using yaffs%d", yaffs_version);
  13590. + yaffs_trace(YAFFS_TRACE_OS,
  13591. + "yaffs_read_super: block size %d", (int)(sb->s_blocksize));
  13592. +
  13593. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  13594. + "yaffs: Attempting MTD mount of %u.%u,\"%s\"",
  13595. + MAJOR(sb->s_dev), MINOR(sb->s_dev),
  13596. + yaffs_devname(sb, devname_buf));
  13597. +
  13598. + /* Get the device */
  13599. + mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
  13600. + if (IS_ERR(mtd)) {
  13601. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  13602. + "yaffs: MTD device %u either not valid or unavailable",
  13603. + MINOR(sb->s_dev));
  13604. + return NULL;
  13605. + }
  13606. +
  13607. + if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
  13608. + yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
  13609. + yaffs_version = 2;
  13610. + }
  13611. +
  13612. + /* Added NCB 26/5/2006 for completeness */
  13613. + if (yaffs_version == 2 && !options.inband_tags
  13614. + && WRITE_SIZE(mtd) == 512) {
  13615. + yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
  13616. + yaffs_version = 1;
  13617. + }
  13618. +
  13619. + if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) ||
  13620. + options.inband_tags)
  13621. + inband_tags = 1;
  13622. +
  13623. + if(yaffs_verify_mtd(mtd, yaffs_version, inband_tags) < 0)
  13624. + return NULL;
  13625. +
  13626. + /* OK, so if we got here, we have an MTD that's NAND and looks
  13627. + * like it has the right capabilities
  13628. + * Set the struct yaffs_dev up for mtd
  13629. + */
  13630. +
  13631. + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
  13632. + read_only = 1;
  13633. + printk(KERN_INFO
  13634. + "yaffs: mtd is read only, setting superblock read only\n"
  13635. + );
  13636. + sb->s_flags |= MS_RDONLY;
  13637. + }
  13638. +
  13639. + dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL);
  13640. + context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
  13641. +
  13642. + if (!dev || !context) {
  13643. + kfree(dev);
  13644. + kfree(context);
  13645. + dev = NULL;
  13646. + context = NULL;
  13647. +
  13648. + /* Deep shit could not allocate device structure */
  13649. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  13650. + "yaffs_read_super: Failed trying to allocate struct yaffs_dev."
  13651. + );
  13652. + return NULL;
  13653. + }
  13654. + memset(dev, 0, sizeof(struct yaffs_dev));
  13655. + param = &(dev->param);
  13656. +
  13657. + memset(context, 0, sizeof(struct yaffs_linux_context));
  13658. + dev->os_context = context;
  13659. + INIT_LIST_HEAD(&(context->context_list));
  13660. + context->dev = dev;
  13661. + context->super = sb;
  13662. +
  13663. + dev->read_only = read_only;
  13664. +
  13665. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  13666. + sb->s_fs_info = dev;
  13667. +#else
  13668. + sb->u.generic_sbp = dev;
  13669. +#endif
  13670. +
  13671. +
  13672. + dev->driver_context = mtd;
  13673. + param->name = mtd->name;
  13674. +
  13675. + /* Set up the memory size parameters.... */
  13676. +
  13677. +
  13678. + param->n_reserved_blocks = 5;
  13679. + param->n_caches = (options.no_cache) ? 0 : 10;
  13680. + param->inband_tags = inband_tags;
  13681. +
  13682. + param->enable_xattr = 1;
  13683. + if (options.lazy_loading_overridden)
  13684. + param->disable_lazy_load = !options.lazy_loading_enabled;
  13685. +
  13686. + param->defered_dir_update = 1;
  13687. +
  13688. + if (options.tags_ecc_overridden)
  13689. + param->no_tags_ecc = !options.tags_ecc_on;
  13690. +
  13691. + param->empty_lost_n_found = 1;
  13692. + param->refresh_period = 500;
  13693. + param->disable_summary = options.disable_summary;
  13694. +
  13695. +
  13696. +#ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING
  13697. + param->disable_bad_block_marking = 1;
  13698. +#endif
  13699. + if (options.empty_lost_and_found_overridden)
  13700. + param->empty_lost_n_found = options.empty_lost_and_found;
  13701. +
  13702. + /* ... and the functions. */
  13703. + if (yaffs_version == 2) {
  13704. + param->is_yaffs2 = 1;
  13705. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13706. + param->total_bytes_per_chunk = mtd->writesize;
  13707. + param->chunks_per_block = mtd->erasesize / mtd->writesize;
  13708. +#else
  13709. + param->total_bytes_per_chunk = mtd->oobblock;
  13710. + param->chunks_per_block = mtd->erasesize / mtd->oobblock;
  13711. +#endif
  13712. + n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize);
  13713. +
  13714. + param->start_block = 0;
  13715. + param->end_block = n_blocks - 1;
  13716. + } else {
  13717. + param->is_yaffs2 = 0;
  13718. + n_blocks = YCALCBLOCKS(mtd->size,
  13719. + YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
  13720. +
  13721. + param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
  13722. + param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
  13723. + }
  13724. +
  13725. + param->start_block = 0;
  13726. + param->end_block = n_blocks - 1;
  13727. +
  13728. + yaffs_mtd_drv_install(dev);
  13729. +
  13730. + param->sb_dirty_fn = yaffs_set_super_dirty;
  13731. + param->gc_control_fn = yaffs_gc_control_callback;
  13732. +
  13733. + yaffs_dev_to_lc(dev)->super = sb;
  13734. +
  13735. + param->use_nand_ecc = 1;
  13736. +
  13737. + param->skip_checkpt_rd = options.skip_checkpoint_read;
  13738. + param->skip_checkpt_wr = options.skip_checkpoint_write;
  13739. +
  13740. + mutex_lock(&yaffs_context_lock);
  13741. + /* Get a mount id */
  13742. + found = 0;
  13743. + for (mount_id = 0; !found; mount_id++) {
  13744. + found = 1;
  13745. + list_for_each(l, &yaffs_context_list) {
  13746. + context_iterator =
  13747. + list_entry(l, struct yaffs_linux_context,
  13748. + context_list);
  13749. + if (context_iterator->mount_id == mount_id)
  13750. + found = 0;
  13751. + }
  13752. + }
  13753. + context->mount_id = mount_id;
  13754. +
  13755. + list_add_tail(&(yaffs_dev_to_lc(dev)->context_list),
  13756. + &yaffs_context_list);
  13757. + mutex_unlock(&yaffs_context_lock);
  13758. +
  13759. + /* Directory search handling... */
  13760. + INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts));
  13761. + param->remove_obj_fn = yaffs_remove_obj_callback;
  13762. +
  13763. + mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock));
  13764. +
  13765. + yaffs_gross_lock(dev);
  13766. +
  13767. + err = yaffs_guts_initialise(dev);
  13768. +
  13769. + yaffs_trace(YAFFS_TRACE_OS,
  13770. + "yaffs_read_super: guts initialised %s",
  13771. + (err == YAFFS_OK) ? "OK" : "FAILED");
  13772. +
  13773. + if (err == YAFFS_OK)
  13774. + yaffs_bg_start(dev);
  13775. +
  13776. + if (!context->bg_thread)
  13777. + param->defered_dir_update = 0;
  13778. +
  13779. + sb->s_maxbytes = yaffs_max_file_size(dev);
  13780. +
  13781. + /* Release lock before yaffs_get_inode() */
  13782. + yaffs_gross_unlock(dev);
  13783. +
  13784. + /* Create root inode */
  13785. + if (err == YAFFS_OK)
  13786. + inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev));
  13787. +
  13788. + if (!inode)
  13789. + return NULL;
  13790. +
  13791. + inode->i_op = &yaffs_dir_inode_operations;
  13792. + inode->i_fop = &yaffs_dir_operations;
  13793. +
  13794. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: got root inode");
  13795. +
  13796. + root = yaffs_make_root(inode);
  13797. +
  13798. + if (!root)
  13799. + return NULL;
  13800. +
  13801. + sb->s_root = root;
  13802. + if(!dev->is_checkpointed)
  13803. + yaffs_set_super_dirty(dev);
  13804. +
  13805. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  13806. + "yaffs_read_super: is_checkpointed %d",
  13807. + dev->is_checkpointed);
  13808. +
  13809. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done");
  13810. + return sb;
  13811. +}
  13812. +
  13813. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  13814. +static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
  13815. + int silent)
  13816. +{
  13817. + return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
  13818. +}
  13819. +
  13820. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  13821. +static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags,
  13822. + const char *dev_name, void *data)
  13823. +{
  13824. + return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd);
  13825. +}
  13826. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13827. +static int yaffs_read_super(struct file_system_type *fs,
  13828. + int flags, const char *dev_name,
  13829. + void *data, struct vfsmount *mnt)
  13830. +{
  13831. +
  13832. + return get_sb_bdev(fs, flags, dev_name, data,
  13833. + yaffs_internal_read_super_mtd, mnt);
  13834. +}
  13835. +#else
  13836. +static struct super_block *yaffs_read_super(struct file_system_type *fs,
  13837. + int flags, const char *dev_name,
  13838. + void *data)
  13839. +{
  13840. +
  13841. + return get_sb_bdev(fs, flags, dev_name, data,
  13842. + yaffs_internal_read_super_mtd);
  13843. +}
  13844. +#endif
  13845. +
  13846. +static struct file_system_type yaffs_fs_type = {
  13847. + .owner = THIS_MODULE,
  13848. + .name = "yaffs",
  13849. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  13850. + .mount = yaffs_mount,
  13851. +#else
  13852. + .get_sb = yaffs_read_super,
  13853. +#endif
  13854. + .kill_sb = kill_block_super,
  13855. + .fs_flags = FS_REQUIRES_DEV,
  13856. +};
  13857. +#else
  13858. +static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
  13859. + int silent)
  13860. +{
  13861. + return yaffs_internal_read_super(1, sb, data, silent);
  13862. +}
  13863. +
  13864. +static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
  13865. + FS_REQUIRES_DEV);
  13866. +#endif
  13867. +
  13868. +
  13869. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  13870. +static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
  13871. + int silent)
  13872. +{
  13873. + return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
  13874. +}
  13875. +
  13876. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  13877. +static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags,
  13878. + const char *dev_name, void *data)
  13879. +{
  13880. + return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd);
  13881. +}
  13882. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13883. +static int yaffs2_read_super(struct file_system_type *fs,
  13884. + int flags, const char *dev_name, void *data,
  13885. + struct vfsmount *mnt)
  13886. +{
  13887. + return get_sb_bdev(fs, flags, dev_name, data,
  13888. + yaffs2_internal_read_super_mtd, mnt);
  13889. +}
  13890. +#else
  13891. +static struct super_block *yaffs2_read_super(struct file_system_type *fs,
  13892. + int flags, const char *dev_name,
  13893. + void *data)
  13894. +{
  13895. +
  13896. + return get_sb_bdev(fs, flags, dev_name, data,
  13897. + yaffs2_internal_read_super_mtd);
  13898. +}
  13899. +#endif
  13900. +
  13901. +static struct file_system_type yaffs2_fs_type = {
  13902. + .owner = THIS_MODULE,
  13903. + .name = "yaffs2",
  13904. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  13905. + .mount = yaffs2_mount,
  13906. +#else
  13907. + .get_sb = yaffs2_read_super,
  13908. +#endif
  13909. + .kill_sb = kill_block_super,
  13910. + .fs_flags = FS_REQUIRES_DEV,
  13911. +};
  13912. +#else
  13913. +static struct super_block *yaffs2_read_super(struct super_block *sb,
  13914. + void *data, int silent)
  13915. +{
  13916. + return yaffs_internal_read_super(2, sb, data, silent);
  13917. +}
  13918. +
  13919. +static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
  13920. + FS_REQUIRES_DEV);
  13921. +#endif
  13922. +
  13923. +
  13924. +static struct proc_dir_entry *my_proc_entry;
  13925. +
  13926. +static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
  13927. +{
  13928. + struct yaffs_param *param = &dev->param;
  13929. + int bs[10];
  13930. +
  13931. + yaffs_count_blocks_by_state(dev,bs);
  13932. +
  13933. + buf += sprintf(buf, "start_block.......... %d\n", param->start_block);
  13934. + buf += sprintf(buf, "end_block............ %d\n", param->end_block);
  13935. + buf += sprintf(buf, "total_bytes_per_chunk %d\n",
  13936. + param->total_bytes_per_chunk);
  13937. + buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc);
  13938. + buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc);
  13939. + buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2);
  13940. + buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags);
  13941. + buf += sprintf(buf, "empty_lost_n_found... %d\n",
  13942. + param->empty_lost_n_found);
  13943. + buf += sprintf(buf, "disable_lazy_load.... %d\n",
  13944. + param->disable_lazy_load);
  13945. + buf += sprintf(buf, "disable_bad_block_mrk %d\n",
  13946. + param->disable_bad_block_marking);
  13947. + buf += sprintf(buf, "refresh_period....... %d\n",
  13948. + param->refresh_period);
  13949. + buf += sprintf(buf, "n_caches............. %d\n", param->n_caches);
  13950. + buf += sprintf(buf, "n_reserved_blocks.... %d\n",
  13951. + param->n_reserved_blocks);
  13952. + buf += sprintf(buf, "always_check_erased.. %d\n",
  13953. + param->always_check_erased);
  13954. + buf += sprintf(buf, "\n");
  13955. + buf += sprintf(buf, "block count by state\n");
  13956. + buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n",
  13957. + bs[0], bs[1], bs[2], bs[3], bs[4]);
  13958. + buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n",
  13959. + bs[5], bs[6], bs[7], bs[8], bs[9]);
  13960. +
  13961. + return buf;
  13962. +}
  13963. +
  13964. +static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
  13965. +{
  13966. + buf += sprintf(buf, "max file size....... %lld\n",
  13967. + (long long) yaffs_max_file_size(dev));
  13968. + buf += sprintf(buf, "data_bytes_per_chunk. %d\n",
  13969. + dev->data_bytes_per_chunk);
  13970. + buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits);
  13971. + buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size);
  13972. + buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks);
  13973. + buf += sprintf(buf, "blocks_in_checkpt.... %d\n",
  13974. + dev->blocks_in_checkpt);
  13975. + buf += sprintf(buf, "\n");
  13976. + buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes);
  13977. + buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj);
  13978. + buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks);
  13979. + buf += sprintf(buf, "\n");
  13980. + buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes);
  13981. + buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads);
  13982. + buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures);
  13983. + buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies);
  13984. + buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs);
  13985. + buf += sprintf(buf, "passive_gc_count..... %u\n",
  13986. + dev->passive_gc_count);
  13987. + buf += sprintf(buf, "oldest_dirty_gc_count %u\n",
  13988. + dev->oldest_dirty_gc_count);
  13989. + buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks);
  13990. + buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs);
  13991. + buf += sprintf(buf, "n_retried_writes..... %u\n",
  13992. + dev->n_retried_writes);
  13993. + buf += sprintf(buf, "n_retired_blocks..... %u\n",
  13994. + dev->n_retired_blocks);
  13995. + buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed);
  13996. + buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed);
  13997. + buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n",
  13998. + dev->n_tags_ecc_fixed);
  13999. + buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n",
  14000. + dev->n_tags_ecc_unfixed);
  14001. + buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits);
  14002. + buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files);
  14003. + buf += sprintf(buf, "n_unlinked_files..... %u\n",
  14004. + dev->n_unlinked_files);
  14005. + buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
  14006. + buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
  14007. + buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
  14008. + buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
  14009. +
  14010. + return buf;
  14011. +}
  14012. +
  14013. +static int yaffs_proc_read(char *page,
  14014. + char **start,
  14015. + off_t offset, int count, int *eof, void *data)
  14016. +{
  14017. + struct list_head *item;
  14018. + char *buf = page;
  14019. + int step = offset;
  14020. + int n = 0;
  14021. +
  14022. + /* Get proc_file_read() to step 'offset' by one on each sucessive call.
  14023. + * We use 'offset' (*ppos) to indicate where we are in dev_list.
  14024. + * This also assumes the user has posted a read buffer large
  14025. + * enough to hold the complete output; but that's life in /proc.
  14026. + */
  14027. +
  14028. + *(int *)start = 1;
  14029. +
  14030. + /* Print header first */
  14031. + if (step == 0)
  14032. + buf +=
  14033. + sprintf(buf,
  14034. + "Multi-version YAFFS\n");
  14035. + else if (step == 1)
  14036. + buf += sprintf(buf, "\n");
  14037. + else {
  14038. + step -= 2;
  14039. +
  14040. + mutex_lock(&yaffs_context_lock);
  14041. +
  14042. + /* Locate and print the Nth entry. Order N-squared but N is small. */
  14043. + list_for_each(item, &yaffs_context_list) {
  14044. + struct yaffs_linux_context *dc =
  14045. + list_entry(item, struct yaffs_linux_context,
  14046. + context_list);
  14047. + struct yaffs_dev *dev = dc->dev;
  14048. +
  14049. + if (n < (step & ~1)) {
  14050. + n += 2;
  14051. + continue;
  14052. + }
  14053. + if ((step & 1) == 0) {
  14054. + buf +=
  14055. + sprintf(buf, "\nDevice %d \"%s\"\n", n,
  14056. + dev->param.name);
  14057. + buf = yaffs_dump_dev_part0(buf, dev);
  14058. + } else {
  14059. + buf = yaffs_dump_dev_part1(buf, dev);
  14060. + }
  14061. +
  14062. + break;
  14063. + }
  14064. + mutex_unlock(&yaffs_context_lock);
  14065. + }
  14066. +
  14067. + return buf - page < count ? buf - page : count;
  14068. +}
  14069. +
  14070. +/**
  14071. + * Set the verbosity of the warnings and error messages.
  14072. + *
  14073. + * Note that the names can only be a..z or _ with the current code.
  14074. + */
  14075. +
  14076. +static struct {
  14077. + char *mask_name;
  14078. + unsigned mask_bitfield;
  14079. +} mask_flags[] = {
  14080. + {"allocate", YAFFS_TRACE_ALLOCATE},
  14081. + {"always", YAFFS_TRACE_ALWAYS},
  14082. + {"background", YAFFS_TRACE_BACKGROUND},
  14083. + {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS},
  14084. + {"buffers", YAFFS_TRACE_BUFFERS},
  14085. + {"bug", YAFFS_TRACE_BUG},
  14086. + {"checkpt", YAFFS_TRACE_CHECKPOINT},
  14087. + {"deletion", YAFFS_TRACE_DELETION},
  14088. + {"erase", YAFFS_TRACE_ERASE},
  14089. + {"error", YAFFS_TRACE_ERROR},
  14090. + {"gc_detail", YAFFS_TRACE_GC_DETAIL},
  14091. + {"gc", YAFFS_TRACE_GC},
  14092. + {"lock", YAFFS_TRACE_LOCK},
  14093. + {"mtd", YAFFS_TRACE_MTD},
  14094. + {"nandaccess", YAFFS_TRACE_NANDACCESS},
  14095. + {"os", YAFFS_TRACE_OS},
  14096. + {"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
  14097. + {"scan", YAFFS_TRACE_SCAN},
  14098. + {"mount", YAFFS_TRACE_MOUNT},
  14099. + {"tracing", YAFFS_TRACE_TRACING},
  14100. + {"sync", YAFFS_TRACE_SYNC},
  14101. + {"write", YAFFS_TRACE_WRITE},
  14102. + {"verify", YAFFS_TRACE_VERIFY},
  14103. + {"verify_nand", YAFFS_TRACE_VERIFY_NAND},
  14104. + {"verify_full", YAFFS_TRACE_VERIFY_FULL},
  14105. + {"verify_all", YAFFS_TRACE_VERIFY_ALL},
  14106. + {"all", 0xffffffff},
  14107. + {"none", 0},
  14108. + {NULL, 0},
  14109. +};
  14110. +
  14111. +#define MAX_MASK_NAME_LENGTH 40
  14112. +static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
  14113. + unsigned long count)
  14114. +{
  14115. + unsigned rg = 0, mask_bitfield;
  14116. + char *end;
  14117. + char *mask_name;
  14118. + const char *x;
  14119. + char substring[MAX_MASK_NAME_LENGTH + 1];
  14120. + int i;
  14121. + int done = 0;
  14122. + int add, len = 0;
  14123. + int pos = 0;
  14124. +
  14125. + rg = yaffs_trace_mask;
  14126. +
  14127. + while (!done && (pos < count)) {
  14128. + done = 1;
  14129. + while ((pos < count) && isspace(buf[pos]))
  14130. + pos++;
  14131. +
  14132. + switch (buf[pos]) {
  14133. + case '+':
  14134. + case '-':
  14135. + case '=':
  14136. + add = buf[pos];
  14137. + pos++;
  14138. + break;
  14139. +
  14140. + default:
  14141. + add = ' ';
  14142. + break;
  14143. + }
  14144. + mask_name = NULL;
  14145. +
  14146. + mask_bitfield = simple_strtoul(buf + pos, &end, 0);
  14147. +
  14148. + if (end > buf + pos) {
  14149. + mask_name = "numeral";
  14150. + len = end - (buf + pos);
  14151. + pos += len;
  14152. + done = 0;
  14153. + } else {
  14154. + for (x = buf + pos, i = 0;
  14155. + (*x == '_' || (*x >= 'a' && *x <= 'z')) &&
  14156. + i < MAX_MASK_NAME_LENGTH; x++, i++, pos++)
  14157. + substring[i] = *x;
  14158. + substring[i] = '\0';
  14159. +
  14160. + for (i = 0; mask_flags[i].mask_name != NULL; i++) {
  14161. + if (strcmp(substring, mask_flags[i].mask_name)
  14162. + == 0) {
  14163. + mask_name = mask_flags[i].mask_name;
  14164. + mask_bitfield =
  14165. + mask_flags[i].mask_bitfield;
  14166. + done = 0;
  14167. + break;
  14168. + }
  14169. + }
  14170. + }
  14171. +
  14172. + if (mask_name != NULL) {
  14173. + done = 0;
  14174. + switch (add) {
  14175. + case '-':
  14176. + rg &= ~mask_bitfield;
  14177. + break;
  14178. + case '+':
  14179. + rg |= mask_bitfield;
  14180. + break;
  14181. + case '=':
  14182. + rg = mask_bitfield;
  14183. + break;
  14184. + default:
  14185. + rg |= mask_bitfield;
  14186. + break;
  14187. + }
  14188. + }
  14189. + }
  14190. +
  14191. + yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS;
  14192. +
  14193. + printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask);
  14194. +
  14195. + if (rg & YAFFS_TRACE_ALWAYS) {
  14196. + for (i = 0; mask_flags[i].mask_name != NULL; i++) {
  14197. + char flag;
  14198. + flag = ((rg & mask_flags[i].mask_bitfield) ==
  14199. + mask_flags[i].mask_bitfield) ? '+' : '-';
  14200. + printk(KERN_DEBUG "%c%s\n", flag,
  14201. + mask_flags[i].mask_name);
  14202. + }
  14203. + }
  14204. +
  14205. + return count;
  14206. +}
  14207. +
  14208. +/* Debug strings are of the form:
  14209. + * .bnnn print info on block n
  14210. + * .cobjn,chunkn print nand chunk id for objn:chunkn
  14211. + */
  14212. +
  14213. +static int yaffs_proc_debug_write(struct file *file, const char *buf,
  14214. + unsigned long count)
  14215. +{
  14216. +
  14217. + char str[100];
  14218. + char *p0;
  14219. + char *p1;
  14220. + long p1_val;
  14221. + long p0_val;
  14222. + char cmd;
  14223. + struct list_head *item;
  14224. +
  14225. + memset(str, 0, sizeof(str));
  14226. + memcpy(str, buf, min((size_t)count, sizeof(str) -1));
  14227. +
  14228. + cmd = str[1];
  14229. +
  14230. + p0 = str + 2;
  14231. +
  14232. + p1 = p0;
  14233. +
  14234. + while (*p1 && *p1 != ',') {
  14235. + p1++;
  14236. + }
  14237. + *p1 = '\0';
  14238. + p1++;
  14239. +
  14240. + p0_val = simple_strtol(p0, NULL, 0);
  14241. + p1_val = simple_strtol(p1, NULL, 0);
  14242. +
  14243. +
  14244. + mutex_lock(&yaffs_context_lock);
  14245. +
  14246. + /* Locate and print the Nth entry. Order N-squared but N is small. */
  14247. + list_for_each(item, &yaffs_context_list) {
  14248. + struct yaffs_linux_context *dc =
  14249. + list_entry(item, struct yaffs_linux_context,
  14250. + context_list);
  14251. + struct yaffs_dev *dev = dc->dev;
  14252. +
  14253. + if (cmd == 'b') {
  14254. + struct yaffs_block_info *bi;
  14255. +
  14256. + bi = yaffs_get_block_info(dev,p0_val);
  14257. +
  14258. + if(bi) {
  14259. + printk("Block %d: state %d, retire %d, use %d, seq %d\n",
  14260. + (int)p0_val, bi->block_state,
  14261. + bi->needs_retiring, bi->pages_in_use,
  14262. + bi->seq_number);
  14263. + }
  14264. + } else if (cmd == 'c') {
  14265. + struct yaffs_obj *obj;
  14266. + int nand_chunk;
  14267. +
  14268. + obj = yaffs_find_by_number(dev, p0_val);
  14269. + if (!obj)
  14270. + printk("No obj %d\n", (int)p0_val);
  14271. + else {
  14272. + if(p1_val == 0)
  14273. + nand_chunk = obj->hdr_chunk;
  14274. + else
  14275. + nand_chunk =
  14276. + yaffs_find_chunk_in_file(obj,
  14277. + p1_val, NULL);
  14278. + printk("Nand chunk for %d:%d is %d\n",
  14279. + (int)p0_val, (int)p1_val, nand_chunk);
  14280. + }
  14281. + }
  14282. + }
  14283. +
  14284. + mutex_unlock(&yaffs_context_lock);
  14285. +
  14286. + return count;
  14287. +}
  14288. +
  14289. +
  14290. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  14291. +static int yaffs_proc_write(struct file *file, const char *buf,
  14292. + unsigned long count, void *ppos)
  14293. +#else
  14294. +static ssize_t yaffs_proc_write(struct file *file, const char __user *buf,
  14295. + size_t count, loff_t *ppos)
  14296. +#endif
  14297. +{
  14298. + if (buf[0] == '.')
  14299. + return yaffs_proc_debug_write(file, buf, count);
  14300. + return yaffs_proc_write_trace_options(file, buf, count);
  14301. +}
  14302. +
  14303. +/* Stuff to handle installation of file systems */
  14304. +struct file_system_to_install {
  14305. + struct file_system_type *fst;
  14306. + int installed;
  14307. +};
  14308. +
  14309. +static struct file_system_to_install fs_to_install[] = {
  14310. + {&yaffs_fs_type, 0},
  14311. + {&yaffs2_fs_type, 0},
  14312. + {NULL, 0}
  14313. +};
  14314. +
  14315. +
  14316. +#ifdef YAFFS_NEW_PROCFS
  14317. +static int yaffs_proc_show(struct seq_file *m, void *v)
  14318. +{
  14319. + /* FIXME: Unify in a better way? */
  14320. + char buffer[512];
  14321. + char *start;
  14322. + int len;
  14323. +
  14324. + len = yaffs_proc_read(buffer, &start, 0, sizeof(buffer), NULL, NULL);
  14325. + seq_puts(m, buffer);
  14326. + return 0;
  14327. +}
  14328. +
  14329. +static int yaffs_proc_open(struct inode *inode, struct file *file)
  14330. +{
  14331. + return single_open(file, yaffs_proc_show, NULL);
  14332. +}
  14333. +
  14334. +static struct file_operations procfs_ops = {
  14335. + .owner = THIS_MODULE,
  14336. + .open = yaffs_proc_open,
  14337. + .read = seq_read,
  14338. + .write = yaffs_proc_write,
  14339. +};
  14340. +
  14341. +static int yaffs_procfs_init(void)
  14342. +{
  14343. + /* Install the proc_fs entries */
  14344. + my_proc_entry = proc_create("yaffs",
  14345. + S_IRUGO | S_IFREG,
  14346. + YPROC_ROOT,
  14347. + &procfs_ops);
  14348. +
  14349. + if (my_proc_entry) {
  14350. + return 0;
  14351. + } else {
  14352. + return -ENOMEM;
  14353. + }
  14354. +}
  14355. +
  14356. +#else
  14357. +
  14358. +
  14359. +static int yaffs_procfs_init(void)
  14360. +{
  14361. + /* Install the proc_fs entries */
  14362. + my_proc_entry = create_proc_entry("yaffs",
  14363. + S_IRUGO | S_IFREG, YPROC_ROOT);
  14364. +
  14365. + if (my_proc_entry) {
  14366. + my_proc_entry->write_proc = yaffs_proc_write;
  14367. + my_proc_entry->read_proc = yaffs_proc_read;
  14368. + my_proc_entry->data = NULL;
  14369. + return 0;
  14370. + } else {
  14371. + return -ENOMEM;
  14372. + }
  14373. +}
  14374. +
  14375. +#endif
  14376. +
  14377. +
  14378. +static int __init init_yaffs_fs(void)
  14379. +{
  14380. + int error = 0;
  14381. + struct file_system_to_install *fsinst;
  14382. +
  14383. + mutex_init(&yaffs_context_lock);
  14384. +
  14385. + error = yaffs_procfs_init();
  14386. + if (error)
  14387. + return error;
  14388. +
  14389. + /* Now add the file system entries */
  14390. +
  14391. + fsinst = fs_to_install;
  14392. +
  14393. + while (fsinst->fst && !error) {
  14394. + error = register_filesystem(fsinst->fst);
  14395. + if (!error)
  14396. + fsinst->installed = 1;
  14397. + fsinst++;
  14398. + }
  14399. +
  14400. + /* Any errors? uninstall */
  14401. + if (error) {
  14402. + fsinst = fs_to_install;
  14403. +
  14404. + while (fsinst->fst) {
  14405. + if (fsinst->installed) {
  14406. + unregister_filesystem(fsinst->fst);
  14407. + fsinst->installed = 0;
  14408. + }
  14409. + fsinst++;
  14410. + }
  14411. + }
  14412. +
  14413. + return error;
  14414. +}
  14415. +
  14416. +static void __exit exit_yaffs_fs(void)
  14417. +{
  14418. +
  14419. + struct file_system_to_install *fsinst;
  14420. +
  14421. + remove_proc_entry("yaffs", YPROC_ROOT);
  14422. +
  14423. + fsinst = fs_to_install;
  14424. +
  14425. + while (fsinst->fst) {
  14426. + if (fsinst->installed) {
  14427. + unregister_filesystem(fsinst->fst);
  14428. + fsinst->installed = 0;
  14429. + }
  14430. + fsinst++;
  14431. + }
  14432. +}
  14433. +
  14434. +module_init(init_yaffs_fs)
  14435. + module_exit(exit_yaffs_fs)
  14436. +
  14437. + MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
  14438. +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
  14439. +MODULE_LICENSE("GPL");
  14440. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs1.c linux-3.18.14/fs/yaffs2/yaffs_yaffs1.c
  14441. --- linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs1.c 1970-01-01 01:00:00.000000000 +0100
  14442. +++ linux-3.18.14/fs/yaffs2/yaffs_yaffs1.c 2015-06-14 21:23:22.000000000 +0200
  14443. @@ -0,0 +1,422 @@
  14444. +/*
  14445. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  14446. + *
  14447. + * Copyright (C) 2002-2011 Aleph One Ltd.
  14448. + * for Toby Churchill Ltd and Brightstar Engineering
  14449. + *
  14450. + * Created by Charles Manning <charles@aleph1.co.uk>
  14451. + *
  14452. + * This program is free software; you can redistribute it and/or modify
  14453. + * it under the terms of the GNU General Public License version 2 as
  14454. + * published by the Free Software Foundation.
  14455. + */
  14456. +
  14457. +#include "yaffs_yaffs1.h"
  14458. +#include "yportenv.h"
  14459. +#include "yaffs_trace.h"
  14460. +#include "yaffs_bitmap.h"
  14461. +#include "yaffs_getblockinfo.h"
  14462. +#include "yaffs_nand.h"
  14463. +#include "yaffs_attribs.h"
  14464. +
  14465. +int yaffs1_scan(struct yaffs_dev *dev)
  14466. +{
  14467. + struct yaffs_ext_tags tags;
  14468. + int blk;
  14469. + int result;
  14470. + int chunk;
  14471. + int c;
  14472. + int deleted;
  14473. + enum yaffs_block_state state;
  14474. + LIST_HEAD(hard_list);
  14475. + struct yaffs_block_info *bi;
  14476. + u32 seq_number;
  14477. + struct yaffs_obj_hdr *oh;
  14478. + struct yaffs_obj *in;
  14479. + struct yaffs_obj *parent;
  14480. + int alloc_failed = 0;
  14481. + struct yaffs_shadow_fixer *shadow_fixers = NULL;
  14482. + u8 *chunk_data;
  14483. +
  14484. + yaffs_trace(YAFFS_TRACE_SCAN,
  14485. + "yaffs1_scan starts intstartblk %d intendblk %d...",
  14486. + dev->internal_start_block, dev->internal_end_block);
  14487. +
  14488. + chunk_data = yaffs_get_temp_buffer(dev);
  14489. +
  14490. + dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
  14491. +
  14492. + /* Scan all the blocks to determine their state */
  14493. + bi = dev->block_info;
  14494. + for (blk = dev->internal_start_block; blk <= dev->internal_end_block;
  14495. + blk++) {
  14496. + yaffs_clear_chunk_bits(dev, blk);
  14497. + bi->pages_in_use = 0;
  14498. + bi->soft_del_pages = 0;
  14499. +
  14500. + yaffs_query_init_block_state(dev, blk, &state, &seq_number);
  14501. +
  14502. + bi->block_state = state;
  14503. + bi->seq_number = seq_number;
  14504. +
  14505. + if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK)
  14506. + bi->block_state = state = YAFFS_BLOCK_STATE_DEAD;
  14507. +
  14508. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG,
  14509. + "Block scanning block %d state %d seq %d",
  14510. + blk, state, seq_number);
  14511. +
  14512. + if (state == YAFFS_BLOCK_STATE_DEAD) {
  14513. + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
  14514. + "block %d is bad", blk);
  14515. + } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
  14516. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty ");
  14517. + dev->n_erased_blocks++;
  14518. + dev->n_free_chunks += dev->param.chunks_per_block;
  14519. + }
  14520. + bi++;
  14521. + }
  14522. +
  14523. + /* For each block.... */
  14524. + for (blk = dev->internal_start_block;
  14525. + !alloc_failed && blk <= dev->internal_end_block; blk++) {
  14526. +
  14527. + cond_resched();
  14528. +
  14529. + bi = yaffs_get_block_info(dev, blk);
  14530. + state = bi->block_state;
  14531. +
  14532. + deleted = 0;
  14533. +
  14534. + /* For each chunk in each block that needs scanning.... */
  14535. + for (c = 0;
  14536. + !alloc_failed && c < dev->param.chunks_per_block &&
  14537. + state == YAFFS_BLOCK_STATE_NEEDS_SCAN; c++) {
  14538. + /* Read the tags and decide what to do */
  14539. + chunk = blk * dev->param.chunks_per_block + c;
  14540. +
  14541. + result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL,
  14542. + &tags);
  14543. +
  14544. + /* Let's have a good look at this chunk... */
  14545. +
  14546. + if (tags.ecc_result == YAFFS_ECC_RESULT_UNFIXED ||
  14547. + tags.is_deleted) {
  14548. + /* YAFFS1 only...
  14549. + * A deleted chunk
  14550. + */
  14551. + deleted++;
  14552. + dev->n_free_chunks++;
  14553. + } else if (!tags.chunk_used) {
  14554. + /* An unassigned chunk in the block
  14555. + * This means that either the block is empty or
  14556. + * this is the one being allocated from
  14557. + */
  14558. +
  14559. + if (c == 0) {
  14560. + /* We're looking at the first chunk in
  14561. + *the block so the block is unused */
  14562. + state = YAFFS_BLOCK_STATE_EMPTY;
  14563. + dev->n_erased_blocks++;
  14564. + } else {
  14565. + /* this is the block being allocated */
  14566. + yaffs_trace(YAFFS_TRACE_SCAN,
  14567. + " Allocating from %d %d",
  14568. + blk, c);
  14569. + state = YAFFS_BLOCK_STATE_ALLOCATING;
  14570. + dev->alloc_block = blk;
  14571. + dev->alloc_page = c;
  14572. + dev->alloc_block_finder = blk;
  14573. +
  14574. + }
  14575. +
  14576. + dev->n_free_chunks +=
  14577. + (dev->param.chunks_per_block - c);
  14578. + } else if (tags.chunk_id > 0) {
  14579. + /* chunk_id > 0 so it is a data chunk... */
  14580. + unsigned int endpos;
  14581. +
  14582. + yaffs_set_chunk_bit(dev, blk, c);
  14583. + bi->pages_in_use++;
  14584. +
  14585. + in = yaffs_find_or_create_by_number(dev,
  14586. + tags.obj_id,
  14587. + YAFFS_OBJECT_TYPE_FILE);
  14588. + /* PutChunkIntoFile checks for a clash
  14589. + * (two data chunks with the same chunk_id).
  14590. + */
  14591. +
  14592. + if (!in)
  14593. + alloc_failed = 1;
  14594. +
  14595. + if (in) {
  14596. + if (!yaffs_put_chunk_in_file
  14597. + (in, tags.chunk_id, chunk, 1))
  14598. + alloc_failed = 1;
  14599. + }
  14600. +
  14601. + endpos =
  14602. + (tags.chunk_id - 1) *
  14603. + dev->data_bytes_per_chunk +
  14604. + tags.n_bytes;
  14605. + if (in &&
  14606. + in->variant_type ==
  14607. + YAFFS_OBJECT_TYPE_FILE &&
  14608. + in->variant.file_variant.scanned_size <
  14609. + endpos) {
  14610. + in->variant.file_variant.scanned_size =
  14611. + endpos;
  14612. + if (!dev->param.use_header_file_size) {
  14613. + in->variant.
  14614. + file_variant.file_size =
  14615. + in->variant.
  14616. + file_variant.scanned_size;
  14617. + }
  14618. +
  14619. + }
  14620. + } else {
  14621. + /* chunk_id == 0, so it is an ObjectHeader.
  14622. + * Make the object
  14623. + */
  14624. + yaffs_set_chunk_bit(dev, blk, c);
  14625. + bi->pages_in_use++;
  14626. +
  14627. + result = yaffs_rd_chunk_tags_nand(dev, chunk,
  14628. + chunk_data,
  14629. + NULL);
  14630. +
  14631. + oh = (struct yaffs_obj_hdr *)chunk_data;
  14632. +
  14633. + in = yaffs_find_by_number(dev, tags.obj_id);
  14634. + if (in && in->variant_type != oh->type) {
  14635. + /* This should not happen, but somehow
  14636. + * Wev'e ended up with an obj_id that
  14637. + * has been reused but not yet deleted,
  14638. + * and worse still it has changed type.
  14639. + * Delete the old object.
  14640. + */
  14641. +
  14642. + yaffs_del_obj(in);
  14643. + in = NULL;
  14644. + }
  14645. +
  14646. + in = yaffs_find_or_create_by_number(dev,
  14647. + tags.obj_id,
  14648. + oh->type);
  14649. +
  14650. + if (!in)
  14651. + alloc_failed = 1;
  14652. +
  14653. + if (in && oh->shadows_obj > 0) {
  14654. +
  14655. + struct yaffs_shadow_fixer *fixer;
  14656. + fixer =
  14657. + kmalloc(sizeof
  14658. + (struct yaffs_shadow_fixer),
  14659. + GFP_NOFS);
  14660. + if (fixer) {
  14661. + fixer->next = shadow_fixers;
  14662. + shadow_fixers = fixer;
  14663. + fixer->obj_id = tags.obj_id;
  14664. + fixer->shadowed_id =
  14665. + oh->shadows_obj;
  14666. + yaffs_trace(YAFFS_TRACE_SCAN,
  14667. + " Shadow fixer: %d shadows %d",
  14668. + fixer->obj_id,
  14669. + fixer->shadowed_id);
  14670. +
  14671. + }
  14672. +
  14673. + }
  14674. +
  14675. + if (in && in->valid) {
  14676. + /* We have already filled this one.
  14677. + * We have a duplicate and need to
  14678. + * resolve it. */
  14679. +
  14680. + unsigned existing_serial = in->serial;
  14681. + unsigned new_serial =
  14682. + tags.serial_number;
  14683. +
  14684. + if (((existing_serial + 1) & 3) ==
  14685. + new_serial) {
  14686. + /* Use new one - destroy the
  14687. + * exisiting one */
  14688. + yaffs_chunk_del(dev,
  14689. + in->hdr_chunk,
  14690. + 1, __LINE__);
  14691. + in->valid = 0;
  14692. + } else {
  14693. + /* Use existing - destroy
  14694. + * this one. */
  14695. + yaffs_chunk_del(dev, chunk, 1,
  14696. + __LINE__);
  14697. + }
  14698. + }
  14699. +
  14700. + if (in && !in->valid &&
  14701. + (tags.obj_id == YAFFS_OBJECTID_ROOT ||
  14702. + tags.obj_id ==
  14703. + YAFFS_OBJECTID_LOSTNFOUND)) {
  14704. + /* We only load some info, don't fiddle
  14705. + * with directory structure */
  14706. + in->valid = 1;
  14707. + in->variant_type = oh->type;
  14708. +
  14709. + in->yst_mode = oh->yst_mode;
  14710. + yaffs_load_attribs(in, oh);
  14711. + in->hdr_chunk = chunk;
  14712. + in->serial = tags.serial_number;
  14713. +
  14714. + } else if (in && !in->valid) {
  14715. + /* we need to load this info */
  14716. +
  14717. + in->valid = 1;
  14718. + in->variant_type = oh->type;
  14719. +
  14720. + in->yst_mode = oh->yst_mode;
  14721. + yaffs_load_attribs(in, oh);
  14722. + in->hdr_chunk = chunk;
  14723. + in->serial = tags.serial_number;
  14724. +
  14725. + yaffs_set_obj_name_from_oh(in, oh);
  14726. + in->dirty = 0;
  14727. +
  14728. + /* directory stuff...
  14729. + * hook up to parent
  14730. + */
  14731. +
  14732. + parent =
  14733. + yaffs_find_or_create_by_number
  14734. + (dev, oh->parent_obj_id,
  14735. + YAFFS_OBJECT_TYPE_DIRECTORY);
  14736. + if (!parent)
  14737. + alloc_failed = 1;
  14738. + if (parent && parent->variant_type ==
  14739. + YAFFS_OBJECT_TYPE_UNKNOWN) {
  14740. + /* Set up as a directory */
  14741. + parent->variant_type =
  14742. + YAFFS_OBJECT_TYPE_DIRECTORY;
  14743. + INIT_LIST_HEAD(&parent->
  14744. + variant.dir_variant.
  14745. + children);
  14746. + } else if (!parent ||
  14747. + parent->variant_type !=
  14748. + YAFFS_OBJECT_TYPE_DIRECTORY) {
  14749. + /* Hoosterman, a problem....
  14750. + * We're trying to use a
  14751. + * non-directory as a directory
  14752. + */
  14753. +
  14754. + yaffs_trace(YAFFS_TRACE_ERROR,
  14755. + "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
  14756. + );
  14757. + parent = dev->lost_n_found;
  14758. + }
  14759. +
  14760. + yaffs_add_obj_to_dir(parent, in);
  14761. +
  14762. + switch (in->variant_type) {
  14763. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  14764. + /* Todo got a problem */
  14765. + break;
  14766. + case YAFFS_OBJECT_TYPE_FILE:
  14767. + if (dev->param.
  14768. + use_header_file_size)
  14769. + in->variant.
  14770. + file_variant.file_size
  14771. + = yaffs_oh_to_size(oh);
  14772. + break;
  14773. + case YAFFS_OBJECT_TYPE_HARDLINK:
  14774. + in->variant.
  14775. + hardlink_variant.equiv_id =
  14776. + oh->equiv_id;
  14777. + list_add(&in->hard_links,
  14778. + &hard_list);
  14779. + break;
  14780. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  14781. + /* Do nothing */
  14782. + break;
  14783. + case YAFFS_OBJECT_TYPE_SPECIAL:
  14784. + /* Do nothing */
  14785. + break;
  14786. + case YAFFS_OBJECT_TYPE_SYMLINK:
  14787. + in->variant.symlink_variant.
  14788. + alias =
  14789. + yaffs_clone_str(oh->alias);
  14790. + if (!in->variant.
  14791. + symlink_variant.alias)
  14792. + alloc_failed = 1;
  14793. + break;
  14794. + }
  14795. + }
  14796. + }
  14797. + }
  14798. +
  14799. + if (state == YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  14800. + /* If we got this far while scanning,
  14801. + * then the block is fully allocated. */
  14802. + state = YAFFS_BLOCK_STATE_FULL;
  14803. + }
  14804. +
  14805. + if (state == YAFFS_BLOCK_STATE_ALLOCATING) {
  14806. + /* If the block was partially allocated then
  14807. + * treat it as fully allocated. */
  14808. + state = YAFFS_BLOCK_STATE_FULL;
  14809. + dev->alloc_block = -1;
  14810. + }
  14811. +
  14812. + bi->block_state = state;
  14813. +
  14814. + /* Now let's see if it was dirty */
  14815. + if (bi->pages_in_use == 0 &&
  14816. + !bi->has_shrink_hdr &&
  14817. + bi->block_state == YAFFS_BLOCK_STATE_FULL)
  14818. + yaffs_block_became_dirty(dev, blk);
  14819. + }
  14820. +
  14821. + /* Ok, we've done all the scanning.
  14822. + * Fix up the hard link chains.
  14823. + * We should now have scanned all the objects, now it's time to add
  14824. + * these hardlinks.
  14825. + */
  14826. +
  14827. + yaffs_link_fixup(dev, &hard_list);
  14828. +
  14829. + /*
  14830. + * Fix up any shadowed objects.
  14831. + * There should not be more than one of these.
  14832. + */
  14833. + {
  14834. + struct yaffs_shadow_fixer *fixer;
  14835. + struct yaffs_obj *obj;
  14836. +
  14837. + while (shadow_fixers) {
  14838. + fixer = shadow_fixers;
  14839. + shadow_fixers = fixer->next;
  14840. + /* Complete the rename transaction by deleting the
  14841. + * shadowed object then setting the object header
  14842. + to unshadowed.
  14843. + */
  14844. + obj = yaffs_find_by_number(dev, fixer->shadowed_id);
  14845. + if (obj)
  14846. + yaffs_del_obj(obj);
  14847. +
  14848. + obj = yaffs_find_by_number(dev, fixer->obj_id);
  14849. +
  14850. + if (obj)
  14851. + yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
  14852. +
  14853. + kfree(fixer);
  14854. + }
  14855. + }
  14856. +
  14857. + yaffs_release_temp_buffer(dev, chunk_data);
  14858. +
  14859. + if (alloc_failed)
  14860. + return YAFFS_FAIL;
  14861. +
  14862. + yaffs_trace(YAFFS_TRACE_SCAN, "yaffs1_scan ends");
  14863. +
  14864. + return YAFFS_OK;
  14865. +}
  14866. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs1.h linux-3.18.14/fs/yaffs2/yaffs_yaffs1.h
  14867. --- linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs1.h 1970-01-01 01:00:00.000000000 +0100
  14868. +++ linux-3.18.14/fs/yaffs2/yaffs_yaffs1.h 2015-06-14 21:23:22.000000000 +0200
  14869. @@ -0,0 +1,22 @@
  14870. +/*
  14871. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  14872. + *
  14873. + * Copyright (C) 2002-2011 Aleph One Ltd.
  14874. + * for Toby Churchill Ltd and Brightstar Engineering
  14875. + *
  14876. + * Created by Charles Manning <charles@aleph1.co.uk>
  14877. + *
  14878. + * This program is free software; you can redistribute it and/or modify
  14879. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  14880. + * published by the Free Software Foundation.
  14881. + *
  14882. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  14883. + */
  14884. +
  14885. +#ifndef __YAFFS_YAFFS1_H__
  14886. +#define __YAFFS_YAFFS1_H__
  14887. +
  14888. +#include "yaffs_guts.h"
  14889. +int yaffs1_scan(struct yaffs_dev *dev);
  14890. +
  14891. +#endif
  14892. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs2.c linux-3.18.14/fs/yaffs2/yaffs_yaffs2.c
  14893. --- linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs2.c 1970-01-01 01:00:00.000000000 +0100
  14894. +++ linux-3.18.14/fs/yaffs2/yaffs_yaffs2.c 2015-06-14 21:23:22.000000000 +0200
  14895. @@ -0,0 +1,1532 @@
  14896. +/*
  14897. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  14898. + *
  14899. + * Copyright (C) 2002-2011 Aleph One Ltd.
  14900. + * for Toby Churchill Ltd and Brightstar Engineering
  14901. + *
  14902. + * Created by Charles Manning <charles@aleph1.co.uk>
  14903. + *
  14904. + * This program is free software; you can redistribute it and/or modify
  14905. + * it under the terms of the GNU General Public License version 2 as
  14906. + * published by the Free Software Foundation.
  14907. + */
  14908. +
  14909. +#include "yaffs_guts.h"
  14910. +#include "yaffs_trace.h"
  14911. +#include "yaffs_yaffs2.h"
  14912. +#include "yaffs_checkptrw.h"
  14913. +#include "yaffs_bitmap.h"
  14914. +#include "yaffs_nand.h"
  14915. +#include "yaffs_getblockinfo.h"
  14916. +#include "yaffs_verify.h"
  14917. +#include "yaffs_attribs.h"
  14918. +#include "yaffs_summary.h"
  14919. +
  14920. +/*
  14921. + * Checkpoints are really no benefit on very small partitions.
  14922. + *
  14923. + * To save space on small partitions don't bother with checkpoints unless
  14924. + * the partition is at least this big.
  14925. + */
  14926. +#define YAFFS_CHECKPOINT_MIN_BLOCKS 60
  14927. +#define YAFFS_SMALL_HOLE_THRESHOLD 4
  14928. +
  14929. +/*
  14930. + * Oldest Dirty Sequence Number handling.
  14931. + */
  14932. +
  14933. +/* yaffs_calc_oldest_dirty_seq()
  14934. + * yaffs2_find_oldest_dirty_seq()
  14935. + * Calculate the oldest dirty sequence number if we don't know it.
  14936. + */
  14937. +void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev)
  14938. +{
  14939. + int i;
  14940. + unsigned seq;
  14941. + unsigned block_no = 0;
  14942. + struct yaffs_block_info *b;
  14943. +
  14944. + if (!dev->param.is_yaffs2)
  14945. + return;
  14946. +
  14947. + /* Find the oldest dirty sequence number. */
  14948. + seq = dev->seq_number + 1;
  14949. + b = dev->block_info;
  14950. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  14951. + if (b->block_state == YAFFS_BLOCK_STATE_FULL &&
  14952. + (b->pages_in_use - b->soft_del_pages) <
  14953. + dev->param.chunks_per_block &&
  14954. + b->seq_number < seq) {
  14955. + seq = b->seq_number;
  14956. + block_no = i;
  14957. + }
  14958. + b++;
  14959. + }
  14960. +
  14961. + if (block_no) {
  14962. + dev->oldest_dirty_seq = seq;
  14963. + dev->oldest_dirty_block = block_no;
  14964. + }
  14965. +}
  14966. +
  14967. +void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev)
  14968. +{
  14969. + if (!dev->param.is_yaffs2)
  14970. + return;
  14971. +
  14972. + if (!dev->oldest_dirty_seq)
  14973. + yaffs_calc_oldest_dirty_seq(dev);
  14974. +}
  14975. +
  14976. +/*
  14977. + * yaffs_clear_oldest_dirty_seq()
  14978. + * Called when a block is erased or marked bad. (ie. when its seq_number
  14979. + * becomes invalid). If the value matches the oldest then we clear
  14980. + * dev->oldest_dirty_seq to force its recomputation.
  14981. + */
  14982. +void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev,
  14983. + struct yaffs_block_info *bi)
  14984. +{
  14985. +
  14986. + if (!dev->param.is_yaffs2)
  14987. + return;
  14988. +
  14989. + if (!bi || bi->seq_number == dev->oldest_dirty_seq) {
  14990. + dev->oldest_dirty_seq = 0;
  14991. + dev->oldest_dirty_block = 0;
  14992. + }
  14993. +}
  14994. +
  14995. +/*
  14996. + * yaffs2_update_oldest_dirty_seq()
  14997. + * Update the oldest dirty sequence number whenever we dirty a block.
  14998. + * Only do this if the oldest_dirty_seq is actually being tracked.
  14999. + */
  15000. +void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no,
  15001. + struct yaffs_block_info *bi)
  15002. +{
  15003. + if (!dev->param.is_yaffs2)
  15004. + return;
  15005. +
  15006. + if (dev->oldest_dirty_seq) {
  15007. + if (dev->oldest_dirty_seq > bi->seq_number) {
  15008. + dev->oldest_dirty_seq = bi->seq_number;
  15009. + dev->oldest_dirty_block = block_no;
  15010. + }
  15011. + }
  15012. +}
  15013. +
  15014. +int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi)
  15015. +{
  15016. +
  15017. + if (!dev->param.is_yaffs2)
  15018. + return 1; /* disqualification only applies to yaffs2. */
  15019. +
  15020. + if (!bi->has_shrink_hdr)
  15021. + return 1; /* can gc */
  15022. +
  15023. + yaffs2_find_oldest_dirty_seq(dev);
  15024. +
  15025. + /* Can't do gc of this block if there are any blocks older than this
  15026. + * one that have discarded pages.
  15027. + */
  15028. + return (bi->seq_number <= dev->oldest_dirty_seq);
  15029. +}
  15030. +
  15031. +/*
  15032. + * yaffs2_find_refresh_block()
  15033. + * periodically finds the oldest full block by sequence number for refreshing.
  15034. + * Only for yaffs2.
  15035. + */
  15036. +u32 yaffs2_find_refresh_block(struct yaffs_dev *dev)
  15037. +{
  15038. + u32 b;
  15039. + u32 oldest = 0;
  15040. + u32 oldest_seq = 0;
  15041. + struct yaffs_block_info *bi;
  15042. +
  15043. + if (!dev->param.is_yaffs2)
  15044. + return oldest;
  15045. +
  15046. + /*
  15047. + * If refresh period < 10 then refreshing is disabled.
  15048. + */
  15049. + if (dev->param.refresh_period < 10)
  15050. + return oldest;
  15051. +
  15052. + /*
  15053. + * Fix broken values.
  15054. + */
  15055. + if (dev->refresh_skip > dev->param.refresh_period)
  15056. + dev->refresh_skip = dev->param.refresh_period;
  15057. +
  15058. + if (dev->refresh_skip > 0)
  15059. + return oldest;
  15060. +
  15061. + /*
  15062. + * Refresh skip is now zero.
  15063. + * We'll do a refresh this time around....
  15064. + * Update the refresh skip and find the oldest block.
  15065. + */
  15066. + dev->refresh_skip = dev->param.refresh_period;
  15067. + dev->refresh_count++;
  15068. + bi = dev->block_info;
  15069. + for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) {
  15070. +
  15071. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL) {
  15072. +
  15073. + if (oldest < 1 || bi->seq_number < oldest_seq) {
  15074. + oldest = b;
  15075. + oldest_seq = bi->seq_number;
  15076. + }
  15077. + }
  15078. + bi++;
  15079. + }
  15080. +
  15081. + if (oldest > 0) {
  15082. + yaffs_trace(YAFFS_TRACE_GC,
  15083. + "GC refresh count %d selected block %d with seq_number %d",
  15084. + dev->refresh_count, oldest, oldest_seq);
  15085. + }
  15086. +
  15087. + return oldest;
  15088. +}
  15089. +
  15090. +int yaffs2_checkpt_required(struct yaffs_dev *dev)
  15091. +{
  15092. + int nblocks;
  15093. +
  15094. + if (!dev->param.is_yaffs2)
  15095. + return 0;
  15096. +
  15097. + nblocks = dev->internal_end_block - dev->internal_start_block + 1;
  15098. +
  15099. + return !dev->param.skip_checkpt_wr &&
  15100. + !dev->read_only && (nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS);
  15101. +}
  15102. +
  15103. +int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev)
  15104. +{
  15105. + int retval;
  15106. + int n_bytes = 0;
  15107. + int n_blocks;
  15108. + int dev_blocks;
  15109. +
  15110. + if (!dev->param.is_yaffs2)
  15111. + return 0;
  15112. +
  15113. + if (!dev->checkpoint_blocks_required && yaffs2_checkpt_required(dev)) {
  15114. + /* Not a valid value so recalculate */
  15115. + dev_blocks = dev->param.end_block - dev->param.start_block + 1;
  15116. + n_bytes += sizeof(struct yaffs_checkpt_validity);
  15117. + n_bytes += sizeof(struct yaffs_checkpt_dev);
  15118. + n_bytes += dev_blocks * sizeof(struct yaffs_block_info);
  15119. + n_bytes += dev_blocks * dev->chunk_bit_stride;
  15120. + n_bytes +=
  15121. + (sizeof(struct yaffs_checkpt_obj) + sizeof(u32)) *
  15122. + dev->n_obj;
  15123. + n_bytes += (dev->tnode_size + sizeof(u32)) * dev->n_tnodes;
  15124. + n_bytes += sizeof(struct yaffs_checkpt_validity);
  15125. + n_bytes += sizeof(u32); /* checksum */
  15126. +
  15127. + /* Round up and add 2 blocks to allow for some bad blocks,
  15128. + * so add 3 */
  15129. +
  15130. + n_blocks =
  15131. + (n_bytes /
  15132. + (dev->data_bytes_per_chunk *
  15133. + dev->param.chunks_per_block)) + 3;
  15134. +
  15135. + dev->checkpoint_blocks_required = n_blocks;
  15136. + }
  15137. +
  15138. + retval = dev->checkpoint_blocks_required - dev->blocks_in_checkpt;
  15139. + if (retval < 0)
  15140. + retval = 0;
  15141. + return retval;
  15142. +}
  15143. +
  15144. +/*--------------------- Checkpointing --------------------*/
  15145. +
  15146. +static int yaffs2_wr_checkpt_validity_marker(struct yaffs_dev *dev, int head)
  15147. +{
  15148. + struct yaffs_checkpt_validity cp;
  15149. +
  15150. + memset(&cp, 0, sizeof(cp));
  15151. +
  15152. + cp.struct_type = sizeof(cp);
  15153. + cp.magic = YAFFS_MAGIC;
  15154. + cp.version = YAFFS_CHECKPOINT_VERSION;
  15155. + cp.head = (head) ? 1 : 0;
  15156. +
  15157. + return (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)) ? 1 : 0;
  15158. +}
  15159. +
  15160. +static int yaffs2_rd_checkpt_validity_marker(struct yaffs_dev *dev, int head)
  15161. +{
  15162. + struct yaffs_checkpt_validity cp;
  15163. + int ok;
  15164. +
  15165. + ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
  15166. +
  15167. + if (ok)
  15168. + ok = (cp.struct_type == sizeof(cp)) &&
  15169. + (cp.magic == YAFFS_MAGIC) &&
  15170. + (cp.version == YAFFS_CHECKPOINT_VERSION) &&
  15171. + (cp.head == ((head) ? 1 : 0));
  15172. + return ok ? 1 : 0;
  15173. +}
  15174. +
  15175. +static void yaffs2_dev_to_checkpt_dev(struct yaffs_checkpt_dev *cp,
  15176. + struct yaffs_dev *dev)
  15177. +{
  15178. + cp->n_erased_blocks = dev->n_erased_blocks;
  15179. + cp->alloc_block = dev->alloc_block;
  15180. + cp->alloc_page = dev->alloc_page;
  15181. + cp->n_free_chunks = dev->n_free_chunks;
  15182. +
  15183. + cp->n_deleted_files = dev->n_deleted_files;
  15184. + cp->n_unlinked_files = dev->n_unlinked_files;
  15185. + cp->n_bg_deletions = dev->n_bg_deletions;
  15186. + cp->seq_number = dev->seq_number;
  15187. +
  15188. +}
  15189. +
  15190. +static void yaffs_checkpt_dev_to_dev(struct yaffs_dev *dev,
  15191. + struct yaffs_checkpt_dev *cp)
  15192. +{
  15193. + dev->n_erased_blocks = cp->n_erased_blocks;
  15194. + dev->alloc_block = cp->alloc_block;
  15195. + dev->alloc_page = cp->alloc_page;
  15196. + dev->n_free_chunks = cp->n_free_chunks;
  15197. +
  15198. + dev->n_deleted_files = cp->n_deleted_files;
  15199. + dev->n_unlinked_files = cp->n_unlinked_files;
  15200. + dev->n_bg_deletions = cp->n_bg_deletions;
  15201. + dev->seq_number = cp->seq_number;
  15202. +}
  15203. +
  15204. +static int yaffs2_wr_checkpt_dev(struct yaffs_dev *dev)
  15205. +{
  15206. + struct yaffs_checkpt_dev cp;
  15207. + u32 n_bytes;
  15208. + u32 n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
  15209. + int ok;
  15210. +
  15211. + /* Write device runtime values */
  15212. + yaffs2_dev_to_checkpt_dev(&cp, dev);
  15213. + cp.struct_type = sizeof(cp);
  15214. +
  15215. + ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
  15216. + if (!ok)
  15217. + return 0;
  15218. +
  15219. + /* Write block info */
  15220. + n_bytes = n_blocks * sizeof(struct yaffs_block_info);
  15221. + ok = (yaffs2_checkpt_wr(dev, dev->block_info, n_bytes) == n_bytes);
  15222. + if (!ok)
  15223. + return 0;
  15224. +
  15225. + /* Write chunk bits */
  15226. + n_bytes = n_blocks * dev->chunk_bit_stride;
  15227. + ok = (yaffs2_checkpt_wr(dev, dev->chunk_bits, n_bytes) == n_bytes);
  15228. +
  15229. + return ok ? 1 : 0;
  15230. +}
  15231. +
  15232. +static int yaffs2_rd_checkpt_dev(struct yaffs_dev *dev)
  15233. +{
  15234. + struct yaffs_checkpt_dev cp;
  15235. + u32 n_bytes;
  15236. + u32 n_blocks =
  15237. + (dev->internal_end_block - dev->internal_start_block + 1);
  15238. + int ok;
  15239. +
  15240. + ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
  15241. + if (!ok)
  15242. + return 0;
  15243. +
  15244. + if (cp.struct_type != sizeof(cp))
  15245. + return 0;
  15246. +
  15247. + yaffs_checkpt_dev_to_dev(dev, &cp);
  15248. +
  15249. + n_bytes = n_blocks * sizeof(struct yaffs_block_info);
  15250. +
  15251. + ok = (yaffs2_checkpt_rd(dev, dev->block_info, n_bytes) == n_bytes);
  15252. +
  15253. + if (!ok)
  15254. + return 0;
  15255. +
  15256. + n_bytes = n_blocks * dev->chunk_bit_stride;
  15257. +
  15258. + ok = (yaffs2_checkpt_rd(dev, dev->chunk_bits, n_bytes) == n_bytes);
  15259. +
  15260. + return ok ? 1 : 0;
  15261. +}
  15262. +
  15263. +static void yaffs2_obj_checkpt_obj(struct yaffs_checkpt_obj *cp,
  15264. + struct yaffs_obj *obj)
  15265. +{
  15266. + cp->obj_id = obj->obj_id;
  15267. + cp->parent_id = (obj->parent) ? obj->parent->obj_id : 0;
  15268. + cp->hdr_chunk = obj->hdr_chunk;
  15269. + cp->variant_type = obj->variant_type;
  15270. + cp->deleted = obj->deleted;
  15271. + cp->soft_del = obj->soft_del;
  15272. + cp->unlinked = obj->unlinked;
  15273. + cp->fake = obj->fake;
  15274. + cp->rename_allowed = obj->rename_allowed;
  15275. + cp->unlink_allowed = obj->unlink_allowed;
  15276. + cp->serial = obj->serial;
  15277. + cp->n_data_chunks = obj->n_data_chunks;
  15278. +
  15279. + if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
  15280. + cp->size_or_equiv_obj = obj->variant.file_variant.file_size;
  15281. + else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK)
  15282. + cp->size_or_equiv_obj = obj->variant.hardlink_variant.equiv_id;
  15283. +}
  15284. +
  15285. +static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj,
  15286. + struct yaffs_checkpt_obj *cp)
  15287. +{
  15288. + struct yaffs_obj *parent;
  15289. +
  15290. + if (obj->variant_type != cp->variant_type) {
  15291. + yaffs_trace(YAFFS_TRACE_ERROR,
  15292. + "Checkpoint read object %d type %d chunk %d does not match existing object type %d",
  15293. + cp->obj_id, cp->variant_type, cp->hdr_chunk,
  15294. + obj->variant_type);
  15295. + return 0;
  15296. + }
  15297. +
  15298. + obj->obj_id = cp->obj_id;
  15299. +
  15300. + if (cp->parent_id)
  15301. + parent = yaffs_find_or_create_by_number(obj->my_dev,
  15302. + cp->parent_id,
  15303. + YAFFS_OBJECT_TYPE_DIRECTORY);
  15304. + else
  15305. + parent = NULL;
  15306. +
  15307. + if (parent) {
  15308. + if (parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  15309. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  15310. + "Checkpoint read object %d parent %d type %d chunk %d Parent type, %d, not directory",
  15311. + cp->obj_id, cp->parent_id,
  15312. + cp->variant_type, cp->hdr_chunk,
  15313. + parent->variant_type);
  15314. + return 0;
  15315. + }
  15316. + yaffs_add_obj_to_dir(parent, obj);
  15317. + }
  15318. +
  15319. + obj->hdr_chunk = cp->hdr_chunk;
  15320. + obj->variant_type = cp->variant_type;
  15321. + obj->deleted = cp->deleted;
  15322. + obj->soft_del = cp->soft_del;
  15323. + obj->unlinked = cp->unlinked;
  15324. + obj->fake = cp->fake;
  15325. + obj->rename_allowed = cp->rename_allowed;
  15326. + obj->unlink_allowed = cp->unlink_allowed;
  15327. + obj->serial = cp->serial;
  15328. + obj->n_data_chunks = cp->n_data_chunks;
  15329. +
  15330. + if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
  15331. + obj->variant.file_variant.file_size = cp->size_or_equiv_obj;
  15332. + else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK)
  15333. + obj->variant.hardlink_variant.equiv_id = cp->size_or_equiv_obj;
  15334. +
  15335. + if (obj->hdr_chunk > 0)
  15336. + obj->lazy_loaded = 1;
  15337. + return 1;
  15338. +}
  15339. +
  15340. +static int yaffs2_checkpt_tnode_worker(struct yaffs_obj *in,
  15341. + struct yaffs_tnode *tn, u32 level,
  15342. + int chunk_offset)
  15343. +{
  15344. + int i;
  15345. + struct yaffs_dev *dev = in->my_dev;
  15346. + int ok = 1;
  15347. + u32 base_offset;
  15348. +
  15349. + if (!tn)
  15350. + return 1;
  15351. +
  15352. + if (level > 0) {
  15353. + for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {
  15354. + if (!tn->internal[i])
  15355. + continue;
  15356. + ok = yaffs2_checkpt_tnode_worker(in,
  15357. + tn->internal[i],
  15358. + level - 1,
  15359. + (chunk_offset <<
  15360. + YAFFS_TNODES_INTERNAL_BITS) + i);
  15361. + }
  15362. + return ok;
  15363. + }
  15364. +
  15365. + /* Level 0 tnode */
  15366. + base_offset = chunk_offset << YAFFS_TNODES_LEVEL0_BITS;
  15367. + ok = (yaffs2_checkpt_wr(dev, &base_offset, sizeof(base_offset)) ==
  15368. + sizeof(base_offset));
  15369. + if (ok)
  15370. + ok = (yaffs2_checkpt_wr(dev, tn, dev->tnode_size) ==
  15371. + dev->tnode_size);
  15372. +
  15373. + return ok;
  15374. +}
  15375. +
  15376. +static int yaffs2_wr_checkpt_tnodes(struct yaffs_obj *obj)
  15377. +{
  15378. + u32 end_marker = ~0;
  15379. + int ok = 1;
  15380. +
  15381. + if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
  15382. + return ok;
  15383. +
  15384. + ok = yaffs2_checkpt_tnode_worker(obj,
  15385. + obj->variant.file_variant.top,
  15386. + obj->variant.file_variant.
  15387. + top_level, 0);
  15388. + if (ok)
  15389. + ok = (yaffs2_checkpt_wr(obj->my_dev, &end_marker,
  15390. + sizeof(end_marker)) == sizeof(end_marker));
  15391. +
  15392. + return ok ? 1 : 0;
  15393. +}
  15394. +
  15395. +static int yaffs2_rd_checkpt_tnodes(struct yaffs_obj *obj)
  15396. +{
  15397. + u32 base_chunk;
  15398. + int ok = 1;
  15399. + struct yaffs_dev *dev = obj->my_dev;
  15400. + struct yaffs_file_var *file_stuct_ptr = &obj->variant.file_variant;
  15401. + struct yaffs_tnode *tn;
  15402. + int nread = 0;
  15403. +
  15404. + ok = (yaffs2_checkpt_rd(dev, &base_chunk, sizeof(base_chunk)) ==
  15405. + sizeof(base_chunk));
  15406. +
  15407. + while (ok && (~base_chunk)) {
  15408. + nread++;
  15409. + /* Read level 0 tnode */
  15410. +
  15411. + tn = yaffs_get_tnode(dev);
  15412. + if (tn)
  15413. + ok = (yaffs2_checkpt_rd(dev, tn, dev->tnode_size) ==
  15414. + dev->tnode_size);
  15415. + else
  15416. + ok = 0;
  15417. +
  15418. + if (tn && ok)
  15419. + ok = yaffs_add_find_tnode_0(dev,
  15420. + file_stuct_ptr,
  15421. + base_chunk, tn) ? 1 : 0;
  15422. +
  15423. + if (ok)
  15424. + ok = (yaffs2_checkpt_rd
  15425. + (dev, &base_chunk,
  15426. + sizeof(base_chunk)) == sizeof(base_chunk));
  15427. + }
  15428. +
  15429. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15430. + "Checkpoint read tnodes %d records, last %d. ok %d",
  15431. + nread, base_chunk, ok);
  15432. +
  15433. + return ok ? 1 : 0;
  15434. +}
  15435. +
  15436. +static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev)
  15437. +{
  15438. + struct yaffs_obj *obj;
  15439. + struct yaffs_checkpt_obj cp;
  15440. + int i;
  15441. + int ok = 1;
  15442. + struct list_head *lh;
  15443. +
  15444. + /* Iterate through the objects in each hash entry,
  15445. + * dumping them to the checkpointing stream.
  15446. + */
  15447. +
  15448. + for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) {
  15449. + list_for_each(lh, &dev->obj_bucket[i].list) {
  15450. + obj = list_entry(lh, struct yaffs_obj, hash_link);
  15451. + if (!obj->defered_free) {
  15452. + yaffs2_obj_checkpt_obj(&cp, obj);
  15453. + cp.struct_type = sizeof(cp);
  15454. +
  15455. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15456. + "Checkpoint write object %d parent %d type %d chunk %d obj addr %p",
  15457. + cp.obj_id, cp.parent_id,
  15458. + cp.variant_type, cp.hdr_chunk, obj);
  15459. +
  15460. + ok = (yaffs2_checkpt_wr(dev, &cp,
  15461. + sizeof(cp)) == sizeof(cp));
  15462. +
  15463. + if (ok &&
  15464. + obj->variant_type ==
  15465. + YAFFS_OBJECT_TYPE_FILE)
  15466. + ok = yaffs2_wr_checkpt_tnodes(obj);
  15467. + }
  15468. + }
  15469. + }
  15470. +
  15471. + /* Dump end of list */
  15472. + memset(&cp, 0xff, sizeof(struct yaffs_checkpt_obj));
  15473. + cp.struct_type = sizeof(cp);
  15474. +
  15475. + if (ok)
  15476. + ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
  15477. +
  15478. + return ok ? 1 : 0;
  15479. +}
  15480. +
  15481. +static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev)
  15482. +{
  15483. + struct yaffs_obj *obj;
  15484. + struct yaffs_checkpt_obj cp;
  15485. + int ok = 1;
  15486. + int done = 0;
  15487. + LIST_HEAD(hard_list);
  15488. +
  15489. +
  15490. + while (ok && !done) {
  15491. + ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
  15492. + if (cp.struct_type != sizeof(cp)) {
  15493. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15494. + "struct size %d instead of %d ok %d",
  15495. + cp.struct_type, (int)sizeof(cp), ok);
  15496. + ok = 0;
  15497. + }
  15498. +
  15499. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15500. + "Checkpoint read object %d parent %d type %d chunk %d ",
  15501. + cp.obj_id, cp.parent_id, cp.variant_type,
  15502. + cp.hdr_chunk);
  15503. +
  15504. + if (ok && cp.obj_id == ~0) {
  15505. + done = 1;
  15506. + } else if (ok) {
  15507. + obj =
  15508. + yaffs_find_or_create_by_number(dev, cp.obj_id,
  15509. + cp.variant_type);
  15510. + if (obj) {
  15511. + ok = yaffs2_checkpt_obj_to_obj(obj, &cp);
  15512. + if (!ok)
  15513. + break;
  15514. + if (obj->variant_type ==
  15515. + YAFFS_OBJECT_TYPE_FILE) {
  15516. + ok = yaffs2_rd_checkpt_tnodes(obj);
  15517. + } else if (obj->variant_type ==
  15518. + YAFFS_OBJECT_TYPE_HARDLINK) {
  15519. + list_add(&obj->hard_links, &hard_list);
  15520. + }
  15521. + } else {
  15522. + ok = 0;
  15523. + }
  15524. + }
  15525. + }
  15526. +
  15527. + if (ok)
  15528. + yaffs_link_fixup(dev, &hard_list);
  15529. +
  15530. + return ok ? 1 : 0;
  15531. +}
  15532. +
  15533. +static int yaffs2_wr_checkpt_sum(struct yaffs_dev *dev)
  15534. +{
  15535. + u32 checkpt_sum;
  15536. + int ok;
  15537. +
  15538. + yaffs2_get_checkpt_sum(dev, &checkpt_sum);
  15539. +
  15540. + ok = (yaffs2_checkpt_wr(dev, &checkpt_sum, sizeof(checkpt_sum)) ==
  15541. + sizeof(checkpt_sum));
  15542. +
  15543. + if (!ok)
  15544. + return 0;
  15545. +
  15546. + return 1;
  15547. +}
  15548. +
  15549. +static int yaffs2_rd_checkpt_sum(struct yaffs_dev *dev)
  15550. +{
  15551. + u32 checkpt_sum0;
  15552. + u32 checkpt_sum1;
  15553. + int ok;
  15554. +
  15555. + yaffs2_get_checkpt_sum(dev, &checkpt_sum0);
  15556. +
  15557. + ok = (yaffs2_checkpt_rd(dev, &checkpt_sum1, sizeof(checkpt_sum1)) ==
  15558. + sizeof(checkpt_sum1));
  15559. +
  15560. + if (!ok)
  15561. + return 0;
  15562. +
  15563. + if (checkpt_sum0 != checkpt_sum1)
  15564. + return 0;
  15565. +
  15566. + return 1;
  15567. +}
  15568. +
  15569. +static int yaffs2_wr_checkpt_data(struct yaffs_dev *dev)
  15570. +{
  15571. + int ok = 1;
  15572. +
  15573. + if (!yaffs2_checkpt_required(dev)) {
  15574. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15575. + "skipping checkpoint write");
  15576. + ok = 0;
  15577. + }
  15578. +
  15579. + if (ok)
  15580. + ok = yaffs2_checkpt_open(dev, 1);
  15581. +
  15582. + if (ok) {
  15583. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15584. + "write checkpoint validity");
  15585. + ok = yaffs2_wr_checkpt_validity_marker(dev, 1);
  15586. + }
  15587. + if (ok) {
  15588. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15589. + "write checkpoint device");
  15590. + ok = yaffs2_wr_checkpt_dev(dev);
  15591. + }
  15592. + if (ok) {
  15593. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15594. + "write checkpoint objects");
  15595. + ok = yaffs2_wr_checkpt_objs(dev);
  15596. + }
  15597. + if (ok) {
  15598. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15599. + "write checkpoint validity");
  15600. + ok = yaffs2_wr_checkpt_validity_marker(dev, 0);
  15601. + }
  15602. +
  15603. + if (ok)
  15604. + ok = yaffs2_wr_checkpt_sum(dev);
  15605. +
  15606. + if (!yaffs_checkpt_close(dev))
  15607. + ok = 0;
  15608. +
  15609. + if (ok)
  15610. + dev->is_checkpointed = 1;
  15611. + else
  15612. + dev->is_checkpointed = 0;
  15613. +
  15614. + return dev->is_checkpointed;
  15615. +}
  15616. +
  15617. +static int yaffs2_rd_checkpt_data(struct yaffs_dev *dev)
  15618. +{
  15619. + int ok = 1;
  15620. +
  15621. + if (!dev->param.is_yaffs2)
  15622. + ok = 0;
  15623. +
  15624. + if (ok && dev->param.skip_checkpt_rd) {
  15625. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15626. + "skipping checkpoint read");
  15627. + ok = 0;
  15628. + }
  15629. +
  15630. + if (ok)
  15631. + ok = yaffs2_checkpt_open(dev, 0); /* open for read */
  15632. +
  15633. + if (ok) {
  15634. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15635. + "read checkpoint validity");
  15636. + ok = yaffs2_rd_checkpt_validity_marker(dev, 1);
  15637. + }
  15638. + if (ok) {
  15639. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15640. + "read checkpoint device");
  15641. + ok = yaffs2_rd_checkpt_dev(dev);
  15642. + }
  15643. + if (ok) {
  15644. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15645. + "read checkpoint objects");
  15646. + ok = yaffs2_rd_checkpt_objs(dev);
  15647. + }
  15648. + if (ok) {
  15649. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15650. + "read checkpoint validity");
  15651. + ok = yaffs2_rd_checkpt_validity_marker(dev, 0);
  15652. + }
  15653. +
  15654. + if (ok) {
  15655. + ok = yaffs2_rd_checkpt_sum(dev);
  15656. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15657. + "read checkpoint checksum %d", ok);
  15658. + }
  15659. +
  15660. + if (!yaffs_checkpt_close(dev))
  15661. + ok = 0;
  15662. +
  15663. + if (ok)
  15664. + dev->is_checkpointed = 1;
  15665. + else
  15666. + dev->is_checkpointed = 0;
  15667. +
  15668. + return ok ? 1 : 0;
  15669. +}
  15670. +
  15671. +void yaffs2_checkpt_invalidate(struct yaffs_dev *dev)
  15672. +{
  15673. + if (dev->is_checkpointed || dev->blocks_in_checkpt > 0) {
  15674. + dev->is_checkpointed = 0;
  15675. + yaffs2_checkpt_invalidate_stream(dev);
  15676. + }
  15677. + if (dev->param.sb_dirty_fn)
  15678. + dev->param.sb_dirty_fn(dev);
  15679. +}
  15680. +
  15681. +int yaffs_checkpoint_save(struct yaffs_dev *dev)
  15682. +{
  15683. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15684. + "save entry: is_checkpointed %d",
  15685. + dev->is_checkpointed);
  15686. +
  15687. + yaffs_verify_objects(dev);
  15688. + yaffs_verify_blocks(dev);
  15689. + yaffs_verify_free_chunks(dev);
  15690. +
  15691. + if (!dev->is_checkpointed) {
  15692. + yaffs2_checkpt_invalidate(dev);
  15693. + yaffs2_wr_checkpt_data(dev);
  15694. + }
  15695. +
  15696. + yaffs_trace(YAFFS_TRACE_CHECKPOINT | YAFFS_TRACE_MOUNT,
  15697. + "save exit: is_checkpointed %d",
  15698. + dev->is_checkpointed);
  15699. +
  15700. + return dev->is_checkpointed;
  15701. +}
  15702. +
  15703. +int yaffs2_checkpt_restore(struct yaffs_dev *dev)
  15704. +{
  15705. + int retval;
  15706. +
  15707. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15708. + "restore entry: is_checkpointed %d",
  15709. + dev->is_checkpointed);
  15710. +
  15711. + retval = yaffs2_rd_checkpt_data(dev);
  15712. +
  15713. + if (dev->is_checkpointed) {
  15714. + yaffs_verify_objects(dev);
  15715. + yaffs_verify_blocks(dev);
  15716. + yaffs_verify_free_chunks(dev);
  15717. + }
  15718. +
  15719. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  15720. + "restore exit: is_checkpointed %d",
  15721. + dev->is_checkpointed);
  15722. +
  15723. + return retval;
  15724. +}
  15725. +
  15726. +int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size)
  15727. +{
  15728. + /* if new_size > old_file_size.
  15729. + * We're going to be writing a hole.
  15730. + * If the hole is small then write zeros otherwise write a start
  15731. + * of hole marker.
  15732. + */
  15733. + loff_t old_file_size;
  15734. + loff_t increase;
  15735. + int small_hole;
  15736. + int result = YAFFS_OK;
  15737. + struct yaffs_dev *dev = NULL;
  15738. + u8 *local_buffer = NULL;
  15739. + int small_increase_ok = 0;
  15740. +
  15741. + if (!obj)
  15742. + return YAFFS_FAIL;
  15743. +
  15744. + if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
  15745. + return YAFFS_FAIL;
  15746. +
  15747. + dev = obj->my_dev;
  15748. +
  15749. + /* Bail out if not yaffs2 mode */
  15750. + if (!dev->param.is_yaffs2)
  15751. + return YAFFS_OK;
  15752. +
  15753. + old_file_size = obj->variant.file_variant.file_size;
  15754. +
  15755. + if (new_size <= old_file_size)
  15756. + return YAFFS_OK;
  15757. +
  15758. + increase = new_size - old_file_size;
  15759. +
  15760. + if (increase < YAFFS_SMALL_HOLE_THRESHOLD * dev->data_bytes_per_chunk &&
  15761. + yaffs_check_alloc_available(dev, YAFFS_SMALL_HOLE_THRESHOLD + 1))
  15762. + small_hole = 1;
  15763. + else
  15764. + small_hole = 0;
  15765. +
  15766. + if (small_hole)
  15767. + local_buffer = yaffs_get_temp_buffer(dev);
  15768. +
  15769. + if (local_buffer) {
  15770. + /* fill hole with zero bytes */
  15771. + loff_t pos = old_file_size;
  15772. + int this_write;
  15773. + int written;
  15774. + memset(local_buffer, 0, dev->data_bytes_per_chunk);
  15775. + small_increase_ok = 1;
  15776. +
  15777. + while (increase > 0 && small_increase_ok) {
  15778. + this_write = increase;
  15779. + if (this_write > dev->data_bytes_per_chunk)
  15780. + this_write = dev->data_bytes_per_chunk;
  15781. + written =
  15782. + yaffs_do_file_wr(obj, local_buffer, pos, this_write,
  15783. + 0);
  15784. + if (written == this_write) {
  15785. + pos += this_write;
  15786. + increase -= this_write;
  15787. + } else {
  15788. + small_increase_ok = 0;
  15789. + }
  15790. + }
  15791. +
  15792. + yaffs_release_temp_buffer(dev, local_buffer);
  15793. +
  15794. + /* If out of space then reverse any chunks we've added */
  15795. + if (!small_increase_ok)
  15796. + yaffs_resize_file_down(obj, old_file_size);
  15797. + }
  15798. +
  15799. + if (!small_increase_ok &&
  15800. + obj->parent &&
  15801. + obj->parent->obj_id != YAFFS_OBJECTID_UNLINKED &&
  15802. + obj->parent->obj_id != YAFFS_OBJECTID_DELETED) {
  15803. + /* Write a hole start header with the old file size */
  15804. + yaffs_update_oh(obj, NULL, 0, 1, 0, NULL);
  15805. + }
  15806. +
  15807. + return result;
  15808. +}
  15809. +
  15810. +struct yaffs_block_index {
  15811. + int seq;
  15812. + int block;
  15813. +};
  15814. +
  15815. +static int yaffs2_ybicmp(const void *a, const void *b)
  15816. +{
  15817. + int aseq = ((struct yaffs_block_index *)a)->seq;
  15818. + int bseq = ((struct yaffs_block_index *)b)->seq;
  15819. + int ablock = ((struct yaffs_block_index *)a)->block;
  15820. + int bblock = ((struct yaffs_block_index *)b)->block;
  15821. +
  15822. + if (aseq == bseq)
  15823. + return ablock - bblock;
  15824. +
  15825. + return aseq - bseq;
  15826. +}
  15827. +
  15828. +static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
  15829. + struct yaffs_block_info *bi,
  15830. + int blk, int chunk_in_block,
  15831. + int *found_chunks,
  15832. + u8 *chunk_data,
  15833. + struct list_head *hard_list,
  15834. + int summary_available)
  15835. +{
  15836. + struct yaffs_obj_hdr *oh;
  15837. + struct yaffs_obj *in;
  15838. + struct yaffs_obj *parent;
  15839. + int equiv_id;
  15840. + loff_t file_size;
  15841. + int is_shrink;
  15842. + int is_unlinked;
  15843. + struct yaffs_ext_tags tags;
  15844. + int result;
  15845. + int alloc_failed = 0;
  15846. + int chunk = blk * dev->param.chunks_per_block + chunk_in_block;
  15847. + struct yaffs_file_var *file_var;
  15848. + struct yaffs_hardlink_var *hl_var;
  15849. + struct yaffs_symlink_var *sl_var;
  15850. +
  15851. + if (summary_available) {
  15852. + result = yaffs_summary_fetch(dev, &tags, chunk_in_block);
  15853. + tags.seq_number = bi->seq_number;
  15854. + }
  15855. +
  15856. + if (!summary_available || tags.obj_id == 0) {
  15857. + result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
  15858. + dev->tags_used++;
  15859. + } else {
  15860. + dev->summary_used++;
  15861. + }
  15862. +
  15863. + /* Let's have a good look at this chunk... */
  15864. +
  15865. + if (!tags.chunk_used) {
  15866. + /* An unassigned chunk in the block.
  15867. + * If there are used chunks after this one, then
  15868. + * it is a chunk that was skipped due to failing
  15869. + * the erased check. Just skip it so that it can
  15870. + * be deleted.
  15871. + * But, more typically, We get here when this is
  15872. + * an unallocated chunk and his means that
  15873. + * either the block is empty or this is the one
  15874. + * being allocated from
  15875. + */
  15876. +
  15877. + if (*found_chunks) {
  15878. + /* This is a chunk that was skipped due
  15879. + * to failing the erased check */
  15880. + } else if (chunk_in_block == 0) {
  15881. + /* We're looking at the first chunk in
  15882. + * the block so the block is unused */
  15883. + bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
  15884. + dev->n_erased_blocks++;
  15885. + } else {
  15886. + if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
  15887. + bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) {
  15888. + if (dev->seq_number == bi->seq_number) {
  15889. + /* Allocating from this block*/
  15890. + yaffs_trace(YAFFS_TRACE_SCAN,
  15891. + " Allocating from %d %d",
  15892. + blk, chunk_in_block);
  15893. +
  15894. + bi->block_state =
  15895. + YAFFS_BLOCK_STATE_ALLOCATING;
  15896. + dev->alloc_block = blk;
  15897. + dev->alloc_page = chunk_in_block;
  15898. + dev->alloc_block_finder = blk;
  15899. + } else {
  15900. + /* This is a partially written block
  15901. + * that is not the current
  15902. + * allocation block.
  15903. + */
  15904. + yaffs_trace(YAFFS_TRACE_SCAN,
  15905. + "Partially written block %d detected. gc will fix this.",
  15906. + blk);
  15907. + }
  15908. + }
  15909. + }
  15910. +
  15911. + dev->n_free_chunks++;
  15912. +
  15913. + } else if (tags.ecc_result ==
  15914. + YAFFS_ECC_RESULT_UNFIXED) {
  15915. + yaffs_trace(YAFFS_TRACE_SCAN,
  15916. + " Unfixed ECC in chunk(%d:%d), chunk ignored",
  15917. + blk, chunk_in_block);
  15918. + dev->n_free_chunks++;
  15919. + } else if (tags.obj_id > YAFFS_MAX_OBJECT_ID ||
  15920. + tags.chunk_id > YAFFS_MAX_CHUNK_ID ||
  15921. + tags.obj_id == YAFFS_OBJECTID_SUMMARY ||
  15922. + (tags.chunk_id > 0 &&
  15923. + tags.n_bytes > dev->data_bytes_per_chunk) ||
  15924. + tags.seq_number != bi->seq_number) {
  15925. + yaffs_trace(YAFFS_TRACE_SCAN,
  15926. + "Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored",
  15927. + blk, chunk_in_block, tags.obj_id,
  15928. + tags.chunk_id, tags.n_bytes);
  15929. + dev->n_free_chunks++;
  15930. + } else if (tags.chunk_id > 0) {
  15931. + /* chunk_id > 0 so it is a data chunk... */
  15932. + loff_t endpos;
  15933. + loff_t chunk_base = (tags.chunk_id - 1) *
  15934. + dev->data_bytes_per_chunk;
  15935. +
  15936. + *found_chunks = 1;
  15937. +
  15938. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  15939. + bi->pages_in_use++;
  15940. +
  15941. + in = yaffs_find_or_create_by_number(dev,
  15942. + tags.obj_id,
  15943. + YAFFS_OBJECT_TYPE_FILE);
  15944. + if (!in)
  15945. + /* Out of memory */
  15946. + alloc_failed = 1;
  15947. +
  15948. + if (in &&
  15949. + in->variant_type == YAFFS_OBJECT_TYPE_FILE &&
  15950. + chunk_base < in->variant.file_variant.shrink_size) {
  15951. + /* This has not been invalidated by
  15952. + * a resize */
  15953. + if (!yaffs_put_chunk_in_file(in, tags.chunk_id,
  15954. + chunk, -1))
  15955. + alloc_failed = 1;
  15956. +
  15957. + /* File size is calculated by looking at
  15958. + * the data chunks if we have not
  15959. + * seen an object header yet.
  15960. + * Stop this practice once we find an
  15961. + * object header.
  15962. + */
  15963. + endpos = chunk_base + tags.n_bytes;
  15964. +
  15965. + if (!in->valid &&
  15966. + in->variant.file_variant.scanned_size < endpos) {
  15967. + in->variant.file_variant.
  15968. + scanned_size = endpos;
  15969. + in->variant.file_variant.
  15970. + file_size = endpos;
  15971. + }
  15972. + } else if (in) {
  15973. + /* This chunk has been invalidated by a
  15974. + * resize, or a past file deletion
  15975. + * so delete the chunk*/
  15976. + yaffs_chunk_del(dev, chunk, 1, __LINE__);
  15977. + }
  15978. + } else {
  15979. + /* chunk_id == 0, so it is an ObjectHeader.
  15980. + * Thus, we read in the object header and make
  15981. + * the object
  15982. + */
  15983. + *found_chunks = 1;
  15984. +
  15985. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  15986. + bi->pages_in_use++;
  15987. +
  15988. + oh = NULL;
  15989. + in = NULL;
  15990. +
  15991. + if (tags.extra_available) {
  15992. + in = yaffs_find_or_create_by_number(dev,
  15993. + tags.obj_id,
  15994. + tags.extra_obj_type);
  15995. + if (!in)
  15996. + alloc_failed = 1;
  15997. + }
  15998. +
  15999. + if (!in ||
  16000. + (!in->valid && dev->param.disable_lazy_load) ||
  16001. + tags.extra_shadows ||
  16002. + (!in->valid && (tags.obj_id == YAFFS_OBJECTID_ROOT ||
  16003. + tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND))) {
  16004. +
  16005. + /* If we don't have valid info then we
  16006. + * need to read the chunk
  16007. + * TODO In future we can probably defer
  16008. + * reading the chunk and living with
  16009. + * invalid data until needed.
  16010. + */
  16011. +
  16012. + result = yaffs_rd_chunk_tags_nand(dev,
  16013. + chunk,
  16014. + chunk_data,
  16015. + NULL);
  16016. +
  16017. + oh = (struct yaffs_obj_hdr *)chunk_data;
  16018. +
  16019. + if (dev->param.inband_tags) {
  16020. + /* Fix up the header if they got
  16021. + * corrupted by inband tags */
  16022. + oh->shadows_obj =
  16023. + oh->inband_shadowed_obj_id;
  16024. + oh->is_shrink =
  16025. + oh->inband_is_shrink;
  16026. + }
  16027. +
  16028. + if (!in) {
  16029. + in = yaffs_find_or_create_by_number(dev,
  16030. + tags.obj_id, oh->type);
  16031. + if (!in)
  16032. + alloc_failed = 1;
  16033. + }
  16034. + }
  16035. +
  16036. + if (!in) {
  16037. + /* TODO Hoosterman we have a problem! */
  16038. + yaffs_trace(YAFFS_TRACE_ERROR,
  16039. + "yaffs tragedy: Could not make object for object %d at chunk %d during scan",
  16040. + tags.obj_id, chunk);
  16041. + return YAFFS_FAIL;
  16042. + }
  16043. +
  16044. + if (in->valid) {
  16045. + /* We have already filled this one.
  16046. + * We have a duplicate that will be
  16047. + * discarded, but we first have to suck
  16048. + * out resize info if it is a file.
  16049. + */
  16050. + if ((in->variant_type == YAFFS_OBJECT_TYPE_FILE) &&
  16051. + ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) ||
  16052. + (tags.extra_available &&
  16053. + tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
  16054. + )) {
  16055. + loff_t this_size = (oh) ?
  16056. + yaffs_oh_to_size(oh) :
  16057. + tags.extra_file_size;
  16058. + u32 parent_obj_id = (oh) ?
  16059. + oh->parent_obj_id :
  16060. + tags.extra_parent_id;
  16061. +
  16062. + is_shrink = (oh) ?
  16063. + oh->is_shrink :
  16064. + tags.extra_is_shrink;
  16065. +
  16066. + /* If it is deleted (unlinked
  16067. + * at start also means deleted)
  16068. + * we treat the file size as
  16069. + * being zeroed at this point.
  16070. + */
  16071. + if (parent_obj_id == YAFFS_OBJECTID_DELETED ||
  16072. + parent_obj_id == YAFFS_OBJECTID_UNLINKED) {
  16073. + this_size = 0;
  16074. + is_shrink = 1;
  16075. + }
  16076. +
  16077. + if (is_shrink &&
  16078. + in->variant.file_variant.shrink_size >
  16079. + this_size)
  16080. + in->variant.file_variant.shrink_size =
  16081. + this_size;
  16082. +
  16083. + if (is_shrink)
  16084. + bi->has_shrink_hdr = 1;
  16085. + }
  16086. + /* Use existing - destroy this one. */
  16087. + yaffs_chunk_del(dev, chunk, 1, __LINE__);
  16088. + }
  16089. +
  16090. + if (!in->valid && in->variant_type !=
  16091. + (oh ? oh->type : tags.extra_obj_type)) {
  16092. + yaffs_trace(YAFFS_TRACE_ERROR,
  16093. + "yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan",
  16094. + oh ? oh->type : tags.extra_obj_type,
  16095. + in->variant_type, tags.obj_id,
  16096. + chunk);
  16097. + in = yaffs_retype_obj(in, oh ? oh->type : tags.extra_obj_type);
  16098. + }
  16099. +
  16100. + if (!in->valid &&
  16101. + (tags.obj_id == YAFFS_OBJECTID_ROOT ||
  16102. + tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND)) {
  16103. + /* We only load some info, don't fiddle
  16104. + * with directory structure */
  16105. + in->valid = 1;
  16106. +
  16107. + if (oh) {
  16108. + in->yst_mode = oh->yst_mode;
  16109. + yaffs_load_attribs(in, oh);
  16110. + in->lazy_loaded = 0;
  16111. + } else {
  16112. + in->lazy_loaded = 1;
  16113. + }
  16114. + in->hdr_chunk = chunk;
  16115. +
  16116. + } else if (!in->valid) {
  16117. + /* we need to load this info */
  16118. + in->valid = 1;
  16119. + in->hdr_chunk = chunk;
  16120. + if (oh) {
  16121. + in->variant_type = oh->type;
  16122. + in->yst_mode = oh->yst_mode;
  16123. + yaffs_load_attribs(in, oh);
  16124. +
  16125. + if (oh->shadows_obj > 0)
  16126. + yaffs_handle_shadowed_obj(dev,
  16127. + oh->shadows_obj, 1);
  16128. +
  16129. + yaffs_set_obj_name_from_oh(in, oh);
  16130. + parent = yaffs_find_or_create_by_number(dev,
  16131. + oh->parent_obj_id,
  16132. + YAFFS_OBJECT_TYPE_DIRECTORY);
  16133. + file_size = yaffs_oh_to_size(oh);
  16134. + is_shrink = oh->is_shrink;
  16135. + equiv_id = oh->equiv_id;
  16136. + } else {
  16137. + in->variant_type = tags.extra_obj_type;
  16138. + parent = yaffs_find_or_create_by_number(dev,
  16139. + tags.extra_parent_id,
  16140. + YAFFS_OBJECT_TYPE_DIRECTORY);
  16141. + file_size = tags.extra_file_size;
  16142. + is_shrink = tags.extra_is_shrink;
  16143. + equiv_id = tags.extra_equiv_id;
  16144. + in->lazy_loaded = 1;
  16145. + }
  16146. + in->dirty = 0;
  16147. +
  16148. + if (!parent)
  16149. + alloc_failed = 1;
  16150. +
  16151. + /* directory stuff...
  16152. + * hook up to parent
  16153. + */
  16154. +
  16155. + if (parent &&
  16156. + parent->variant_type == YAFFS_OBJECT_TYPE_UNKNOWN) {
  16157. + /* Set up as a directory */
  16158. + parent->variant_type =
  16159. + YAFFS_OBJECT_TYPE_DIRECTORY;
  16160. + INIT_LIST_HEAD(&parent->
  16161. + variant.dir_variant.children);
  16162. + } else if (!parent ||
  16163. + parent->variant_type !=
  16164. + YAFFS_OBJECT_TYPE_DIRECTORY) {
  16165. + /* Hoosterman, another problem....
  16166. + * Trying to use a non-directory as a directory
  16167. + */
  16168. +
  16169. + yaffs_trace(YAFFS_TRACE_ERROR,
  16170. + "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
  16171. + );
  16172. + parent = dev->lost_n_found;
  16173. + }
  16174. + yaffs_add_obj_to_dir(parent, in);
  16175. +
  16176. + is_unlinked = (parent == dev->del_dir) ||
  16177. + (parent == dev->unlinked_dir);
  16178. +
  16179. + if (is_shrink)
  16180. + /* Mark the block */
  16181. + bi->has_shrink_hdr = 1;
  16182. +
  16183. + /* Note re hardlinks.
  16184. + * Since we might scan a hardlink before its equivalent
  16185. + * object is scanned we put them all in a list.
  16186. + * After scanning is complete, we should have all the
  16187. + * objects, so we run through this list and fix up all
  16188. + * the chains.
  16189. + */
  16190. +
  16191. + switch (in->variant_type) {
  16192. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  16193. + /* Todo got a problem */
  16194. + break;
  16195. + case YAFFS_OBJECT_TYPE_FILE:
  16196. + file_var = &in->variant.file_variant;
  16197. + if (file_var->scanned_size < file_size) {
  16198. + /* This covers the case where the file
  16199. + * size is greater than the data held.
  16200. + * This will happen if the file is
  16201. + * resized to be larger than its
  16202. + * current data extents.
  16203. + */
  16204. + file_var->file_size = file_size;
  16205. + file_var->scanned_size = file_size;
  16206. + }
  16207. +
  16208. + if (file_var->shrink_size > file_size)
  16209. + file_var->shrink_size = file_size;
  16210. +
  16211. + break;
  16212. + case YAFFS_OBJECT_TYPE_HARDLINK:
  16213. + hl_var = &in->variant.hardlink_variant;
  16214. + if (!is_unlinked) {
  16215. + hl_var->equiv_id = equiv_id;
  16216. + list_add(&in->hard_links, hard_list);
  16217. + }
  16218. + break;
  16219. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  16220. + /* Do nothing */
  16221. + break;
  16222. + case YAFFS_OBJECT_TYPE_SPECIAL:
  16223. + /* Do nothing */
  16224. + break;
  16225. + case YAFFS_OBJECT_TYPE_SYMLINK:
  16226. + sl_var = &in->variant.symlink_variant;
  16227. + if (oh) {
  16228. + sl_var->alias =
  16229. + yaffs_clone_str(oh->alias);
  16230. + if (!sl_var->alias)
  16231. + alloc_failed = 1;
  16232. + }
  16233. + break;
  16234. + }
  16235. + }
  16236. + }
  16237. + return alloc_failed ? YAFFS_FAIL : YAFFS_OK;
  16238. +}
  16239. +
  16240. +int yaffs2_scan_backwards(struct yaffs_dev *dev)
  16241. +{
  16242. + int blk;
  16243. + int block_iter;
  16244. + int start_iter;
  16245. + int end_iter;
  16246. + int n_to_scan = 0;
  16247. + enum yaffs_block_state state;
  16248. + int c;
  16249. + LIST_HEAD(hard_list);
  16250. + struct yaffs_block_info *bi;
  16251. + u32 seq_number;
  16252. + int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
  16253. + u8 *chunk_data;
  16254. + int found_chunks;
  16255. + int alloc_failed = 0;
  16256. + struct yaffs_block_index *block_index = NULL;
  16257. + int alt_block_index = 0;
  16258. + int summary_available;
  16259. +
  16260. + yaffs_trace(YAFFS_TRACE_SCAN,
  16261. + "yaffs2_scan_backwards starts intstartblk %d intendblk %d...",
  16262. + dev->internal_start_block, dev->internal_end_block);
  16263. +
  16264. + dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
  16265. +
  16266. + block_index =
  16267. + kmalloc(n_blocks * sizeof(struct yaffs_block_index), GFP_NOFS);
  16268. +
  16269. + if (!block_index) {
  16270. + block_index =
  16271. + vmalloc(n_blocks * sizeof(struct yaffs_block_index));
  16272. + alt_block_index = 1;
  16273. + }
  16274. +
  16275. + if (!block_index) {
  16276. + yaffs_trace(YAFFS_TRACE_SCAN,
  16277. + "yaffs2_scan_backwards() could not allocate block index!"
  16278. + );
  16279. + return YAFFS_FAIL;
  16280. + }
  16281. +
  16282. + dev->blocks_in_checkpt = 0;
  16283. +
  16284. + chunk_data = yaffs_get_temp_buffer(dev);
  16285. +
  16286. + /* Scan all the blocks to determine their state */
  16287. + bi = dev->block_info;
  16288. + for (blk = dev->internal_start_block; blk <= dev->internal_end_block;
  16289. + blk++) {
  16290. + yaffs_clear_chunk_bits(dev, blk);
  16291. + bi->pages_in_use = 0;
  16292. + bi->soft_del_pages = 0;
  16293. +
  16294. + yaffs_query_init_block_state(dev, blk, &state, &seq_number);
  16295. +
  16296. + bi->block_state = state;
  16297. + bi->seq_number = seq_number;
  16298. +
  16299. + if (bi->seq_number == YAFFS_SEQUENCE_CHECKPOINT_DATA)
  16300. + bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
  16301. + if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK)
  16302. + bi->block_state = YAFFS_BLOCK_STATE_DEAD;
  16303. +
  16304. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG,
  16305. + "Block scanning block %d state %d seq %d",
  16306. + blk, bi->block_state, seq_number);
  16307. +
  16308. + if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) {
  16309. + dev->blocks_in_checkpt++;
  16310. +
  16311. + } else if (bi->block_state == YAFFS_BLOCK_STATE_DEAD) {
  16312. + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
  16313. + "block %d is bad", blk);
  16314. + } else if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
  16315. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty ");
  16316. + dev->n_erased_blocks++;
  16317. + dev->n_free_chunks += dev->param.chunks_per_block;
  16318. + } else if (bi->block_state ==
  16319. + YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  16320. + /* Determine the highest sequence number */
  16321. + if (seq_number >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
  16322. + seq_number < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
  16323. + block_index[n_to_scan].seq = seq_number;
  16324. + block_index[n_to_scan].block = blk;
  16325. + n_to_scan++;
  16326. + if (seq_number >= dev->seq_number)
  16327. + dev->seq_number = seq_number;
  16328. + } else {
  16329. + /* TODO: Nasty sequence number! */
  16330. + yaffs_trace(YAFFS_TRACE_SCAN,
  16331. + "Block scanning block %d has bad sequence number %d",
  16332. + blk, seq_number);
  16333. + }
  16334. + }
  16335. + bi++;
  16336. + }
  16337. +
  16338. + yaffs_trace(YAFFS_TRACE_ALWAYS, "%d blocks to be sorted...", n_to_scan);
  16339. +
  16340. + cond_resched();
  16341. +
  16342. + /* Sort the blocks by sequence number */
  16343. + sort(block_index, n_to_scan, sizeof(struct yaffs_block_index),
  16344. + yaffs2_ybicmp, NULL);
  16345. +
  16346. + cond_resched();
  16347. +
  16348. + yaffs_trace(YAFFS_TRACE_SCAN, "...done");
  16349. +
  16350. + /* Now scan the blocks looking at the data. */
  16351. + start_iter = 0;
  16352. + end_iter = n_to_scan - 1;
  16353. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "%d blocks to scan", n_to_scan);
  16354. +
  16355. + /* For each block.... backwards */
  16356. + for (block_iter = end_iter;
  16357. + !alloc_failed && block_iter >= start_iter;
  16358. + block_iter--) {
  16359. + /* Cooperative multitasking! This loop can run for so
  16360. + long that watchdog timers expire. */
  16361. + cond_resched();
  16362. +
  16363. + /* get the block to scan in the correct order */
  16364. + blk = block_index[block_iter].block;
  16365. + bi = yaffs_get_block_info(dev, blk);
  16366. +
  16367. + summary_available = yaffs_summary_read(dev, dev->sum_tags, blk);
  16368. +
  16369. + /* For each chunk in each block that needs scanning.... */
  16370. + found_chunks = 0;
  16371. + if (summary_available)
  16372. + c = dev->chunks_per_summary - 1;
  16373. + else
  16374. + c = dev->param.chunks_per_block - 1;
  16375. +
  16376. + for (/* c is already initialised */;
  16377. + !alloc_failed && c >= 0 &&
  16378. + (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
  16379. + bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING);
  16380. + c--) {
  16381. + /* Scan backwards...
  16382. + * Read the tags and decide what to do
  16383. + */
  16384. + if (yaffs2_scan_chunk(dev, bi, blk, c,
  16385. + &found_chunks, chunk_data,
  16386. + &hard_list, summary_available) ==
  16387. + YAFFS_FAIL)
  16388. + alloc_failed = 1;
  16389. + }
  16390. +
  16391. + if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  16392. + /* If we got this far while scanning, then the block
  16393. + * is fully allocated. */
  16394. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  16395. + }
  16396. +
  16397. + /* Now let's see if it was dirty */
  16398. + if (bi->pages_in_use == 0 &&
  16399. + !bi->has_shrink_hdr &&
  16400. + bi->block_state == YAFFS_BLOCK_STATE_FULL) {
  16401. + yaffs_block_became_dirty(dev, blk);
  16402. + }
  16403. + }
  16404. +
  16405. + yaffs_skip_rest_of_block(dev);
  16406. +
  16407. + if (alt_block_index)
  16408. + vfree(block_index);
  16409. + else
  16410. + kfree(block_index);
  16411. +
  16412. + /* Ok, we've done all the scanning.
  16413. + * Fix up the hard link chains.
  16414. + * We have scanned all the objects, now it's time to add these
  16415. + * hardlinks.
  16416. + */
  16417. + yaffs_link_fixup(dev, &hard_list);
  16418. +
  16419. + yaffs_release_temp_buffer(dev, chunk_data);
  16420. +
  16421. + if (alloc_failed)
  16422. + return YAFFS_FAIL;
  16423. +
  16424. + yaffs_trace(YAFFS_TRACE_SCAN, "yaffs2_scan_backwards ends");
  16425. +
  16426. + return YAFFS_OK;
  16427. +}
  16428. diff -Nur linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs2.h linux-3.18.14/fs/yaffs2/yaffs_yaffs2.h
  16429. --- linux-3.18.14.orig/fs/yaffs2/yaffs_yaffs2.h 1970-01-01 01:00:00.000000000 +0100
  16430. +++ linux-3.18.14/fs/yaffs2/yaffs_yaffs2.h 2015-06-14 21:23:22.000000000 +0200
  16431. @@ -0,0 +1,39 @@
  16432. +/*
  16433. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  16434. + *
  16435. + * Copyright (C) 2002-2011 Aleph One Ltd.
  16436. + * for Toby Churchill Ltd and Brightstar Engineering
  16437. + *
  16438. + * Created by Charles Manning <charles@aleph1.co.uk>
  16439. + *
  16440. + * This program is free software; you can redistribute it and/or modify
  16441. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  16442. + * published by the Free Software Foundation.
  16443. + *
  16444. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  16445. + */
  16446. +
  16447. +#ifndef __YAFFS_YAFFS2_H__
  16448. +#define __YAFFS_YAFFS2_H__
  16449. +
  16450. +#include "yaffs_guts.h"
  16451. +
  16452. +void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev);
  16453. +void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev);
  16454. +void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev,
  16455. + struct yaffs_block_info *bi);
  16456. +void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no,
  16457. + struct yaffs_block_info *bi);
  16458. +int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi);
  16459. +u32 yaffs2_find_refresh_block(struct yaffs_dev *dev);
  16460. +int yaffs2_checkpt_required(struct yaffs_dev *dev);
  16461. +int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev);
  16462. +
  16463. +void yaffs2_checkpt_invalidate(struct yaffs_dev *dev);
  16464. +int yaffs2_checkpt_save(struct yaffs_dev *dev);
  16465. +int yaffs2_checkpt_restore(struct yaffs_dev *dev);
  16466. +
  16467. +int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size);
  16468. +int yaffs2_scan_backwards(struct yaffs_dev *dev);
  16469. +
  16470. +#endif
  16471. diff -Nur linux-3.18.14.orig/fs/yaffs2/yportenv.h linux-3.18.14/fs/yaffs2/yportenv.h
  16472. --- linux-3.18.14.orig/fs/yaffs2/yportenv.h 1970-01-01 01:00:00.000000000 +0100
  16473. +++ linux-3.18.14/fs/yaffs2/yportenv.h 2015-06-14 21:23:22.000000000 +0200
  16474. @@ -0,0 +1,85 @@
  16475. +/*
  16476. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  16477. + *
  16478. + * Copyright (C) 2002-2011 Aleph One Ltd.
  16479. + * for Toby Churchill Ltd and Brightstar Engineering
  16480. + *
  16481. + * Created by Charles Manning <charles@aleph1.co.uk>
  16482. + *
  16483. + * This program is free software; you can redistribute it and/or modify
  16484. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  16485. + * published by the Free Software Foundation.
  16486. + *
  16487. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  16488. + */
  16489. +
  16490. +#ifndef __YPORTENV_H__
  16491. +#define __YPORTENV_H__
  16492. +
  16493. +/*
  16494. + * Define the MTD version in terms of Linux Kernel versions
  16495. + * This allows yaffs to be used independantly of the kernel
  16496. + * as well as with it.
  16497. + */
  16498. +
  16499. +#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
  16500. +
  16501. +#ifdef YAFFS_OUT_OF_TREE
  16502. +#include "moduleconfig.h"
  16503. +#endif
  16504. +
  16505. +#include <linux/version.h>
  16506. +#define MTD_VERSION_CODE LINUX_VERSION_CODE
  16507. +
  16508. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  16509. +#include <linux/config.h>
  16510. +#endif
  16511. +#include <linux/version.h>
  16512. +#include <linux/kernel.h>
  16513. +#include <linux/mm.h>
  16514. +#include <linux/sched.h>
  16515. +#include <linux/string.h>
  16516. +#include <linux/slab.h>
  16517. +#include <linux/vmalloc.h>
  16518. +#include <linux/xattr.h>
  16519. +#include <linux/list.h>
  16520. +#include <linux/types.h>
  16521. +#include <linux/fs.h>
  16522. +#include <linux/stat.h>
  16523. +#include <linux/sort.h>
  16524. +#include <linux/bitops.h>
  16525. +
  16526. +/* These type wrappings are used to support Unicode names in WinCE. */
  16527. +#define YCHAR char
  16528. +#define YUCHAR unsigned char
  16529. +#define _Y(x) x
  16530. +
  16531. +#define YAFFS_LOSTNFOUND_NAME "lost+found"
  16532. +#define YAFFS_LOSTNFOUND_PREFIX "obj"
  16533. +
  16534. +
  16535. +#define YAFFS_ROOT_MODE 0755
  16536. +#define YAFFS_LOSTNFOUND_MODE 0700
  16537. +
  16538. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  16539. +#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
  16540. +#define Y_TIME_CONVERT(x) (x).tv_sec
  16541. +#else
  16542. +#define Y_CURRENT_TIME CURRENT_TIME
  16543. +#define Y_TIME_CONVERT(x) (x)
  16544. +#endif
  16545. +
  16546. +#define compile_time_assertion(assertion) \
  16547. + ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; })
  16548. +
  16549. +
  16550. +#define yaffs_printf(msk, fmt, ...) \
  16551. + printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__)
  16552. +
  16553. +#define yaffs_trace(msk, fmt, ...) do { \
  16554. + if (yaffs_trace_mask & (msk)) \
  16555. + printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__); \
  16556. +} while (0)
  16557. +
  16558. +
  16559. +#endif