yaffs2.patch 529 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438
  1. diff -Nur linux-3.14.4.orig/fs/Kconfig linux-3.14.4/fs/Kconfig
  2. --- linux-3.14.4.orig/fs/Kconfig 2014-05-13 13:33:14.000000000 +0200
  3. +++ linux-3.14.4/fs/Kconfig 2014-05-14 12:41:23.844791998 +0200
  4. @@ -189,6 +189,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.14.4.orig/fs/Kconfig.orig linux-3.14.4/fs/Kconfig.orig
  13. --- linux-3.14.4.orig/fs/Kconfig.orig 1970-01-01 01:00:00.000000000 +0100
  14. +++ linux-3.14.4/fs/Kconfig.orig 2014-05-13 13:33:14.000000000 +0200
  15. @@ -0,0 +1,267 @@
  16. +#
  17. +# File system configuration
  18. +#
  19. +
  20. +menu "File systems"
  21. +
  22. +# Use unaligned word dcache accesses
  23. +config DCACHE_WORD_ACCESS
  24. + bool
  25. +
  26. +if BLOCK
  27. +
  28. +source "fs/ext2/Kconfig"
  29. +source "fs/ext3/Kconfig"
  30. +source "fs/ext4/Kconfig"
  31. +
  32. +config FS_XIP
  33. +# execute in place
  34. + bool
  35. + depends on EXT2_FS_XIP
  36. + default y
  37. +
  38. +source "fs/jbd/Kconfig"
  39. +source "fs/jbd2/Kconfig"
  40. +
  41. +config FS_MBCACHE
  42. +# Meta block cache for Extended Attributes (ext2/ext3/ext4)
  43. + tristate
  44. + default y if EXT2_FS=y && EXT2_FS_XATTR
  45. + default y if EXT3_FS=y && EXT3_FS_XATTR
  46. + default y if EXT4_FS=y
  47. + default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS
  48. +
  49. +source "fs/reiserfs/Kconfig"
  50. +source "fs/jfs/Kconfig"
  51. +
  52. +source "fs/xfs/Kconfig"
  53. +source "fs/gfs2/Kconfig"
  54. +source "fs/ocfs2/Kconfig"
  55. +source "fs/btrfs/Kconfig"
  56. +source "fs/nilfs2/Kconfig"
  57. +
  58. +endif # BLOCK
  59. +
  60. +# Posix ACL utility routines
  61. +#
  62. +# Note: Posix ACLs can be implemented without these helpers. Never use
  63. +# this symbol for ifdefs in core code.
  64. +#
  65. +config FS_POSIX_ACL
  66. + def_bool n
  67. +
  68. +config EXPORTFS
  69. + tristate
  70. +
  71. +config FILE_LOCKING
  72. + bool "Enable POSIX file locking API" if EXPERT
  73. + default y
  74. + help
  75. + This option enables standard file locking support, required
  76. + for filesystems like NFS and for the flock() system
  77. + call. Disabling this option saves about 11k.
  78. +
  79. +source "fs/notify/Kconfig"
  80. +
  81. +source "fs/quota/Kconfig"
  82. +
  83. +source "fs/autofs4/Kconfig"
  84. +source "fs/fuse/Kconfig"
  85. +
  86. +menu "Caches"
  87. +
  88. +source "fs/fscache/Kconfig"
  89. +source "fs/cachefiles/Kconfig"
  90. +
  91. +endmenu
  92. +
  93. +if BLOCK
  94. +menu "CD-ROM/DVD Filesystems"
  95. +
  96. +source "fs/isofs/Kconfig"
  97. +source "fs/udf/Kconfig"
  98. +
  99. +endmenu
  100. +endif # BLOCK
  101. +
  102. +if BLOCK
  103. +menu "DOS/FAT/NT Filesystems"
  104. +
  105. +source "fs/fat/Kconfig"
  106. +source "fs/ntfs/Kconfig"
  107. +
  108. +endmenu
  109. +endif # BLOCK
  110. +
  111. +menu "Pseudo filesystems"
  112. +
  113. +source "fs/proc/Kconfig"
  114. +source "fs/sysfs/Kconfig"
  115. +
  116. +config TMPFS
  117. + bool "Tmpfs virtual memory file system support (former shm fs)"
  118. + depends on SHMEM
  119. + help
  120. + Tmpfs is a file system which keeps all files in virtual memory.
  121. +
  122. + Everything in tmpfs is temporary in the sense that no files will be
  123. + created on your hard drive. The files live in memory and swap
  124. + space. If you unmount a tmpfs instance, everything stored therein is
  125. + lost.
  126. +
  127. + See <file:Documentation/filesystems/tmpfs.txt> for details.
  128. +
  129. +config TMPFS_POSIX_ACL
  130. + bool "Tmpfs POSIX Access Control Lists"
  131. + depends on TMPFS
  132. + select TMPFS_XATTR
  133. + select FS_POSIX_ACL
  134. + help
  135. + POSIX Access Control Lists (ACLs) support additional access rights
  136. + for users and groups beyond the standard owner/group/world scheme,
  137. + and this option selects support for ACLs specifically for tmpfs
  138. + filesystems.
  139. +
  140. + If you've selected TMPFS, it's possible that you'll also need
  141. + this option as there are a number of Linux distros that require
  142. + POSIX ACL support under /dev for certain features to work properly.
  143. + For example, some distros need this feature for ALSA-related /dev
  144. + files for sound to work properly. In short, if you're not sure,
  145. + say Y.
  146. +
  147. + To learn more about Access Control Lists, visit the POSIX ACLs for
  148. + Linux website <http://acl.bestbits.at/>.
  149. +
  150. +config TMPFS_XATTR
  151. + bool "Tmpfs extended attributes"
  152. + depends on TMPFS
  153. + default n
  154. + help
  155. + Extended attributes are name:value pairs associated with inodes by
  156. + the kernel or by users (see the attr(5) manual page, or visit
  157. + <http://acl.bestbits.at/> for details).
  158. +
  159. + Currently this enables support for the trusted.* and
  160. + security.* namespaces.
  161. +
  162. + You need this for POSIX ACL support on tmpfs.
  163. +
  164. + If unsure, say N.
  165. +
  166. +config HUGETLBFS
  167. + bool "HugeTLB file system support"
  168. + depends on X86 || IA64 || SPARC64 || (S390 && 64BIT) || \
  169. + SYS_SUPPORTS_HUGETLBFS || BROKEN
  170. + help
  171. + hugetlbfs is a filesystem backing for HugeTLB pages, based on
  172. + ramfs. For architectures that support it, say Y here and read
  173. + <file:Documentation/vm/hugetlbpage.txt> for details.
  174. +
  175. + If unsure, say N.
  176. +
  177. +config HUGETLB_PAGE
  178. + def_bool HUGETLBFS
  179. +
  180. +source "fs/configfs/Kconfig"
  181. +
  182. +endmenu
  183. +
  184. +menuconfig MISC_FILESYSTEMS
  185. + bool "Miscellaneous filesystems"
  186. + default y
  187. + ---help---
  188. + Say Y here to get to see options for various miscellaneous
  189. + filesystems, such as filesystems that came from other
  190. + operating systems.
  191. +
  192. + This option alone does not add any kernel code.
  193. +
  194. + If you say N, all options in this submenu will be skipped and
  195. + disabled; if unsure, say Y here.
  196. +
  197. +if MISC_FILESYSTEMS
  198. +
  199. +source "fs/adfs/Kconfig"
  200. +source "fs/affs/Kconfig"
  201. +source "fs/ecryptfs/Kconfig"
  202. +source "fs/hfs/Kconfig"
  203. +source "fs/hfsplus/Kconfig"
  204. +source "fs/befs/Kconfig"
  205. +source "fs/bfs/Kconfig"
  206. +source "fs/efs/Kconfig"
  207. +source "fs/jffs2/Kconfig"
  208. +# UBIFS File system configuration
  209. +source "fs/ubifs/Kconfig"
  210. +source "fs/logfs/Kconfig"
  211. +source "fs/cramfs/Kconfig"
  212. +source "fs/squashfs/Kconfig"
  213. +source "fs/freevxfs/Kconfig"
  214. +source "fs/minix/Kconfig"
  215. +source "fs/omfs/Kconfig"
  216. +source "fs/hpfs/Kconfig"
  217. +source "fs/qnx4/Kconfig"
  218. +source "fs/qnx6/Kconfig"
  219. +source "fs/romfs/Kconfig"
  220. +source "fs/pstore/Kconfig"
  221. +source "fs/sysv/Kconfig"
  222. +source "fs/ufs/Kconfig"
  223. +source "fs/exofs/Kconfig"
  224. +source "fs/f2fs/Kconfig"
  225. +source "fs/efivarfs/Kconfig"
  226. +
  227. +endif # MISC_FILESYSTEMS
  228. +
  229. +source "fs/exofs/Kconfig.ore"
  230. +
  231. +menuconfig NETWORK_FILESYSTEMS
  232. + bool "Network File Systems"
  233. + default y
  234. + depends on NET
  235. + ---help---
  236. + Say Y here to get to see options for network filesystems and
  237. + filesystem-related networking code, such as NFS daemon and
  238. + RPCSEC security modules.
  239. +
  240. + This option alone does not add any kernel code.
  241. +
  242. + If you say N, all options in this submenu will be skipped and
  243. + disabled; if unsure, say Y here.
  244. +
  245. +if NETWORK_FILESYSTEMS
  246. +
  247. +source "fs/nfs/Kconfig"
  248. +source "fs/nfsd/Kconfig"
  249. +
  250. +config LOCKD
  251. + tristate
  252. + depends on FILE_LOCKING
  253. +
  254. +config LOCKD_V4
  255. + bool
  256. + depends on NFSD_V3 || NFS_V3
  257. + depends on FILE_LOCKING
  258. + default y
  259. +
  260. +config NFS_ACL_SUPPORT
  261. + tristate
  262. + select FS_POSIX_ACL
  263. +
  264. +config NFS_COMMON
  265. + bool
  266. + depends on NFSD || NFS_FS
  267. + default y
  268. +
  269. +source "net/sunrpc/Kconfig"
  270. +source "fs/ceph/Kconfig"
  271. +source "fs/cifs/Kconfig"
  272. +source "fs/ncpfs/Kconfig"
  273. +source "fs/coda/Kconfig"
  274. +source "fs/afs/Kconfig"
  275. +source "fs/9p/Kconfig"
  276. +
  277. +endif # NETWORK_FILESYSTEMS
  278. +
  279. +source "fs/nls/Kconfig"
  280. +source "fs/dlm/Kconfig"
  281. +
  282. +endmenu
  283. diff -Nur linux-3.14.4.orig/fs/Makefile linux-3.14.4/fs/Makefile
  284. --- linux-3.14.4.orig/fs/Makefile 2014-05-13 13:33:14.000000000 +0200
  285. +++ linux-3.14.4/fs/Makefile 2014-05-14 12:41:23.868792075 +0200
  286. @@ -125,3 +125,4 @@
  287. obj-$(CONFIG_CEPH_FS) += ceph/
  288. obj-$(CONFIG_PSTORE) += pstore/
  289. obj-$(CONFIG_EFIVAR_FS) += efivarfs/
  290. +obj-$(CONFIG_YAFFS_FS) += yaffs2/
  291. diff -Nur linux-3.14.4.orig/fs/Makefile.orig linux-3.14.4/fs/Makefile.orig
  292. --- linux-3.14.4.orig/fs/Makefile.orig 1970-01-01 01:00:00.000000000 +0100
  293. +++ linux-3.14.4/fs/Makefile.orig 2014-05-13 13:33:14.000000000 +0200
  294. @@ -0,0 +1,127 @@
  295. +#
  296. +# Makefile for the Linux filesystems.
  297. +#
  298. +# 14 Sep 2000, Christoph Hellwig <hch@infradead.org>
  299. +# Rewritten to use lists instead of if-statements.
  300. +#
  301. +
  302. +obj-y := open.o read_write.o file_table.o super.o \
  303. + char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
  304. + ioctl.o readdir.o select.o dcache.o inode.o \
  305. + attr.o bad_inode.o file.o filesystems.o namespace.o \
  306. + seq_file.o xattr.o libfs.o fs-writeback.o \
  307. + pnode.o splice.o sync.o utimes.o \
  308. + stack.o fs_struct.o statfs.o
  309. +
  310. +ifeq ($(CONFIG_BLOCK),y)
  311. +obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
  312. +else
  313. +obj-y += no-block.o
  314. +endif
  315. +
  316. +obj-$(CONFIG_PROC_FS) += proc_namespace.o
  317. +
  318. +obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o
  319. +obj-y += notify/
  320. +obj-$(CONFIG_EPOLL) += eventpoll.o
  321. +obj-$(CONFIG_ANON_INODES) += anon_inodes.o
  322. +obj-$(CONFIG_SIGNALFD) += signalfd.o
  323. +obj-$(CONFIG_TIMERFD) += timerfd.o
  324. +obj-$(CONFIG_EVENTFD) += eventfd.o
  325. +obj-$(CONFIG_AIO) += aio.o
  326. +obj-$(CONFIG_FILE_LOCKING) += locks.o
  327. +obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
  328. +obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
  329. +obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
  330. +obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o
  331. +obj-$(CONFIG_BINFMT_SCRIPT) += binfmt_script.o
  332. +obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
  333. +obj-$(CONFIG_COMPAT_BINFMT_ELF) += compat_binfmt_elf.o
  334. +obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o
  335. +obj-$(CONFIG_BINFMT_SOM) += binfmt_som.o
  336. +obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o
  337. +
  338. +obj-$(CONFIG_FS_MBCACHE) += mbcache.o
  339. +obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
  340. +obj-$(CONFIG_NFS_COMMON) += nfs_common/
  341. +obj-$(CONFIG_COREDUMP) += coredump.o
  342. +obj-$(CONFIG_SYSCTL) += drop_caches.o
  343. +
  344. +obj-$(CONFIG_FHANDLE) += fhandle.o
  345. +
  346. +obj-y += quota/
  347. +
  348. +obj-$(CONFIG_PROC_FS) += proc/
  349. +obj-$(CONFIG_SYSFS) += sysfs/ kernfs/
  350. +obj-$(CONFIG_CONFIGFS_FS) += configfs/
  351. +obj-y += devpts/
  352. +
  353. +obj-$(CONFIG_PROFILING) += dcookies.o
  354. +obj-$(CONFIG_DLM) += dlm/
  355. +
  356. +# Do not add any filesystems before this line
  357. +obj-$(CONFIG_FSCACHE) += fscache/
  358. +obj-$(CONFIG_REISERFS_FS) += reiserfs/
  359. +obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3
  360. +obj-$(CONFIG_EXT2_FS) += ext2/
  361. +# We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2
  362. +# unless explicitly requested by rootfstype
  363. +obj-$(CONFIG_EXT4_FS) += ext4/
  364. +obj-$(CONFIG_JBD) += jbd/
  365. +obj-$(CONFIG_JBD2) += jbd2/
  366. +obj-$(CONFIG_CRAMFS) += cramfs/
  367. +obj-$(CONFIG_SQUASHFS) += squashfs/
  368. +obj-y += ramfs/
  369. +obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
  370. +obj-$(CONFIG_CODA_FS) += coda/
  371. +obj-$(CONFIG_MINIX_FS) += minix/
  372. +obj-$(CONFIG_FAT_FS) += fat/
  373. +obj-$(CONFIG_BFS_FS) += bfs/
  374. +obj-$(CONFIG_ISO9660_FS) += isofs/
  375. +obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
  376. +obj-$(CONFIG_HFS_FS) += hfs/
  377. +obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
  378. +obj-$(CONFIG_VXFS_FS) += freevxfs/
  379. +obj-$(CONFIG_NFS_FS) += nfs/
  380. +obj-$(CONFIG_EXPORTFS) += exportfs/
  381. +obj-$(CONFIG_NFSD) += nfsd/
  382. +obj-$(CONFIG_LOCKD) += lockd/
  383. +obj-$(CONFIG_NLS) += nls/
  384. +obj-$(CONFIG_SYSV_FS) += sysv/
  385. +obj-$(CONFIG_CIFS) += cifs/
  386. +obj-$(CONFIG_NCP_FS) += ncpfs/
  387. +obj-$(CONFIG_HPFS_FS) += hpfs/
  388. +obj-$(CONFIG_NTFS_FS) += ntfs/
  389. +obj-$(CONFIG_UFS_FS) += ufs/
  390. +obj-$(CONFIG_EFS_FS) += efs/
  391. +obj-$(CONFIG_JFFS2_FS) += jffs2/
  392. +obj-$(CONFIG_LOGFS) += logfs/
  393. +obj-$(CONFIG_UBIFS_FS) += ubifs/
  394. +obj-$(CONFIG_AFFS_FS) += affs/
  395. +obj-$(CONFIG_ROMFS_FS) += romfs/
  396. +obj-$(CONFIG_QNX4FS_FS) += qnx4/
  397. +obj-$(CONFIG_QNX6FS_FS) += qnx6/
  398. +obj-$(CONFIG_AUTOFS4_FS) += autofs4/
  399. +obj-$(CONFIG_ADFS_FS) += adfs/
  400. +obj-$(CONFIG_FUSE_FS) += fuse/
  401. +obj-$(CONFIG_UDF_FS) += udf/
  402. +obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
  403. +obj-$(CONFIG_OMFS_FS) += omfs/
  404. +obj-$(CONFIG_JFS_FS) += jfs/
  405. +obj-$(CONFIG_XFS_FS) += xfs/
  406. +obj-$(CONFIG_9P_FS) += 9p/
  407. +obj-$(CONFIG_AFS_FS) += afs/
  408. +obj-$(CONFIG_NILFS2_FS) += nilfs2/
  409. +obj-$(CONFIG_BEFS_FS) += befs/
  410. +obj-$(CONFIG_HOSTFS) += hostfs/
  411. +obj-$(CONFIG_HPPFS) += hppfs/
  412. +obj-$(CONFIG_CACHEFILES) += cachefiles/
  413. +obj-$(CONFIG_DEBUG_FS) += debugfs/
  414. +obj-$(CONFIG_OCFS2_FS) += ocfs2/
  415. +obj-$(CONFIG_BTRFS_FS) += btrfs/
  416. +obj-$(CONFIG_GFS2_FS) += gfs2/
  417. +obj-$(CONFIG_F2FS_FS) += f2fs/
  418. +obj-y += exofs/ # Multiple modules
  419. +obj-$(CONFIG_CEPH_FS) += ceph/
  420. +obj-$(CONFIG_PSTORE) += pstore/
  421. +obj-$(CONFIG_EFIVAR_FS) += efivarfs/
  422. diff -Nur linux-3.14.4.orig/fs/yaffs2/Kconfig linux-3.14.4/fs/yaffs2/Kconfig
  423. --- linux-3.14.4.orig/fs/yaffs2/Kconfig 1970-01-01 01:00:00.000000000 +0100
  424. +++ linux-3.14.4/fs/yaffs2/Kconfig 2014-05-14 12:41:23.868792075 +0200
  425. @@ -0,0 +1,171 @@
  426. +#
  427. +# yaffs file system configurations
  428. +#
  429. +
  430. +config YAFFS_FS
  431. + tristate "yaffs2 file system support"
  432. + default n
  433. + depends on MTD_BLOCK
  434. + select YAFFS_YAFFS1
  435. + select YAFFS_YAFFS2
  436. + help
  437. + yaffs2, or Yet Another Flash File System, is a file system
  438. + optimised for NAND Flash chips.
  439. +
  440. + To compile the yaffs2 file system support as a module, choose M
  441. + here: the module will be called yaffs2.
  442. +
  443. + If unsure, say N.
  444. +
  445. + Further information on yaffs2 is available at
  446. + <http://www.aleph1.co.uk/yaffs/>.
  447. +
  448. +config YAFFS_YAFFS1
  449. + bool "512 byte / page devices"
  450. + depends on YAFFS_FS
  451. + default y
  452. + help
  453. + Enable yaffs1 support -- yaffs for 512 byte / page devices
  454. +
  455. + Not needed for 2K-page devices.
  456. +
  457. + If unsure, say Y.
  458. +
  459. +config YAFFS_9BYTE_TAGS
  460. + bool "Use older-style on-NAND data format with pageStatus byte"
  461. + depends on YAFFS_YAFFS1
  462. + default n
  463. + help
  464. +
  465. + Older-style on-NAND data format has a "pageStatus" byte to record
  466. + chunk/page state. This byte is zero when the page is discarded.
  467. + Choose this option if you have existing on-NAND data using this
  468. + format that you need to continue to support. New data written
  469. + also uses the older-style format. Note: Use of this option
  470. + generally requires that MTD's oob layout be adjusted to use the
  471. + older-style format. See notes on tags formats and MTD versions
  472. + in yaffs_mtdif1.c.
  473. +
  474. + If unsure, say N.
  475. +
  476. +config YAFFS_DOES_ECC
  477. + bool "Lets yaffs do its own ECC"
  478. + depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS
  479. + default n
  480. + help
  481. + This enables yaffs to use its own ECC functions instead of using
  482. + the ones from the generic MTD-NAND driver.
  483. +
  484. + If unsure, say N.
  485. +
  486. +config YAFFS_ECC_WRONG_ORDER
  487. + bool "Use the same ecc byte order as Steven Hill's nand_ecc.c"
  488. + depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS
  489. + default n
  490. + help
  491. + This makes yaffs_ecc.c use the same ecc byte order as Steven
  492. + Hill's nand_ecc.c. If not set, then you get the same ecc byte
  493. + order as SmartMedia.
  494. +
  495. + If unsure, say N.
  496. +
  497. +config YAFFS_YAFFS2
  498. + bool "2048 byte (or larger) / page devices"
  499. + depends on YAFFS_FS
  500. + default y
  501. + help
  502. + Enable yaffs2 support -- yaffs for >= 2K bytes per page devices
  503. +
  504. + If unsure, say Y.
  505. +
  506. +config YAFFS_AUTO_YAFFS2
  507. + bool "Autoselect yaffs2 format"
  508. + depends on YAFFS_YAFFS2
  509. + default y
  510. + help
  511. + Without this, you need to explicitely use yaffs2 as the file
  512. + system type. With this, you can say "yaffs" and yaffs or yaffs2
  513. + will be used depending on the device page size (yaffs on
  514. + 512-byte page devices, yaffs2 on 2K page devices).
  515. +
  516. + If unsure, say Y.
  517. +
  518. +config YAFFS_DISABLE_TAGS_ECC
  519. + bool "Disable yaffs from doing ECC on tags by default"
  520. + depends on YAFFS_FS && YAFFS_YAFFS2
  521. + default n
  522. + help
  523. + This defaults yaffs to using its own ECC calculations on tags instead of
  524. + just relying on the MTD.
  525. + This behavior can also be overridden with tags_ecc_on and
  526. + tags_ecc_off mount options.
  527. +
  528. + If unsure, say N.
  529. +
  530. +config YAFFS_ALWAYS_CHECK_CHUNK_ERASED
  531. + bool "Force chunk erase check"
  532. + depends on YAFFS_FS
  533. + default n
  534. + help
  535. + Normally yaffs only checks chunks before writing until an erased
  536. + chunk is found. This helps to detect any partially written
  537. + chunks that might have happened due to power loss.
  538. +
  539. + Enabling this forces on the test that chunks are erased in flash
  540. + before writing to them. This takes more time but is potentially
  541. + a bit more secure.
  542. +
  543. + Suggest setting Y during development and ironing out driver
  544. + issues etc. Suggest setting to N if you want faster writing.
  545. +
  546. + If unsure, say Y.
  547. +
  548. +config YAFFS_EMPTY_LOST_AND_FOUND
  549. + bool "Empty lost and found on boot"
  550. + depends on YAFFS_FS
  551. + default n
  552. + help
  553. + If this is enabled then the contents of lost and found is
  554. + automatically dumped at mount.
  555. +
  556. + If unsure, say N.
  557. +
  558. +config YAFFS_DISABLE_BLOCK_REFRESHING
  559. + bool "Disable yaffs2 block refreshing"
  560. + depends on YAFFS_FS
  561. + default n
  562. + help
  563. + If this is set, then block refreshing is disabled.
  564. + Block refreshing infrequently refreshes the oldest block in
  565. + a yaffs2 file system. This mechanism helps to refresh flash to
  566. + mitigate against data loss. This is particularly useful for MLC.
  567. +
  568. + If unsure, say N.
  569. +
  570. +config YAFFS_DISABLE_BACKGROUND
  571. + bool "Disable yaffs2 background processing"
  572. + depends on YAFFS_FS
  573. + default n
  574. + help
  575. + If this is set, then background processing is disabled.
  576. + Background processing makes many foreground activities faster.
  577. +
  578. + If unsure, say N.
  579. +
  580. +config YAFFS_DISABLE_BAD_BLOCK_MARKING
  581. + bool "Disable yaffs2 bad block marking"
  582. + depends on YAFFS_FS
  583. + default n
  584. + help
  585. + Useful during early flash bring up to prevent problems causing
  586. + lots of bad block marking.
  587. +
  588. + If unsure, say N.
  589. +
  590. +config YAFFS_XATTR
  591. + bool "Enable yaffs2 xattr support"
  592. + depends on YAFFS_FS
  593. + default y
  594. + help
  595. + If this is set then yaffs2 will provide xattr support.
  596. + If unsure, say Y.
  597. diff -Nur linux-3.14.4.orig/fs/yaffs2/Makefile linux-3.14.4/fs/yaffs2/Makefile
  598. --- linux-3.14.4.orig/fs/yaffs2/Makefile 1970-01-01 01:00:00.000000000 +0100
  599. +++ linux-3.14.4/fs/yaffs2/Makefile 2014-05-14 12:41:23.868792075 +0200
  600. @@ -0,0 +1,18 @@
  601. +#
  602. +# Makefile for the linux YAFFS filesystem routines.
  603. +#
  604. +
  605. +obj-$(CONFIG_YAFFS_FS) += yaffs.o
  606. +
  607. +yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o
  608. +yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
  609. +yaffs-y += yaffs_tagscompat.o yaffs_tagsmarshall.o
  610. +yaffs-y += yaffs_mtdif.o
  611. +yaffs-y += yaffs_nameval.o yaffs_attribs.o
  612. +yaffs-y += yaffs_allocator.o
  613. +yaffs-y += yaffs_yaffs1.o
  614. +yaffs-y += yaffs_yaffs2.o
  615. +yaffs-y += yaffs_bitmap.o
  616. +yaffs-y += yaffs_summary.o
  617. +yaffs-y += yaffs_verify.o
  618. +
  619. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_allocator.c linux-3.14.4/fs/yaffs2/yaffs_allocator.c
  620. --- linux-3.14.4.orig/fs/yaffs2/yaffs_allocator.c 1970-01-01 01:00:00.000000000 +0100
  621. +++ linux-3.14.4/fs/yaffs2/yaffs_allocator.c 2014-05-14 12:41:23.872792088 +0200
  622. @@ -0,0 +1,357 @@
  623. +/*
  624. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  625. + *
  626. + * Copyright (C) 2002-2011 Aleph One Ltd.
  627. + * for Toby Churchill Ltd and Brightstar Engineering
  628. + *
  629. + * Created by Charles Manning <charles@aleph1.co.uk>
  630. + *
  631. + * This program is free software; you can redistribute it and/or modify
  632. + * it under the terms of the GNU General Public License version 2 as
  633. + * published by the Free Software Foundation.
  634. + */
  635. +
  636. +#include "yaffs_allocator.h"
  637. +#include "yaffs_guts.h"
  638. +#include "yaffs_trace.h"
  639. +#include "yportenv.h"
  640. +
  641. +/*
  642. + * Each entry in yaffs_tnode_list and yaffs_obj_list hold blocks
  643. + * of approx 100 objects that are themn allocated singly.
  644. + * This is basically a simplified slab allocator.
  645. + *
  646. + * We don't use the Linux slab allocator because slab does not allow
  647. + * us to dump all the objects in one hit when we do a umount and tear
  648. + * down all the tnodes and objects. slab requires that we first free
  649. + * the individual objects.
  650. + *
  651. + * Once yaffs has been mainlined I shall try to motivate for a change
  652. + * to slab to provide the extra features we need here.
  653. + */
  654. +
  655. +struct yaffs_tnode_list {
  656. + struct yaffs_tnode_list *next;
  657. + struct yaffs_tnode *tnodes;
  658. +};
  659. +
  660. +struct yaffs_obj_list {
  661. + struct yaffs_obj_list *next;
  662. + struct yaffs_obj *objects;
  663. +};
  664. +
  665. +struct yaffs_allocator {
  666. + int n_tnodes_created;
  667. + struct yaffs_tnode *free_tnodes;
  668. + int n_free_tnodes;
  669. + struct yaffs_tnode_list *alloc_tnode_list;
  670. +
  671. + int n_obj_created;
  672. + struct list_head free_objs;
  673. + int n_free_objects;
  674. +
  675. + struct yaffs_obj_list *allocated_obj_list;
  676. +};
  677. +
  678. +static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
  679. +{
  680. + struct yaffs_allocator *allocator =
  681. + (struct yaffs_allocator *)dev->allocator;
  682. + struct yaffs_tnode_list *tmp;
  683. +
  684. + if (!allocator) {
  685. + BUG();
  686. + return;
  687. + }
  688. +
  689. + while (allocator->alloc_tnode_list) {
  690. + tmp = allocator->alloc_tnode_list->next;
  691. +
  692. + kfree(allocator->alloc_tnode_list->tnodes);
  693. + kfree(allocator->alloc_tnode_list);
  694. + allocator->alloc_tnode_list = tmp;
  695. + }
  696. +
  697. + allocator->free_tnodes = NULL;
  698. + allocator->n_free_tnodes = 0;
  699. + allocator->n_tnodes_created = 0;
  700. +}
  701. +
  702. +static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
  703. +{
  704. + struct yaffs_allocator *allocator = dev->allocator;
  705. +
  706. + if (!allocator) {
  707. + BUG();
  708. + return;
  709. + }
  710. +
  711. + allocator->alloc_tnode_list = NULL;
  712. + allocator->free_tnodes = NULL;
  713. + allocator->n_free_tnodes = 0;
  714. + allocator->n_tnodes_created = 0;
  715. +}
  716. +
  717. +static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
  718. +{
  719. + struct yaffs_allocator *allocator =
  720. + (struct yaffs_allocator *)dev->allocator;
  721. + int i;
  722. + struct yaffs_tnode *new_tnodes;
  723. + u8 *mem;
  724. + struct yaffs_tnode *curr;
  725. + struct yaffs_tnode *next;
  726. + struct yaffs_tnode_list *tnl;
  727. +
  728. + if (!allocator) {
  729. + BUG();
  730. + return YAFFS_FAIL;
  731. + }
  732. +
  733. + if (n_tnodes < 1)
  734. + return YAFFS_OK;
  735. +
  736. + /* make these things */
  737. + new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS);
  738. + mem = (u8 *) new_tnodes;
  739. +
  740. + if (!new_tnodes) {
  741. + yaffs_trace(YAFFS_TRACE_ERROR,
  742. + "yaffs: Could not allocate Tnodes");
  743. + return YAFFS_FAIL;
  744. + }
  745. +
  746. + /* New hookup for wide tnodes */
  747. + for (i = 0; i < n_tnodes - 1; i++) {
  748. + curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size];
  749. + next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size];
  750. + curr->internal[0] = next;
  751. + }
  752. +
  753. + curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size];
  754. + curr->internal[0] = allocator->free_tnodes;
  755. + allocator->free_tnodes = (struct yaffs_tnode *)mem;
  756. +
  757. + allocator->n_free_tnodes += n_tnodes;
  758. + allocator->n_tnodes_created += n_tnodes;
  759. +
  760. + /* Now add this bunch of tnodes to a list for freeing up.
  761. + * NB If we can't add this to the management list it isn't fatal
  762. + * but it just means we can't free this bunch of tnodes later.
  763. + */
  764. + tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS);
  765. + if (!tnl) {
  766. + yaffs_trace(YAFFS_TRACE_ERROR,
  767. + "Could not add tnodes to management list");
  768. + return YAFFS_FAIL;
  769. + } else {
  770. + tnl->tnodes = new_tnodes;
  771. + tnl->next = allocator->alloc_tnode_list;
  772. + allocator->alloc_tnode_list = tnl;
  773. + }
  774. +
  775. + yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added");
  776. +
  777. + return YAFFS_OK;
  778. +}
  779. +
  780. +struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
  781. +{
  782. + struct yaffs_allocator *allocator =
  783. + (struct yaffs_allocator *)dev->allocator;
  784. + struct yaffs_tnode *tn = NULL;
  785. +
  786. + if (!allocator) {
  787. + BUG();
  788. + return NULL;
  789. + }
  790. +
  791. + /* If there are none left make more */
  792. + if (!allocator->free_tnodes)
  793. + yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES);
  794. +
  795. + if (allocator->free_tnodes) {
  796. + tn = allocator->free_tnodes;
  797. + allocator->free_tnodes = allocator->free_tnodes->internal[0];
  798. + allocator->n_free_tnodes--;
  799. + }
  800. +
  801. + return tn;
  802. +}
  803. +
  804. +/* FreeTnode frees up a tnode and puts it back on the free list */
  805. +void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
  806. +{
  807. + struct yaffs_allocator *allocator = dev->allocator;
  808. +
  809. + if (!allocator) {
  810. + BUG();
  811. + return;
  812. + }
  813. +
  814. + if (tn) {
  815. + tn->internal[0] = allocator->free_tnodes;
  816. + allocator->free_tnodes = tn;
  817. + allocator->n_free_tnodes++;
  818. + }
  819. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  820. +}
  821. +
  822. +/*--------------- yaffs_obj alloaction ------------------------
  823. + *
  824. + * Free yaffs_objs are stored in a list using obj->siblings.
  825. + * The blocks of allocated objects are stored in a linked list.
  826. + */
  827. +
  828. +static void yaffs_init_raw_objs(struct yaffs_dev *dev)
  829. +{
  830. + struct yaffs_allocator *allocator = dev->allocator;
  831. +
  832. + if (!allocator) {
  833. + BUG();
  834. + return;
  835. + }
  836. +
  837. + allocator->allocated_obj_list = NULL;
  838. + INIT_LIST_HEAD(&allocator->free_objs);
  839. + allocator->n_free_objects = 0;
  840. +}
  841. +
  842. +static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
  843. +{
  844. + struct yaffs_allocator *allocator = dev->allocator;
  845. + struct yaffs_obj_list *tmp;
  846. +
  847. + if (!allocator) {
  848. + BUG();
  849. + return;
  850. + }
  851. +
  852. + while (allocator->allocated_obj_list) {
  853. + tmp = allocator->allocated_obj_list->next;
  854. + kfree(allocator->allocated_obj_list->objects);
  855. + kfree(allocator->allocated_obj_list);
  856. + allocator->allocated_obj_list = tmp;
  857. + }
  858. +
  859. + INIT_LIST_HEAD(&allocator->free_objs);
  860. + allocator->n_free_objects = 0;
  861. + allocator->n_obj_created = 0;
  862. +}
  863. +
  864. +static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
  865. +{
  866. + struct yaffs_allocator *allocator = dev->allocator;
  867. + int i;
  868. + struct yaffs_obj *new_objs;
  869. + struct yaffs_obj_list *list;
  870. +
  871. + if (!allocator) {
  872. + BUG();
  873. + return YAFFS_FAIL;
  874. + }
  875. +
  876. + if (n_obj < 1)
  877. + return YAFFS_OK;
  878. +
  879. + /* make these things */
  880. + new_objs = kmalloc(n_obj * sizeof(struct yaffs_obj), GFP_NOFS);
  881. + list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS);
  882. +
  883. + if (!new_objs || !list) {
  884. + kfree(new_objs);
  885. + new_objs = NULL;
  886. + kfree(list);
  887. + list = NULL;
  888. + yaffs_trace(YAFFS_TRACE_ALLOCATE,
  889. + "Could not allocate more objects");
  890. + return YAFFS_FAIL;
  891. + }
  892. +
  893. + /* Hook them into the free list */
  894. + for (i = 0; i < n_obj; i++)
  895. + list_add(&new_objs[i].siblings, &allocator->free_objs);
  896. +
  897. + allocator->n_free_objects += n_obj;
  898. + allocator->n_obj_created += n_obj;
  899. +
  900. + /* Now add this bunch of Objects to a list for freeing up. */
  901. +
  902. + list->objects = new_objs;
  903. + list->next = allocator->allocated_obj_list;
  904. + allocator->allocated_obj_list = list;
  905. +
  906. + return YAFFS_OK;
  907. +}
  908. +
  909. +struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
  910. +{
  911. + struct yaffs_obj *obj = NULL;
  912. + struct list_head *lh;
  913. + struct yaffs_allocator *allocator = dev->allocator;
  914. +
  915. + if (!allocator) {
  916. + BUG();
  917. + return obj;
  918. + }
  919. +
  920. + /* If there are none left make more */
  921. + if (list_empty(&allocator->free_objs))
  922. + yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS);
  923. +
  924. + if (!list_empty(&allocator->free_objs)) {
  925. + lh = allocator->free_objs.next;
  926. + obj = list_entry(lh, struct yaffs_obj, siblings);
  927. + list_del_init(lh);
  928. + allocator->n_free_objects--;
  929. + }
  930. +
  931. + return obj;
  932. +}
  933. +
  934. +void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
  935. +{
  936. +
  937. + struct yaffs_allocator *allocator = dev->allocator;
  938. +
  939. + if (!allocator) {
  940. + BUG();
  941. + return;
  942. + }
  943. +
  944. + /* Link into the free list. */
  945. + list_add(&obj->siblings, &allocator->free_objs);
  946. + allocator->n_free_objects++;
  947. +}
  948. +
  949. +void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
  950. +{
  951. +
  952. + if (!dev->allocator) {
  953. + BUG();
  954. + return;
  955. + }
  956. +
  957. + yaffs_deinit_raw_tnodes(dev);
  958. + yaffs_deinit_raw_objs(dev);
  959. + kfree(dev->allocator);
  960. + dev->allocator = NULL;
  961. +}
  962. +
  963. +void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
  964. +{
  965. + struct yaffs_allocator *allocator;
  966. +
  967. + if (dev->allocator) {
  968. + BUG();
  969. + return;
  970. + }
  971. +
  972. + allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS);
  973. + if (allocator) {
  974. + dev->allocator = allocator;
  975. + yaffs_init_raw_tnodes(dev);
  976. + yaffs_init_raw_objs(dev);
  977. + }
  978. +}
  979. +
  980. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_allocator.h linux-3.14.4/fs/yaffs2/yaffs_allocator.h
  981. --- linux-3.14.4.orig/fs/yaffs2/yaffs_allocator.h 1970-01-01 01:00:00.000000000 +0100
  982. +++ linux-3.14.4/fs/yaffs2/yaffs_allocator.h 2014-05-14 12:41:23.872792088 +0200
  983. @@ -0,0 +1,30 @@
  984. +/*
  985. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  986. + *
  987. + * Copyright (C) 2002-2011 Aleph One Ltd.
  988. + * for Toby Churchill Ltd and Brightstar Engineering
  989. + *
  990. + * Created by Charles Manning <charles@aleph1.co.uk>
  991. + *
  992. + * This program is free software; you can redistribute it and/or modify
  993. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  994. + * published by the Free Software Foundation.
  995. + *
  996. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  997. + */
  998. +
  999. +#ifndef __YAFFS_ALLOCATOR_H__
  1000. +#define __YAFFS_ALLOCATOR_H__
  1001. +
  1002. +#include "yaffs_guts.h"
  1003. +
  1004. +void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev);
  1005. +void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev);
  1006. +
  1007. +struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev);
  1008. +void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn);
  1009. +
  1010. +struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev);
  1011. +void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj);
  1012. +
  1013. +#endif
  1014. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_attribs.c linux-3.14.4/fs/yaffs2/yaffs_attribs.c
  1015. --- linux-3.14.4.orig/fs/yaffs2/yaffs_attribs.c 1970-01-01 01:00:00.000000000 +0100
  1016. +++ linux-3.14.4/fs/yaffs2/yaffs_attribs.c 2014-05-14 12:41:23.872792088 +0200
  1017. @@ -0,0 +1,166 @@
  1018. +/*
  1019. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  1020. + *
  1021. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1022. + * for Toby Churchill Ltd and Brightstar Engineering
  1023. + *
  1024. + * Created by Charles Manning <charles@aleph1.co.uk>
  1025. + *
  1026. + * This program is free software; you can redistribute it and/or modify
  1027. + * it under the terms of the GNU General Public License version 2 as
  1028. + * published by the Free Software Foundation.
  1029. + */
  1030. +
  1031. +#include "yaffs_guts.h"
  1032. +#include "yaffs_attribs.h"
  1033. +
  1034. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  1035. +static inline uid_t ia_uid_read(const struct iattr *iattr)
  1036. +{
  1037. + return from_kuid(&init_user_ns, iattr->ia_uid);
  1038. +}
  1039. +
  1040. +static inline gid_t ia_gid_read(const struct iattr *iattr)
  1041. +{
  1042. + return from_kgid(&init_user_ns, iattr->ia_gid);
  1043. +}
  1044. +
  1045. +static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
  1046. +{
  1047. + iattr->ia_uid = make_kuid(&init_user_ns, uid);
  1048. +}
  1049. +
  1050. +static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
  1051. +{
  1052. + iattr->ia_gid = make_kgid(&init_user_ns, gid);
  1053. +}
  1054. +#else
  1055. +static inline uid_t ia_uid_read(const struct iattr *iattr)
  1056. +{
  1057. + return iattr->ia_uid;
  1058. +}
  1059. +
  1060. +static inline gid_t ia_gid_read(const struct iattr *inode)
  1061. +{
  1062. + return iattr->ia_gid;
  1063. +}
  1064. +
  1065. +static inline void ia_uid_write(struct iattr *iattr, uid_t uid)
  1066. +{
  1067. + iattr->ia_uid = uid;
  1068. +}
  1069. +
  1070. +static inline void ia_gid_write(struct iattr *iattr, gid_t gid)
  1071. +{
  1072. + iattr->ia_gid = gid;
  1073. +}
  1074. +#endif
  1075. +
  1076. +void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
  1077. +{
  1078. + obj->yst_uid = oh->yst_uid;
  1079. + obj->yst_gid = oh->yst_gid;
  1080. + obj->yst_atime = oh->yst_atime;
  1081. + obj->yst_mtime = oh->yst_mtime;
  1082. + obj->yst_ctime = oh->yst_ctime;
  1083. + obj->yst_rdev = oh->yst_rdev;
  1084. +}
  1085. +
  1086. +void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj)
  1087. +{
  1088. + oh->yst_uid = obj->yst_uid;
  1089. + oh->yst_gid = obj->yst_gid;
  1090. + oh->yst_atime = obj->yst_atime;
  1091. + oh->yst_mtime = obj->yst_mtime;
  1092. + oh->yst_ctime = obj->yst_ctime;
  1093. + oh->yst_rdev = obj->yst_rdev;
  1094. +
  1095. +}
  1096. +
  1097. +void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
  1098. +{
  1099. + obj->yst_mtime = Y_CURRENT_TIME;
  1100. + if (do_a)
  1101. + obj->yst_atime = obj->yst_mtime;
  1102. + if (do_c)
  1103. + obj->yst_ctime = obj->yst_mtime;
  1104. +}
  1105. +
  1106. +void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev)
  1107. +{
  1108. + yaffs_load_current_time(obj, 1, 1);
  1109. + obj->yst_rdev = rdev;
  1110. + obj->yst_uid = uid;
  1111. + obj->yst_gid = gid;
  1112. +}
  1113. +
  1114. +static loff_t yaffs_get_file_size(struct yaffs_obj *obj)
  1115. +{
  1116. + YCHAR *alias = NULL;
  1117. + obj = yaffs_get_equivalent_obj(obj);
  1118. +
  1119. + switch (obj->variant_type) {
  1120. + case YAFFS_OBJECT_TYPE_FILE:
  1121. + return obj->variant.file_variant.file_size;
  1122. + case YAFFS_OBJECT_TYPE_SYMLINK:
  1123. + alias = obj->variant.symlink_variant.alias;
  1124. + if (!alias)
  1125. + return 0;
  1126. + return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH);
  1127. + default:
  1128. + return 0;
  1129. + }
  1130. +}
  1131. +
  1132. +int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
  1133. +{
  1134. + unsigned int valid = attr->ia_valid;
  1135. +
  1136. + if (valid & ATTR_MODE)
  1137. + obj->yst_mode = attr->ia_mode;
  1138. + if (valid & ATTR_UID)
  1139. + obj->yst_uid = ia_uid_read(attr);
  1140. + if (valid & ATTR_GID)
  1141. + obj->yst_gid = ia_gid_read(attr);
  1142. +
  1143. + if (valid & ATTR_ATIME)
  1144. + obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
  1145. + if (valid & ATTR_CTIME)
  1146. + obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
  1147. + if (valid & ATTR_MTIME)
  1148. + obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
  1149. +
  1150. + if (valid & ATTR_SIZE)
  1151. + yaffs_resize_file(obj, attr->ia_size);
  1152. +
  1153. + yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
  1154. +
  1155. + return YAFFS_OK;
  1156. +
  1157. +}
  1158. +
  1159. +int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
  1160. +{
  1161. + unsigned int valid = 0;
  1162. +
  1163. + attr->ia_mode = obj->yst_mode;
  1164. + valid |= ATTR_MODE;
  1165. + ia_uid_write(attr, obj->yst_uid);
  1166. + valid |= ATTR_UID;
  1167. + ia_gid_write(attr, obj->yst_gid);
  1168. + valid |= ATTR_GID;
  1169. +
  1170. + Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
  1171. + valid |= ATTR_ATIME;
  1172. + Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
  1173. + valid |= ATTR_CTIME;
  1174. + Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
  1175. + valid |= ATTR_MTIME;
  1176. +
  1177. + attr->ia_size = yaffs_get_file_size(obj);
  1178. + valid |= ATTR_SIZE;
  1179. +
  1180. + attr->ia_valid = valid;
  1181. +
  1182. + return YAFFS_OK;
  1183. +}
  1184. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_attribs.h linux-3.14.4/fs/yaffs2/yaffs_attribs.h
  1185. --- linux-3.14.4.orig/fs/yaffs2/yaffs_attribs.h 1970-01-01 01:00:00.000000000 +0100
  1186. +++ linux-3.14.4/fs/yaffs2/yaffs_attribs.h 2014-05-14 12:41:23.872792088 +0200
  1187. @@ -0,0 +1,28 @@
  1188. +/*
  1189. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  1190. + *
  1191. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1192. + * for Toby Churchill Ltd and Brightstar Engineering
  1193. + *
  1194. + * Created by Charles Manning <charles@aleph1.co.uk>
  1195. + *
  1196. + * This program is free software; you can redistribute it and/or modify
  1197. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  1198. + * published by the Free Software Foundation.
  1199. + *
  1200. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  1201. + */
  1202. +
  1203. +#ifndef __YAFFS_ATTRIBS_H__
  1204. +#define __YAFFS_ATTRIBS_H__
  1205. +
  1206. +#include "yaffs_guts.h"
  1207. +
  1208. +void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
  1209. +void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj);
  1210. +void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev);
  1211. +void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c);
  1212. +int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr);
  1213. +int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr);
  1214. +
  1215. +#endif
  1216. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_bitmap.c linux-3.14.4/fs/yaffs2/yaffs_bitmap.c
  1217. --- linux-3.14.4.orig/fs/yaffs2/yaffs_bitmap.c 1970-01-01 01:00:00.000000000 +0100
  1218. +++ linux-3.14.4/fs/yaffs2/yaffs_bitmap.c 2014-05-14 12:41:23.872792088 +0200
  1219. @@ -0,0 +1,97 @@
  1220. +/*
  1221. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  1222. + *
  1223. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1224. + * for Toby Churchill Ltd and Brightstar Engineering
  1225. + *
  1226. + * Created by Charles Manning <charles@aleph1.co.uk>
  1227. + *
  1228. + * This program is free software; you can redistribute it and/or modify
  1229. + * it under the terms of the GNU General Public License version 2 as
  1230. + * published by the Free Software Foundation.
  1231. + */
  1232. +
  1233. +#include "yaffs_bitmap.h"
  1234. +#include "yaffs_trace.h"
  1235. +/*
  1236. + * Chunk bitmap manipulations
  1237. + */
  1238. +
  1239. +static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk)
  1240. +{
  1241. + if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
  1242. + yaffs_trace(YAFFS_TRACE_ERROR,
  1243. + "BlockBits block %d is not valid",
  1244. + blk);
  1245. + BUG();
  1246. + }
  1247. + return dev->chunk_bits +
  1248. + (dev->chunk_bit_stride * (blk - dev->internal_start_block));
  1249. +}
  1250. +
  1251. +void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk)
  1252. +{
  1253. + if (blk < dev->internal_start_block || blk > dev->internal_end_block ||
  1254. + chunk < 0 || chunk >= dev->param.chunks_per_block) {
  1255. + yaffs_trace(YAFFS_TRACE_ERROR,
  1256. + "Chunk Id (%d:%d) invalid",
  1257. + blk, chunk);
  1258. + BUG();
  1259. + }
  1260. +}
  1261. +
  1262. +void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk)
  1263. +{
  1264. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  1265. +
  1266. + memset(blk_bits, 0, dev->chunk_bit_stride);
  1267. +}
  1268. +
  1269. +void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
  1270. +{
  1271. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  1272. +
  1273. + yaffs_verify_chunk_bit_id(dev, blk, chunk);
  1274. + blk_bits[chunk / 8] &= ~(1 << (chunk & 7));
  1275. +}
  1276. +
  1277. +void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
  1278. +{
  1279. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  1280. +
  1281. + yaffs_verify_chunk_bit_id(dev, blk, chunk);
  1282. + blk_bits[chunk / 8] |= (1 << (chunk & 7));
  1283. +}
  1284. +
  1285. +int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
  1286. +{
  1287. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  1288. +
  1289. + yaffs_verify_chunk_bit_id(dev, blk, chunk);
  1290. + return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
  1291. +}
  1292. +
  1293. +int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk)
  1294. +{
  1295. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  1296. + int i;
  1297. +
  1298. + for (i = 0; i < dev->chunk_bit_stride; i++) {
  1299. + if (*blk_bits)
  1300. + return 1;
  1301. + blk_bits++;
  1302. + }
  1303. + return 0;
  1304. +}
  1305. +
  1306. +int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk)
  1307. +{
  1308. + u8 *blk_bits = yaffs_block_bits(dev, blk);
  1309. + int i;
  1310. + int n = 0;
  1311. +
  1312. + for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++)
  1313. + n += hweight8(*blk_bits);
  1314. +
  1315. + return n;
  1316. +}
  1317. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_bitmap.h linux-3.14.4/fs/yaffs2/yaffs_bitmap.h
  1318. --- linux-3.14.4.orig/fs/yaffs2/yaffs_bitmap.h 1970-01-01 01:00:00.000000000 +0100
  1319. +++ linux-3.14.4/fs/yaffs2/yaffs_bitmap.h 2014-05-14 12:41:23.972792410 +0200
  1320. @@ -0,0 +1,33 @@
  1321. +/*
  1322. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  1323. + *
  1324. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1325. + * for Toby Churchill Ltd and Brightstar Engineering
  1326. + *
  1327. + * Created by Charles Manning <charles@aleph1.co.uk>
  1328. + *
  1329. + * This program is free software; you can redistribute it and/or modify
  1330. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  1331. + * published by the Free Software Foundation.
  1332. + *
  1333. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  1334. + */
  1335. +
  1336. +/*
  1337. + * Chunk bitmap manipulations
  1338. + */
  1339. +
  1340. +#ifndef __YAFFS_BITMAP_H__
  1341. +#define __YAFFS_BITMAP_H__
  1342. +
  1343. +#include "yaffs_guts.h"
  1344. +
  1345. +void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk);
  1346. +void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk);
  1347. +void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
  1348. +void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
  1349. +int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
  1350. +int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk);
  1351. +int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk);
  1352. +
  1353. +#endif
  1354. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_checkptrw.c linux-3.14.4/fs/yaffs2/yaffs_checkptrw.c
  1355. --- linux-3.14.4.orig/fs/yaffs2/yaffs_checkptrw.c 1970-01-01 01:00:00.000000000 +0100
  1356. +++ linux-3.14.4/fs/yaffs2/yaffs_checkptrw.c 2014-05-14 12:41:23.976792423 +0200
  1357. @@ -0,0 +1,474 @@
  1358. +/*
  1359. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  1360. + *
  1361. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1362. + * for Toby Churchill Ltd and Brightstar Engineering
  1363. + *
  1364. + * Created by Charles Manning <charles@aleph1.co.uk>
  1365. + *
  1366. + * This program is free software; you can redistribute it and/or modify
  1367. + * it under the terms of the GNU General Public License version 2 as
  1368. + * published by the Free Software Foundation.
  1369. + */
  1370. +
  1371. +#include "yaffs_checkptrw.h"
  1372. +#include "yaffs_getblockinfo.h"
  1373. +
  1374. +struct yaffs_checkpt_chunk_hdr {
  1375. + int version;
  1376. + int seq;
  1377. + u32 sum;
  1378. + u32 xor;
  1379. +} ;
  1380. +
  1381. +
  1382. +static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
  1383. +{
  1384. + return chunk - dev->chunk_offset;
  1385. +}
  1386. +
  1387. +static int apply_block_offset(struct yaffs_dev *dev, int block)
  1388. +{
  1389. + return block - dev->block_offset;
  1390. +}
  1391. +
  1392. +static void yaffs2_checkpt_init_chunk_hdr(struct yaffs_dev *dev)
  1393. +{
  1394. + struct yaffs_checkpt_chunk_hdr hdr;
  1395. +
  1396. + hdr.version = YAFFS_CHECKPOINT_VERSION;
  1397. + hdr.seq = dev->checkpt_page_seq;
  1398. + hdr.sum = dev->checkpt_sum;
  1399. + hdr.xor = dev->checkpt_xor;
  1400. +
  1401. + dev->checkpt_byte_offs = sizeof(hdr);
  1402. +
  1403. + memcpy(dev->checkpt_buffer, &hdr, sizeof(hdr));
  1404. +}
  1405. +
  1406. +static int yaffs2_checkpt_check_chunk_hdr(struct yaffs_dev *dev)
  1407. +{
  1408. + struct yaffs_checkpt_chunk_hdr hdr;
  1409. +
  1410. + memcpy(&hdr, dev->checkpt_buffer, sizeof(hdr));
  1411. +
  1412. + dev->checkpt_byte_offs = sizeof(hdr);
  1413. +
  1414. + return hdr.version == YAFFS_CHECKPOINT_VERSION &&
  1415. + hdr.seq == dev->checkpt_page_seq &&
  1416. + hdr.sum == dev->checkpt_sum &&
  1417. + hdr.xor == dev->checkpt_xor;
  1418. +}
  1419. +
  1420. +static int yaffs2_checkpt_space_ok(struct yaffs_dev *dev)
  1421. +{
  1422. + int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
  1423. +
  1424. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1425. + "checkpt blocks_avail = %d", blocks_avail);
  1426. +
  1427. + return (blocks_avail <= 0) ? 0 : 1;
  1428. +}
  1429. +
  1430. +static int yaffs_checkpt_erase(struct yaffs_dev *dev)
  1431. +{
  1432. + int i;
  1433. +
  1434. + if (!dev->drv.drv_erase_fn)
  1435. + return 0;
  1436. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1437. + "checking blocks %d to %d",
  1438. + dev->internal_start_block, dev->internal_end_block);
  1439. +
  1440. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  1441. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
  1442. + int offset_i = apply_block_offset(dev, i);
  1443. + int result;
  1444. +
  1445. + if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) {
  1446. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1447. + "erasing checkpt block %d", i);
  1448. +
  1449. + dev->n_erasures++;
  1450. +
  1451. + result = dev->drv.drv_erase_fn(dev, offset_i);
  1452. + if(result) {
  1453. + bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
  1454. + dev->n_erased_blocks++;
  1455. + dev->n_free_chunks +=
  1456. + dev->param.chunks_per_block;
  1457. + } else {
  1458. + dev->drv.drv_mark_bad_fn(dev, offset_i);
  1459. + bi->block_state = YAFFS_BLOCK_STATE_DEAD;
  1460. + }
  1461. + }
  1462. + }
  1463. +
  1464. + dev->blocks_in_checkpt = 0;
  1465. +
  1466. + return 1;
  1467. +}
  1468. +
  1469. +static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev)
  1470. +{
  1471. + int i;
  1472. + int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
  1473. +
  1474. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1475. + "allocating checkpt block: erased %d reserved %d avail %d next %d ",
  1476. + dev->n_erased_blocks, dev->param.n_reserved_blocks,
  1477. + blocks_avail, dev->checkpt_next_block);
  1478. +
  1479. + if (dev->checkpt_next_block >= 0 &&
  1480. + dev->checkpt_next_block <= dev->internal_end_block &&
  1481. + blocks_avail > 0) {
  1482. +
  1483. + for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
  1484. + i++) {
  1485. + struct yaffs_block_info *bi;
  1486. +
  1487. + bi = yaffs_get_block_info(dev, i);
  1488. + if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
  1489. + dev->checkpt_next_block = i + 1;
  1490. + dev->checkpt_cur_block = i;
  1491. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1492. + "allocating checkpt block %d", i);
  1493. + return;
  1494. + }
  1495. + }
  1496. + }
  1497. + yaffs_trace(YAFFS_TRACE_CHECKPOINT, "out of checkpt blocks");
  1498. +
  1499. + dev->checkpt_next_block = -1;
  1500. + dev->checkpt_cur_block = -1;
  1501. +}
  1502. +
  1503. +static void yaffs2_checkpt_find_block(struct yaffs_dev *dev)
  1504. +{
  1505. + int i;
  1506. + struct yaffs_ext_tags tags;
  1507. +
  1508. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1509. + "find next checkpt block: start: blocks %d next %d",
  1510. + dev->blocks_in_checkpt, dev->checkpt_next_block);
  1511. +
  1512. + if (dev->blocks_in_checkpt < dev->checkpt_max_blocks)
  1513. + for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
  1514. + i++) {
  1515. + int chunk = i * dev->param.chunks_per_block;
  1516. + enum yaffs_block_state state;
  1517. + u32 seq;
  1518. +
  1519. + dev->tagger.read_chunk_tags_fn(dev,
  1520. + apply_chunk_offset(dev, chunk),
  1521. + NULL, &tags);
  1522. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1523. + "find next checkpt block: search: block %d state %d oid %d seq %d eccr %d",
  1524. + i, (int) state,
  1525. + tags.obj_id, tags.seq_number,
  1526. + tags.ecc_result);
  1527. +
  1528. + if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
  1529. + continue;
  1530. +
  1531. + dev->tagger.query_block_fn(dev,
  1532. + apply_block_offset(dev, i),
  1533. + &state, &seq);
  1534. + if (state == YAFFS_BLOCK_STATE_DEAD)
  1535. + continue;
  1536. +
  1537. + /* Right kind of block */
  1538. + dev->checkpt_next_block = tags.obj_id;
  1539. + dev->checkpt_cur_block = i;
  1540. + dev->checkpt_block_list[dev->blocks_in_checkpt] = i;
  1541. + dev->blocks_in_checkpt++;
  1542. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1543. + "found checkpt block %d", i);
  1544. + return;
  1545. + }
  1546. +
  1547. + yaffs_trace(YAFFS_TRACE_CHECKPOINT, "found no more checkpt blocks");
  1548. +
  1549. + dev->checkpt_next_block = -1;
  1550. + dev->checkpt_cur_block = -1;
  1551. +}
  1552. +
  1553. +int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing)
  1554. +{
  1555. + int i;
  1556. +
  1557. + dev->checkpt_open_write = writing;
  1558. +
  1559. + /* Got the functions we need? */
  1560. + if (!dev->tagger.write_chunk_tags_fn ||
  1561. + !dev->tagger.read_chunk_tags_fn ||
  1562. + !dev->drv.drv_erase_fn ||
  1563. + !dev->drv.drv_mark_bad_fn)
  1564. + return 0;
  1565. +
  1566. + if (writing && !yaffs2_checkpt_space_ok(dev))
  1567. + return 0;
  1568. +
  1569. + if (!dev->checkpt_buffer)
  1570. + dev->checkpt_buffer =
  1571. + kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
  1572. + if (!dev->checkpt_buffer)
  1573. + return 0;
  1574. +
  1575. + dev->checkpt_page_seq = 0;
  1576. + dev->checkpt_byte_count = 0;
  1577. + dev->checkpt_sum = 0;
  1578. + dev->checkpt_xor = 0;
  1579. + dev->checkpt_cur_block = -1;
  1580. + dev->checkpt_cur_chunk = -1;
  1581. + dev->checkpt_next_block = dev->internal_start_block;
  1582. +
  1583. + if (writing) {
  1584. + memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
  1585. + yaffs2_checkpt_init_chunk_hdr(dev);
  1586. + return yaffs_checkpt_erase(dev);
  1587. + }
  1588. +
  1589. + /* Opening for a read */
  1590. + /* Set to a value that will kick off a read */
  1591. + dev->checkpt_byte_offs = dev->data_bytes_per_chunk;
  1592. + /* A checkpoint block list of 1 checkpoint block per 16 block is
  1593. + * (hopefully) going to be way more than we need */
  1594. + dev->blocks_in_checkpt = 0;
  1595. + dev->checkpt_max_blocks =
  1596. + (dev->internal_end_block - dev->internal_start_block) / 16 + 2;
  1597. + dev->checkpt_block_list =
  1598. + kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS);
  1599. +
  1600. + if (!dev->checkpt_block_list)
  1601. + return 0;
  1602. +
  1603. + for (i = 0; i < dev->checkpt_max_blocks; i++)
  1604. + dev->checkpt_block_list[i] = -1;
  1605. +
  1606. + return 1;
  1607. +}
  1608. +
  1609. +int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum)
  1610. +{
  1611. + u32 composite_sum;
  1612. +
  1613. + composite_sum = (dev->checkpt_sum << 8) | (dev->checkpt_xor & 0xff);
  1614. + *sum = composite_sum;
  1615. + return 1;
  1616. +}
  1617. +
  1618. +static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev)
  1619. +{
  1620. + int chunk;
  1621. + int offset_chunk;
  1622. + struct yaffs_ext_tags tags;
  1623. +
  1624. + if (dev->checkpt_cur_block < 0) {
  1625. + yaffs2_checkpt_find_erased_block(dev);
  1626. + dev->checkpt_cur_chunk = 0;
  1627. + }
  1628. +
  1629. + if (dev->checkpt_cur_block < 0)
  1630. + return 0;
  1631. +
  1632. + tags.is_deleted = 0;
  1633. + tags.obj_id = dev->checkpt_next_block; /* Hint to next place to look */
  1634. + tags.chunk_id = dev->checkpt_page_seq + 1;
  1635. + tags.seq_number = YAFFS_SEQUENCE_CHECKPOINT_DATA;
  1636. + tags.n_bytes = dev->data_bytes_per_chunk;
  1637. + if (dev->checkpt_cur_chunk == 0) {
  1638. + /* First chunk we write for the block? Set block state to
  1639. + checkpoint */
  1640. + struct yaffs_block_info *bi =
  1641. + yaffs_get_block_info(dev, dev->checkpt_cur_block);
  1642. + bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
  1643. + dev->blocks_in_checkpt++;
  1644. + }
  1645. +
  1646. + chunk =
  1647. + dev->checkpt_cur_block * dev->param.chunks_per_block +
  1648. + dev->checkpt_cur_chunk;
  1649. +
  1650. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1651. + "checkpoint wite buffer nand %d(%d:%d) objid %d chId %d",
  1652. + chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk,
  1653. + tags.obj_id, tags.chunk_id);
  1654. +
  1655. + offset_chunk = apply_chunk_offset(dev, chunk);
  1656. +
  1657. + dev->n_page_writes++;
  1658. +
  1659. + dev->tagger.write_chunk_tags_fn(dev, offset_chunk,
  1660. + dev->checkpt_buffer, &tags);
  1661. + dev->checkpt_page_seq++;
  1662. + dev->checkpt_cur_chunk++;
  1663. + if (dev->checkpt_cur_chunk >= dev->param.chunks_per_block) {
  1664. + dev->checkpt_cur_chunk = 0;
  1665. + dev->checkpt_cur_block = -1;
  1666. + }
  1667. + memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
  1668. +
  1669. + yaffs2_checkpt_init_chunk_hdr(dev);
  1670. +
  1671. +
  1672. + return 1;
  1673. +}
  1674. +
  1675. +int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes)
  1676. +{
  1677. + int i = 0;
  1678. + int ok = 1;
  1679. + u8 *data_bytes = (u8 *) data;
  1680. +
  1681. + if (!dev->checkpt_buffer)
  1682. + return 0;
  1683. +
  1684. + if (!dev->checkpt_open_write)
  1685. + return -1;
  1686. +
  1687. + while (i < n_bytes && ok) {
  1688. + dev->checkpt_buffer[dev->checkpt_byte_offs] = *data_bytes;
  1689. + dev->checkpt_sum += *data_bytes;
  1690. + dev->checkpt_xor ^= *data_bytes;
  1691. +
  1692. + dev->checkpt_byte_offs++;
  1693. + i++;
  1694. + data_bytes++;
  1695. + dev->checkpt_byte_count++;
  1696. +
  1697. + if (dev->checkpt_byte_offs < 0 ||
  1698. + dev->checkpt_byte_offs >= dev->data_bytes_per_chunk)
  1699. + ok = yaffs2_checkpt_flush_buffer(dev);
  1700. + }
  1701. +
  1702. + return i;
  1703. +}
  1704. +
  1705. +int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
  1706. +{
  1707. + int i = 0;
  1708. + int ok = 1;
  1709. + struct yaffs_ext_tags tags;
  1710. + int chunk;
  1711. + int offset_chunk;
  1712. + u8 *data_bytes = (u8 *) data;
  1713. +
  1714. + if (!dev->checkpt_buffer)
  1715. + return 0;
  1716. +
  1717. + if (dev->checkpt_open_write)
  1718. + return -1;
  1719. +
  1720. + while (i < n_bytes && ok) {
  1721. +
  1722. + if (dev->checkpt_byte_offs < 0 ||
  1723. + dev->checkpt_byte_offs >= dev->data_bytes_per_chunk) {
  1724. +
  1725. + if (dev->checkpt_cur_block < 0) {
  1726. + yaffs2_checkpt_find_block(dev);
  1727. + dev->checkpt_cur_chunk = 0;
  1728. + }
  1729. +
  1730. + if (dev->checkpt_cur_block < 0) {
  1731. + ok = 0;
  1732. + break;
  1733. + }
  1734. +
  1735. + chunk = dev->checkpt_cur_block *
  1736. + dev->param.chunks_per_block +
  1737. + dev->checkpt_cur_chunk;
  1738. +
  1739. + offset_chunk = apply_chunk_offset(dev, chunk);
  1740. + dev->n_page_reads++;
  1741. +
  1742. + /* read in the next chunk */
  1743. + dev->tagger.read_chunk_tags_fn(dev,
  1744. + offset_chunk,
  1745. + dev->checkpt_buffer,
  1746. + &tags);
  1747. +
  1748. + if (tags.chunk_id != (dev->checkpt_page_seq + 1) ||
  1749. + tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
  1750. + tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) {
  1751. + ok = 0;
  1752. + break;
  1753. + }
  1754. + if(!yaffs2_checkpt_check_chunk_hdr(dev)) {
  1755. + ok = 0;
  1756. + break;
  1757. + }
  1758. +
  1759. + dev->checkpt_page_seq++;
  1760. + dev->checkpt_cur_chunk++;
  1761. +
  1762. + if (dev->checkpt_cur_chunk >=
  1763. + dev->param.chunks_per_block)
  1764. + dev->checkpt_cur_block = -1;
  1765. +
  1766. + }
  1767. +
  1768. + *data_bytes = dev->checkpt_buffer[dev->checkpt_byte_offs];
  1769. + dev->checkpt_sum += *data_bytes;
  1770. + dev->checkpt_xor ^= *data_bytes;
  1771. + dev->checkpt_byte_offs++;
  1772. + i++;
  1773. + data_bytes++;
  1774. + dev->checkpt_byte_count++;
  1775. + }
  1776. +
  1777. + return i;
  1778. +}
  1779. +
  1780. +int yaffs_checkpt_close(struct yaffs_dev *dev)
  1781. +{
  1782. + int i;
  1783. +
  1784. + if (dev->checkpt_open_write) {
  1785. + if (dev->checkpt_byte_offs !=
  1786. + sizeof(sizeof(struct yaffs_checkpt_chunk_hdr)))
  1787. + yaffs2_checkpt_flush_buffer(dev);
  1788. + } else if (dev->checkpt_block_list) {
  1789. + for (i = 0;
  1790. + i < dev->blocks_in_checkpt &&
  1791. + dev->checkpt_block_list[i] >= 0; i++) {
  1792. + int blk = dev->checkpt_block_list[i];
  1793. + struct yaffs_block_info *bi = NULL;
  1794. +
  1795. + if (dev->internal_start_block <= blk &&
  1796. + blk <= dev->internal_end_block)
  1797. + bi = yaffs_get_block_info(dev, blk);
  1798. + if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY)
  1799. + bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
  1800. + }
  1801. + kfree(dev->checkpt_block_list);
  1802. + dev->checkpt_block_list = NULL;
  1803. + }
  1804. +
  1805. + dev->n_free_chunks -=
  1806. + dev->blocks_in_checkpt * dev->param.chunks_per_block;
  1807. + dev->n_erased_blocks -= dev->blocks_in_checkpt;
  1808. +
  1809. + yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d",
  1810. + dev->checkpt_byte_count);
  1811. +
  1812. + if (dev->checkpt_buffer) {
  1813. + /* free the buffer */
  1814. + kfree(dev->checkpt_buffer);
  1815. + dev->checkpt_buffer = NULL;
  1816. + return 1;
  1817. + } else {
  1818. + return 0;
  1819. + }
  1820. +}
  1821. +
  1822. +int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev)
  1823. +{
  1824. + /* Erase the checkpoint data */
  1825. +
  1826. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  1827. + "checkpoint invalidate of %d blocks",
  1828. + dev->blocks_in_checkpt);
  1829. +
  1830. + return yaffs_checkpt_erase(dev);
  1831. +}
  1832. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_checkptrw.h linux-3.14.4/fs/yaffs2/yaffs_checkptrw.h
  1833. --- linux-3.14.4.orig/fs/yaffs2/yaffs_checkptrw.h 1970-01-01 01:00:00.000000000 +0100
  1834. +++ linux-3.14.4/fs/yaffs2/yaffs_checkptrw.h 2014-05-14 12:41:23.976792423 +0200
  1835. @@ -0,0 +1,33 @@
  1836. +/*
  1837. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  1838. + *
  1839. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1840. + * for Toby Churchill Ltd and Brightstar Engineering
  1841. + *
  1842. + * Created by Charles Manning <charles@aleph1.co.uk>
  1843. + *
  1844. + * This program is free software; you can redistribute it and/or modify
  1845. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  1846. + * published by the Free Software Foundation.
  1847. + *
  1848. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  1849. + */
  1850. +
  1851. +#ifndef __YAFFS_CHECKPTRW_H__
  1852. +#define __YAFFS_CHECKPTRW_H__
  1853. +
  1854. +#include "yaffs_guts.h"
  1855. +
  1856. +int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing);
  1857. +
  1858. +int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes);
  1859. +
  1860. +int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes);
  1861. +
  1862. +int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum);
  1863. +
  1864. +int yaffs_checkpt_close(struct yaffs_dev *dev);
  1865. +
  1866. +int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev);
  1867. +
  1868. +#endif
  1869. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_ecc.c linux-3.14.4/fs/yaffs2/yaffs_ecc.c
  1870. --- linux-3.14.4.orig/fs/yaffs2/yaffs_ecc.c 1970-01-01 01:00:00.000000000 +0100
  1871. +++ linux-3.14.4/fs/yaffs2/yaffs_ecc.c 2014-05-14 12:41:23.976792423 +0200
  1872. @@ -0,0 +1,281 @@
  1873. +/*
  1874. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  1875. + *
  1876. + * Copyright (C) 2002-2011 Aleph One Ltd.
  1877. + * for Toby Churchill Ltd and Brightstar Engineering
  1878. + *
  1879. + * Created by Charles Manning <charles@aleph1.co.uk>
  1880. + *
  1881. + * This program is free software; you can redistribute it and/or modify
  1882. + * it under the terms of the GNU General Public License version 2 as
  1883. + * published by the Free Software Foundation.
  1884. + */
  1885. +
  1886. +/*
  1887. + * This code implements the ECC algorithm used in SmartMedia.
  1888. + *
  1889. + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
  1890. + * The two unused bit are set to 1.
  1891. + * The ECC can correct single bit errors in a 256-byte page of data. Thus, two
  1892. + * such ECC blocks are used on a 512-byte NAND page.
  1893. + *
  1894. + */
  1895. +
  1896. +#include "yportenv.h"
  1897. +
  1898. +#include "yaffs_ecc.h"
  1899. +
  1900. +/* Table generated by gen-ecc.c
  1901. + * Using a table means we do not have to calculate p1..p4 and p1'..p4'
  1902. + * for each byte of data. These are instead provided in a table in bits7..2.
  1903. + * Bit 0 of each entry indicates whether the entry has an odd or even parity,
  1904. + * and therefore this bytes influence on the line parity.
  1905. + */
  1906. +
  1907. +static const unsigned char column_parity_table[] = {
  1908. + 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
  1909. + 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
  1910. + 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
  1911. + 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
  1912. + 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
  1913. + 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
  1914. + 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
  1915. + 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
  1916. + 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
  1917. + 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
  1918. + 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
  1919. + 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
  1920. + 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
  1921. + 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
  1922. + 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
  1923. + 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
  1924. + 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
  1925. + 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
  1926. + 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
  1927. + 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
  1928. + 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
  1929. + 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
  1930. + 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
  1931. + 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
  1932. + 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
  1933. + 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
  1934. + 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
  1935. + 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
  1936. + 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
  1937. + 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
  1938. + 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
  1939. + 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
  1940. +};
  1941. +
  1942. +
  1943. +/* Calculate the ECC for a 256-byte block of data */
  1944. +void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc)
  1945. +{
  1946. + unsigned int i;
  1947. + unsigned char col_parity = 0;
  1948. + unsigned char line_parity = 0;
  1949. + unsigned char line_parity_prime = 0;
  1950. + unsigned char t;
  1951. + unsigned char b;
  1952. +
  1953. + for (i = 0; i < 256; i++) {
  1954. + b = column_parity_table[*data++];
  1955. + col_parity ^= b;
  1956. +
  1957. + if (b & 0x01) { /* odd number of bits in the byte */
  1958. + line_parity ^= i;
  1959. + line_parity_prime ^= ~i;
  1960. + }
  1961. + }
  1962. +
  1963. + ecc[2] = (~col_parity) | 0x03;
  1964. +
  1965. + t = 0;
  1966. + if (line_parity & 0x80)
  1967. + t |= 0x80;
  1968. + if (line_parity_prime & 0x80)
  1969. + t |= 0x40;
  1970. + if (line_parity & 0x40)
  1971. + t |= 0x20;
  1972. + if (line_parity_prime & 0x40)
  1973. + t |= 0x10;
  1974. + if (line_parity & 0x20)
  1975. + t |= 0x08;
  1976. + if (line_parity_prime & 0x20)
  1977. + t |= 0x04;
  1978. + if (line_parity & 0x10)
  1979. + t |= 0x02;
  1980. + if (line_parity_prime & 0x10)
  1981. + t |= 0x01;
  1982. + ecc[1] = ~t;
  1983. +
  1984. + t = 0;
  1985. + if (line_parity & 0x08)
  1986. + t |= 0x80;
  1987. + if (line_parity_prime & 0x08)
  1988. + t |= 0x40;
  1989. + if (line_parity & 0x04)
  1990. + t |= 0x20;
  1991. + if (line_parity_prime & 0x04)
  1992. + t |= 0x10;
  1993. + if (line_parity & 0x02)
  1994. + t |= 0x08;
  1995. + if (line_parity_prime & 0x02)
  1996. + t |= 0x04;
  1997. + if (line_parity & 0x01)
  1998. + t |= 0x02;
  1999. + if (line_parity_prime & 0x01)
  2000. + t |= 0x01;
  2001. + ecc[0] = ~t;
  2002. +
  2003. +}
  2004. +
  2005. +/* Correct the ECC on a 256 byte block of data */
  2006. +
  2007. +int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
  2008. + const unsigned char *test_ecc)
  2009. +{
  2010. + unsigned char d0, d1, d2; /* deltas */
  2011. +
  2012. + d0 = read_ecc[0] ^ test_ecc[0];
  2013. + d1 = read_ecc[1] ^ test_ecc[1];
  2014. + d2 = read_ecc[2] ^ test_ecc[2];
  2015. +
  2016. + if ((d0 | d1 | d2) == 0)
  2017. + return 0; /* no error */
  2018. +
  2019. + if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
  2020. + ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
  2021. + ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) {
  2022. + /* Single bit (recoverable) error in data */
  2023. +
  2024. + unsigned byte;
  2025. + unsigned bit;
  2026. +
  2027. + bit = byte = 0;
  2028. +
  2029. + if (d1 & 0x80)
  2030. + byte |= 0x80;
  2031. + if (d1 & 0x20)
  2032. + byte |= 0x40;
  2033. + if (d1 & 0x08)
  2034. + byte |= 0x20;
  2035. + if (d1 & 0x02)
  2036. + byte |= 0x10;
  2037. + if (d0 & 0x80)
  2038. + byte |= 0x08;
  2039. + if (d0 & 0x20)
  2040. + byte |= 0x04;
  2041. + if (d0 & 0x08)
  2042. + byte |= 0x02;
  2043. + if (d0 & 0x02)
  2044. + byte |= 0x01;
  2045. +
  2046. + if (d2 & 0x80)
  2047. + bit |= 0x04;
  2048. + if (d2 & 0x20)
  2049. + bit |= 0x02;
  2050. + if (d2 & 0x08)
  2051. + bit |= 0x01;
  2052. +
  2053. + data[byte] ^= (1 << bit);
  2054. +
  2055. + return 1; /* Corrected the error */
  2056. + }
  2057. +
  2058. + if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) {
  2059. + /* Reccoverable error in ecc */
  2060. +
  2061. + read_ecc[0] = test_ecc[0];
  2062. + read_ecc[1] = test_ecc[1];
  2063. + read_ecc[2] = test_ecc[2];
  2064. +
  2065. + return 1; /* Corrected the error */
  2066. + }
  2067. +
  2068. + /* Unrecoverable error */
  2069. +
  2070. + return -1;
  2071. +
  2072. +}
  2073. +
  2074. +/*
  2075. + * ECCxxxOther does ECC calcs on arbitrary n bytes of data
  2076. + */
  2077. +void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
  2078. + struct yaffs_ecc_other *ecc_other)
  2079. +{
  2080. + unsigned int i;
  2081. + unsigned char col_parity = 0;
  2082. + unsigned line_parity = 0;
  2083. + unsigned line_parity_prime = 0;
  2084. + unsigned char b;
  2085. +
  2086. + for (i = 0; i < n_bytes; i++) {
  2087. + b = column_parity_table[*data++];
  2088. + col_parity ^= b;
  2089. +
  2090. + if (b & 0x01) {
  2091. + /* odd number of bits in the byte */
  2092. + line_parity ^= i;
  2093. + line_parity_prime ^= ~i;
  2094. + }
  2095. +
  2096. + }
  2097. +
  2098. + ecc_other->col_parity = (col_parity >> 2) & 0x3f;
  2099. + ecc_other->line_parity = line_parity;
  2100. + ecc_other->line_parity_prime = line_parity_prime;
  2101. +}
  2102. +
  2103. +int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
  2104. + struct yaffs_ecc_other *read_ecc,
  2105. + const struct yaffs_ecc_other *test_ecc)
  2106. +{
  2107. + unsigned char delta_col; /* column parity delta */
  2108. + unsigned delta_line; /* line parity delta */
  2109. + unsigned delta_line_prime; /* line parity delta */
  2110. + unsigned bit;
  2111. +
  2112. + delta_col = read_ecc->col_parity ^ test_ecc->col_parity;
  2113. + delta_line = read_ecc->line_parity ^ test_ecc->line_parity;
  2114. + delta_line_prime =
  2115. + read_ecc->line_parity_prime ^ test_ecc->line_parity_prime;
  2116. +
  2117. + if ((delta_col | delta_line | delta_line_prime) == 0)
  2118. + return 0; /* no error */
  2119. +
  2120. + if (delta_line == ~delta_line_prime &&
  2121. + (((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) {
  2122. + /* Single bit (recoverable) error in data */
  2123. +
  2124. + bit = 0;
  2125. +
  2126. + if (delta_col & 0x20)
  2127. + bit |= 0x04;
  2128. + if (delta_col & 0x08)
  2129. + bit |= 0x02;
  2130. + if (delta_col & 0x02)
  2131. + bit |= 0x01;
  2132. +
  2133. + if (delta_line >= n_bytes)
  2134. + return -1;
  2135. +
  2136. + data[delta_line] ^= (1 << bit);
  2137. +
  2138. + return 1; /* corrected */
  2139. + }
  2140. +
  2141. + if ((hweight32(delta_line) +
  2142. + hweight32(delta_line_prime) +
  2143. + hweight8(delta_col)) == 1) {
  2144. + /* Reccoverable error in ecc */
  2145. +
  2146. + *read_ecc = *test_ecc;
  2147. + return 1; /* corrected */
  2148. + }
  2149. +
  2150. + /* Unrecoverable error */
  2151. +
  2152. + return -1;
  2153. +}
  2154. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_ecc.h linux-3.14.4/fs/yaffs2/yaffs_ecc.h
  2155. --- linux-3.14.4.orig/fs/yaffs2/yaffs_ecc.h 1970-01-01 01:00:00.000000000 +0100
  2156. +++ linux-3.14.4/fs/yaffs2/yaffs_ecc.h 2014-05-14 12:41:23.976792423 +0200
  2157. @@ -0,0 +1,44 @@
  2158. +/*
  2159. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  2160. + *
  2161. + * Copyright (C) 2002-2011 Aleph One Ltd.
  2162. + * for Toby Churchill Ltd and Brightstar Engineering
  2163. + *
  2164. + * Created by Charles Manning <charles@aleph1.co.uk>
  2165. + *
  2166. + * This program is free software; you can redistribute it and/or modify
  2167. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  2168. + * published by the Free Software Foundation.
  2169. + *
  2170. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  2171. + */
  2172. +
  2173. +/*
  2174. + * This code implements the ECC algorithm used in SmartMedia.
  2175. + *
  2176. + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
  2177. + * The two unused bit are set to 1.
  2178. + * The ECC can correct single bit errors in a 256-byte page of data.
  2179. + * Thus, two such ECC blocks are used on a 512-byte NAND page.
  2180. + *
  2181. + */
  2182. +
  2183. +#ifndef __YAFFS_ECC_H__
  2184. +#define __YAFFS_ECC_H__
  2185. +
  2186. +struct yaffs_ecc_other {
  2187. + unsigned char col_parity;
  2188. + unsigned line_parity;
  2189. + unsigned line_parity_prime;
  2190. +};
  2191. +
  2192. +void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc);
  2193. +int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
  2194. + const unsigned char *test_ecc);
  2195. +
  2196. +void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
  2197. + struct yaffs_ecc_other *ecc);
  2198. +int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
  2199. + struct yaffs_ecc_other *read_ecc,
  2200. + const struct yaffs_ecc_other *test_ecc);
  2201. +#endif
  2202. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_getblockinfo.h linux-3.14.4/fs/yaffs2/yaffs_getblockinfo.h
  2203. --- linux-3.14.4.orig/fs/yaffs2/yaffs_getblockinfo.h 1970-01-01 01:00:00.000000000 +0100
  2204. +++ linux-3.14.4/fs/yaffs2/yaffs_getblockinfo.h 2014-05-14 12:41:23.976792423 +0200
  2205. @@ -0,0 +1,35 @@
  2206. +/*
  2207. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  2208. + *
  2209. + * Copyright (C) 2002-2011 Aleph One Ltd.
  2210. + * for Toby Churchill Ltd and Brightstar Engineering
  2211. + *
  2212. + * Created by Charles Manning <charles@aleph1.co.uk>
  2213. + *
  2214. + * This program is free software; you can redistribute it and/or modify
  2215. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  2216. + * published by the Free Software Foundation.
  2217. + *
  2218. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  2219. + */
  2220. +
  2221. +#ifndef __YAFFS_GETBLOCKINFO_H__
  2222. +#define __YAFFS_GETBLOCKINFO_H__
  2223. +
  2224. +#include "yaffs_guts.h"
  2225. +#include "yaffs_trace.h"
  2226. +
  2227. +/* Function to manipulate block info */
  2228. +static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev
  2229. + *dev, int blk)
  2230. +{
  2231. + if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
  2232. + yaffs_trace(YAFFS_TRACE_ERROR,
  2233. + "**>> yaffs: get_block_info block %d is not valid",
  2234. + blk);
  2235. + BUG();
  2236. + }
  2237. + return &dev->block_info[blk - dev->internal_start_block];
  2238. +}
  2239. +
  2240. +#endif
  2241. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_guts.c linux-3.14.4/fs/yaffs2/yaffs_guts.c
  2242. --- linux-3.14.4.orig/fs/yaffs2/yaffs_guts.c 1970-01-01 01:00:00.000000000 +0100
  2243. +++ linux-3.14.4/fs/yaffs2/yaffs_guts.c 2014-05-14 12:41:23.984792448 +0200
  2244. @@ -0,0 +1,5146 @@
  2245. +/*
  2246. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  2247. + *
  2248. + * Copyright (C) 2002-2011 Aleph One Ltd.
  2249. + * for Toby Churchill Ltd and Brightstar Engineering
  2250. + *
  2251. + * Created by Charles Manning <charles@aleph1.co.uk>
  2252. + *
  2253. + * This program is free software; you can redistribute it and/or modify
  2254. + * it under the terms of the GNU General Public License version 2 as
  2255. + * published by the Free Software Foundation.
  2256. + */
  2257. +
  2258. +#include "yportenv.h"
  2259. +#include "yaffs_trace.h"
  2260. +
  2261. +#include "yaffs_guts.h"
  2262. +#include "yaffs_getblockinfo.h"
  2263. +#include "yaffs_tagscompat.h"
  2264. +#include "yaffs_tagsmarshall.h"
  2265. +#include "yaffs_nand.h"
  2266. +#include "yaffs_yaffs1.h"
  2267. +#include "yaffs_yaffs2.h"
  2268. +#include "yaffs_bitmap.h"
  2269. +#include "yaffs_verify.h"
  2270. +#include "yaffs_nand.h"
  2271. +#include "yaffs_packedtags2.h"
  2272. +#include "yaffs_nameval.h"
  2273. +#include "yaffs_allocator.h"
  2274. +#include "yaffs_attribs.h"
  2275. +#include "yaffs_summary.h"
  2276. +
  2277. +/* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
  2278. +#define YAFFS_GC_GOOD_ENOUGH 2
  2279. +#define YAFFS_GC_PASSIVE_THRESHOLD 4
  2280. +
  2281. +#include "yaffs_ecc.h"
  2282. +
  2283. +/* Forward declarations */
  2284. +
  2285. +static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
  2286. + const u8 *buffer, int n_bytes, int use_reserve);
  2287. +
  2288. +static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
  2289. + int buffer_size);
  2290. +
  2291. +/* Function to calculate chunk and offset */
  2292. +
  2293. +void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
  2294. + int *chunk_out, u32 *offset_out)
  2295. +{
  2296. + int chunk;
  2297. + u32 offset;
  2298. +
  2299. + chunk = (u32) (addr >> dev->chunk_shift);
  2300. +
  2301. + if (dev->chunk_div == 1) {
  2302. + /* easy power of 2 case */
  2303. + offset = (u32) (addr & dev->chunk_mask);
  2304. + } else {
  2305. + /* Non power-of-2 case */
  2306. +
  2307. + loff_t chunk_base;
  2308. +
  2309. + chunk /= dev->chunk_div;
  2310. +
  2311. + chunk_base = ((loff_t) chunk) * dev->data_bytes_per_chunk;
  2312. + offset = (u32) (addr - chunk_base);
  2313. + }
  2314. +
  2315. + *chunk_out = chunk;
  2316. + *offset_out = offset;
  2317. +}
  2318. +
  2319. +/* Function to return the number of shifts for a power of 2 greater than or
  2320. + * equal to the given number
  2321. + * Note we don't try to cater for all possible numbers and this does not have to
  2322. + * be hellishly efficient.
  2323. + */
  2324. +
  2325. +static inline u32 calc_shifts_ceiling(u32 x)
  2326. +{
  2327. + int extra_bits;
  2328. + int shifts;
  2329. +
  2330. + shifts = extra_bits = 0;
  2331. +
  2332. + while (x > 1) {
  2333. + if (x & 1)
  2334. + extra_bits++;
  2335. + x >>= 1;
  2336. + shifts++;
  2337. + }
  2338. +
  2339. + if (extra_bits)
  2340. + shifts++;
  2341. +
  2342. + return shifts;
  2343. +}
  2344. +
  2345. +/* Function to return the number of shifts to get a 1 in bit 0
  2346. + */
  2347. +
  2348. +static inline u32 calc_shifts(u32 x)
  2349. +{
  2350. + u32 shifts;
  2351. +
  2352. + shifts = 0;
  2353. +
  2354. + if (!x)
  2355. + return 0;
  2356. +
  2357. + while (!(x & 1)) {
  2358. + x >>= 1;
  2359. + shifts++;
  2360. + }
  2361. +
  2362. + return shifts;
  2363. +}
  2364. +
  2365. +/*
  2366. + * Temporary buffer manipulations.
  2367. + */
  2368. +
  2369. +static int yaffs_init_tmp_buffers(struct yaffs_dev *dev)
  2370. +{
  2371. + int i;
  2372. + u8 *buf = (u8 *) 1;
  2373. +
  2374. + memset(dev->temp_buffer, 0, sizeof(dev->temp_buffer));
  2375. +
  2376. + for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
  2377. + dev->temp_buffer[i].in_use = 0;
  2378. + buf = kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
  2379. + dev->temp_buffer[i].buffer = buf;
  2380. + }
  2381. +
  2382. + return buf ? YAFFS_OK : YAFFS_FAIL;
  2383. +}
  2384. +
  2385. +u8 *yaffs_get_temp_buffer(struct yaffs_dev * dev)
  2386. +{
  2387. + int i;
  2388. +
  2389. + dev->temp_in_use++;
  2390. + if (dev->temp_in_use > dev->max_temp)
  2391. + dev->max_temp = dev->temp_in_use;
  2392. +
  2393. + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
  2394. + if (dev->temp_buffer[i].in_use == 0) {
  2395. + dev->temp_buffer[i].in_use = 1;
  2396. + return dev->temp_buffer[i].buffer;
  2397. + }
  2398. + }
  2399. +
  2400. + yaffs_trace(YAFFS_TRACE_BUFFERS, "Out of temp buffers");
  2401. + /*
  2402. + * If we got here then we have to allocate an unmanaged one
  2403. + * This is not good.
  2404. + */
  2405. +
  2406. + dev->unmanaged_buffer_allocs++;
  2407. + return kmalloc(dev->data_bytes_per_chunk, GFP_NOFS);
  2408. +
  2409. +}
  2410. +
  2411. +void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer)
  2412. +{
  2413. + int i;
  2414. +
  2415. + dev->temp_in_use--;
  2416. +
  2417. + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
  2418. + if (dev->temp_buffer[i].buffer == buffer) {
  2419. + dev->temp_buffer[i].in_use = 0;
  2420. + return;
  2421. + }
  2422. + }
  2423. +
  2424. + if (buffer) {
  2425. + /* assume it is an unmanaged one. */
  2426. + yaffs_trace(YAFFS_TRACE_BUFFERS,
  2427. + "Releasing unmanaged temp buffer");
  2428. + kfree(buffer);
  2429. + dev->unmanaged_buffer_deallocs++;
  2430. + }
  2431. +
  2432. +}
  2433. +
  2434. +/*
  2435. + * Functions for robustisizing TODO
  2436. + *
  2437. + */
  2438. +
  2439. +static void yaffs_handle_chunk_wr_ok(struct yaffs_dev *dev, int nand_chunk,
  2440. + const u8 *data,
  2441. + const struct yaffs_ext_tags *tags)
  2442. +{
  2443. + (void) dev;
  2444. + (void) nand_chunk;
  2445. + (void) data;
  2446. + (void) tags;
  2447. +}
  2448. +
  2449. +static void yaffs_handle_chunk_update(struct yaffs_dev *dev, int nand_chunk,
  2450. + const struct yaffs_ext_tags *tags)
  2451. +{
  2452. + (void) dev;
  2453. + (void) nand_chunk;
  2454. + (void) tags;
  2455. +}
  2456. +
  2457. +void yaffs_handle_chunk_error(struct yaffs_dev *dev,
  2458. + struct yaffs_block_info *bi)
  2459. +{
  2460. + if (!bi->gc_prioritise) {
  2461. + bi->gc_prioritise = 1;
  2462. + dev->has_pending_prioritised_gc = 1;
  2463. + bi->chunk_error_strikes++;
  2464. +
  2465. + if (bi->chunk_error_strikes > 3) {
  2466. + bi->needs_retiring = 1; /* Too many stikes, so retire */
  2467. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2468. + "yaffs: Block struck out");
  2469. +
  2470. + }
  2471. + }
  2472. +}
  2473. +
  2474. +static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk,
  2475. + int erased_ok)
  2476. +{
  2477. + int flash_block = nand_chunk / dev->param.chunks_per_block;
  2478. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
  2479. +
  2480. + yaffs_handle_chunk_error(dev, bi);
  2481. +
  2482. + if (erased_ok) {
  2483. + /* Was an actual write failure,
  2484. + * so mark the block for retirement.*/
  2485. + bi->needs_retiring = 1;
  2486. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  2487. + "**>> Block %d needs retiring", flash_block);
  2488. + }
  2489. +
  2490. + /* Delete the chunk */
  2491. + yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
  2492. + yaffs_skip_rest_of_block(dev);
  2493. +}
  2494. +
  2495. +/*
  2496. + * Verification code
  2497. + */
  2498. +
  2499. +/*
  2500. + * Simple hash function. Needs to have a reasonable spread
  2501. + */
  2502. +
  2503. +static inline int yaffs_hash_fn(int n)
  2504. +{
  2505. + if (n < 0)
  2506. + n = -n;
  2507. + return n % YAFFS_NOBJECT_BUCKETS;
  2508. +}
  2509. +
  2510. +/*
  2511. + * Access functions to useful fake objects.
  2512. + * Note that root might have a presence in NAND if permissions are set.
  2513. + */
  2514. +
  2515. +struct yaffs_obj *yaffs_root(struct yaffs_dev *dev)
  2516. +{
  2517. + return dev->root_dir;
  2518. +}
  2519. +
  2520. +struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev)
  2521. +{
  2522. + return dev->lost_n_found;
  2523. +}
  2524. +
  2525. +/*
  2526. + * Erased NAND checking functions
  2527. + */
  2528. +
  2529. +int yaffs_check_ff(u8 *buffer, int n_bytes)
  2530. +{
  2531. + /* Horrible, slow implementation */
  2532. + while (n_bytes--) {
  2533. + if (*buffer != 0xff)
  2534. + return 0;
  2535. + buffer++;
  2536. + }
  2537. + return 1;
  2538. +}
  2539. +
  2540. +static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk)
  2541. +{
  2542. + int retval = YAFFS_OK;
  2543. + u8 *data = yaffs_get_temp_buffer(dev);
  2544. + struct yaffs_ext_tags tags;
  2545. + int result;
  2546. +
  2547. + result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);
  2548. +
  2549. + if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
  2550. + retval = YAFFS_FAIL;
  2551. +
  2552. + if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) ||
  2553. + tags.chunk_used) {
  2554. + yaffs_trace(YAFFS_TRACE_NANDACCESS,
  2555. + "Chunk %d not erased", nand_chunk);
  2556. + retval = YAFFS_FAIL;
  2557. + }
  2558. +
  2559. + yaffs_release_temp_buffer(dev, data);
  2560. +
  2561. + return retval;
  2562. +
  2563. +}
  2564. +
  2565. +static int yaffs_verify_chunk_written(struct yaffs_dev *dev,
  2566. + int nand_chunk,
  2567. + const u8 *data,
  2568. + struct yaffs_ext_tags *tags)
  2569. +{
  2570. + int retval = YAFFS_OK;
  2571. + struct yaffs_ext_tags temp_tags;
  2572. + u8 *buffer = yaffs_get_temp_buffer(dev);
  2573. + int result;
  2574. +
  2575. + result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags);
  2576. + if (memcmp(buffer, data, dev->data_bytes_per_chunk) ||
  2577. + temp_tags.obj_id != tags->obj_id ||
  2578. + temp_tags.chunk_id != tags->chunk_id ||
  2579. + temp_tags.n_bytes != tags->n_bytes)
  2580. + retval = YAFFS_FAIL;
  2581. +
  2582. + yaffs_release_temp_buffer(dev, buffer);
  2583. +
  2584. + return retval;
  2585. +}
  2586. +
  2587. +
  2588. +int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks)
  2589. +{
  2590. + int reserved_chunks;
  2591. + int reserved_blocks = dev->param.n_reserved_blocks;
  2592. + int checkpt_blocks;
  2593. +
  2594. + checkpt_blocks = yaffs_calc_checkpt_blocks_required(dev);
  2595. +
  2596. + reserved_chunks =
  2597. + (reserved_blocks + checkpt_blocks) * dev->param.chunks_per_block;
  2598. +
  2599. + return (dev->n_free_chunks > (reserved_chunks + n_chunks));
  2600. +}
  2601. +
  2602. +static int yaffs_find_alloc_block(struct yaffs_dev *dev)
  2603. +{
  2604. + int i;
  2605. + struct yaffs_block_info *bi;
  2606. +
  2607. + if (dev->n_erased_blocks < 1) {
  2608. + /* Hoosterman we've got a problem.
  2609. + * Can't get space to gc
  2610. + */
  2611. + yaffs_trace(YAFFS_TRACE_ERROR,
  2612. + "yaffs tragedy: no more erased blocks");
  2613. +
  2614. + return -1;
  2615. + }
  2616. +
  2617. + /* Find an empty block. */
  2618. +
  2619. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  2620. + dev->alloc_block_finder++;
  2621. + if (dev->alloc_block_finder < dev->internal_start_block
  2622. + || dev->alloc_block_finder > dev->internal_end_block) {
  2623. + dev->alloc_block_finder = dev->internal_start_block;
  2624. + }
  2625. +
  2626. + bi = yaffs_get_block_info(dev, dev->alloc_block_finder);
  2627. +
  2628. + if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
  2629. + bi->block_state = YAFFS_BLOCK_STATE_ALLOCATING;
  2630. + dev->seq_number++;
  2631. + bi->seq_number = dev->seq_number;
  2632. + dev->n_erased_blocks--;
  2633. + yaffs_trace(YAFFS_TRACE_ALLOCATE,
  2634. + "Allocated block %d, seq %d, %d left" ,
  2635. + dev->alloc_block_finder, dev->seq_number,
  2636. + dev->n_erased_blocks);
  2637. + return dev->alloc_block_finder;
  2638. + }
  2639. + }
  2640. +
  2641. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2642. + "yaffs tragedy: no more erased blocks, but there should have been %d",
  2643. + dev->n_erased_blocks);
  2644. +
  2645. + return -1;
  2646. +}
  2647. +
  2648. +static int yaffs_alloc_chunk(struct yaffs_dev *dev, int use_reserver,
  2649. + struct yaffs_block_info **block_ptr)
  2650. +{
  2651. + int ret_val;
  2652. + struct yaffs_block_info *bi;
  2653. +
  2654. + if (dev->alloc_block < 0) {
  2655. + /* Get next block to allocate off */
  2656. + dev->alloc_block = yaffs_find_alloc_block(dev);
  2657. + dev->alloc_page = 0;
  2658. + }
  2659. +
  2660. + if (!use_reserver && !yaffs_check_alloc_available(dev, 1)) {
  2661. + /* No space unless we're allowed to use the reserve. */
  2662. + return -1;
  2663. + }
  2664. +
  2665. + if (dev->n_erased_blocks < dev->param.n_reserved_blocks
  2666. + && dev->alloc_page == 0)
  2667. + yaffs_trace(YAFFS_TRACE_ALLOCATE, "Allocating reserve");
  2668. +
  2669. + /* Next page please.... */
  2670. + if (dev->alloc_block >= 0) {
  2671. + bi = yaffs_get_block_info(dev, dev->alloc_block);
  2672. +
  2673. + ret_val = (dev->alloc_block * dev->param.chunks_per_block) +
  2674. + dev->alloc_page;
  2675. + bi->pages_in_use++;
  2676. + yaffs_set_chunk_bit(dev, dev->alloc_block, dev->alloc_page);
  2677. +
  2678. + dev->alloc_page++;
  2679. +
  2680. + dev->n_free_chunks--;
  2681. +
  2682. + /* If the block is full set the state to full */
  2683. + if (dev->alloc_page >= dev->param.chunks_per_block) {
  2684. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  2685. + dev->alloc_block = -1;
  2686. + }
  2687. +
  2688. + if (block_ptr)
  2689. + *block_ptr = bi;
  2690. +
  2691. + return ret_val;
  2692. + }
  2693. +
  2694. + yaffs_trace(YAFFS_TRACE_ERROR,
  2695. + "!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!");
  2696. +
  2697. + return -1;
  2698. +}
  2699. +
  2700. +static int yaffs_get_erased_chunks(struct yaffs_dev *dev)
  2701. +{
  2702. + int n;
  2703. +
  2704. + n = dev->n_erased_blocks * dev->param.chunks_per_block;
  2705. +
  2706. + if (dev->alloc_block > 0)
  2707. + n += (dev->param.chunks_per_block - dev->alloc_page);
  2708. +
  2709. + return n;
  2710. +
  2711. +}
  2712. +
  2713. +/*
  2714. + * yaffs_skip_rest_of_block() skips over the rest of the allocation block
  2715. + * if we don't want to write to it.
  2716. + */
  2717. +void yaffs_skip_rest_of_block(struct yaffs_dev *dev)
  2718. +{
  2719. + struct yaffs_block_info *bi;
  2720. +
  2721. + if (dev->alloc_block > 0) {
  2722. + bi = yaffs_get_block_info(dev, dev->alloc_block);
  2723. + if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) {
  2724. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  2725. + dev->alloc_block = -1;
  2726. + }
  2727. + }
  2728. +}
  2729. +
  2730. +static int yaffs_write_new_chunk(struct yaffs_dev *dev,
  2731. + const u8 *data,
  2732. + struct yaffs_ext_tags *tags, int use_reserver)
  2733. +{
  2734. + int attempts = 0;
  2735. + int write_ok = 0;
  2736. + int chunk;
  2737. +
  2738. + yaffs2_checkpt_invalidate(dev);
  2739. +
  2740. + do {
  2741. + struct yaffs_block_info *bi = 0;
  2742. + int erased_ok = 0;
  2743. +
  2744. + chunk = yaffs_alloc_chunk(dev, use_reserver, &bi);
  2745. + if (chunk < 0) {
  2746. + /* no space */
  2747. + break;
  2748. + }
  2749. +
  2750. + /* First check this chunk is erased, if it needs
  2751. + * checking. The checking policy (unless forced
  2752. + * always on) is as follows:
  2753. + *
  2754. + * Check the first page we try to write in a block.
  2755. + * If the check passes then we don't need to check any
  2756. + * more. If the check fails, we check again...
  2757. + * If the block has been erased, we don't need to check.
  2758. + *
  2759. + * However, if the block has been prioritised for gc,
  2760. + * then we think there might be something odd about
  2761. + * this block and stop using it.
  2762. + *
  2763. + * Rationale: We should only ever see chunks that have
  2764. + * not been erased if there was a partially written
  2765. + * chunk due to power loss. This checking policy should
  2766. + * catch that case with very few checks and thus save a
  2767. + * lot of checks that are most likely not needed.
  2768. + *
  2769. + * Mods to the above
  2770. + * If an erase check fails or the write fails we skip the
  2771. + * rest of the block.
  2772. + */
  2773. +
  2774. + /* let's give it a try */
  2775. + attempts++;
  2776. +
  2777. + if (dev->param.always_check_erased)
  2778. + bi->skip_erased_check = 0;
  2779. +
  2780. + if (!bi->skip_erased_check) {
  2781. + erased_ok = yaffs_check_chunk_erased(dev, chunk);
  2782. + if (erased_ok != YAFFS_OK) {
  2783. + yaffs_trace(YAFFS_TRACE_ERROR,
  2784. + "**>> yaffs chunk %d was not erased",
  2785. + chunk);
  2786. +
  2787. + /* If not erased, delete this one,
  2788. + * skip rest of block and
  2789. + * try another chunk */
  2790. + yaffs_chunk_del(dev, chunk, 1, __LINE__);
  2791. + yaffs_skip_rest_of_block(dev);
  2792. + continue;
  2793. + }
  2794. + }
  2795. +
  2796. + write_ok = yaffs_wr_chunk_tags_nand(dev, chunk, data, tags);
  2797. +
  2798. + if (!bi->skip_erased_check)
  2799. + write_ok =
  2800. + yaffs_verify_chunk_written(dev, chunk, data, tags);
  2801. +
  2802. + if (write_ok != YAFFS_OK) {
  2803. + /* Clean up aborted write, skip to next block and
  2804. + * try another chunk */
  2805. + yaffs_handle_chunk_wr_error(dev, chunk, erased_ok);
  2806. + continue;
  2807. + }
  2808. +
  2809. + bi->skip_erased_check = 1;
  2810. +
  2811. + /* Copy the data into the robustification buffer */
  2812. + yaffs_handle_chunk_wr_ok(dev, chunk, data, tags);
  2813. +
  2814. + } while (write_ok != YAFFS_OK &&
  2815. + (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
  2816. +
  2817. + if (!write_ok)
  2818. + chunk = -1;
  2819. +
  2820. + if (attempts > 1) {
  2821. + yaffs_trace(YAFFS_TRACE_ERROR,
  2822. + "**>> yaffs write required %d attempts",
  2823. + attempts);
  2824. + dev->n_retried_writes += (attempts - 1);
  2825. + }
  2826. +
  2827. + return chunk;
  2828. +}
  2829. +
  2830. +/*
  2831. + * Block retiring for handling a broken block.
  2832. + */
  2833. +
  2834. +static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block)
  2835. +{
  2836. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
  2837. +
  2838. + yaffs2_checkpt_invalidate(dev);
  2839. +
  2840. + yaffs2_clear_oldest_dirty_seq(dev, bi);
  2841. +
  2842. + if (yaffs_mark_bad(dev, flash_block) != YAFFS_OK) {
  2843. + if (yaffs_erase_block(dev, flash_block) != YAFFS_OK) {
  2844. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2845. + "yaffs: Failed to mark bad and erase block %d",
  2846. + flash_block);
  2847. + } else {
  2848. + struct yaffs_ext_tags tags;
  2849. + int chunk_id =
  2850. + flash_block * dev->param.chunks_per_block;
  2851. +
  2852. + u8 *buffer = yaffs_get_temp_buffer(dev);
  2853. +
  2854. + memset(buffer, 0xff, dev->data_bytes_per_chunk);
  2855. + memset(&tags, 0, sizeof(tags));
  2856. + tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK;
  2857. + if (dev->tagger.write_chunk_tags_fn(dev, chunk_id -
  2858. + dev->chunk_offset,
  2859. + buffer,
  2860. + &tags) != YAFFS_OK)
  2861. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  2862. + "yaffs: Failed to write bad block marker to block %d",
  2863. + flash_block);
  2864. +
  2865. + yaffs_release_temp_buffer(dev, buffer);
  2866. + }
  2867. + }
  2868. +
  2869. + bi->block_state = YAFFS_BLOCK_STATE_DEAD;
  2870. + bi->gc_prioritise = 0;
  2871. + bi->needs_retiring = 0;
  2872. +
  2873. + dev->n_retired_blocks++;
  2874. +}
  2875. +
  2876. +/*---------------- Name handling functions ------------*/
  2877. +
  2878. +static u16 yaffs_calc_name_sum(const YCHAR *name)
  2879. +{
  2880. + u16 sum = 0;
  2881. + u16 i = 1;
  2882. +
  2883. + if (!name)
  2884. + return 0;
  2885. +
  2886. + while ((*name) && i < (YAFFS_MAX_NAME_LENGTH / 2)) {
  2887. +
  2888. + /* 0x1f mask is case insensitive */
  2889. + sum += ((*name) & 0x1f) * i;
  2890. + i++;
  2891. + name++;
  2892. + }
  2893. + return sum;
  2894. +}
  2895. +
  2896. +
  2897. +void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
  2898. +{
  2899. + memset(obj->short_name, 0, sizeof(obj->short_name));
  2900. +
  2901. + if (name && !name[0]) {
  2902. + yaffs_fix_null_name(obj, obj->short_name,
  2903. + YAFFS_SHORT_NAME_LENGTH);
  2904. + name = obj->short_name;
  2905. + } else if (name &&
  2906. + strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <=
  2907. + YAFFS_SHORT_NAME_LENGTH) {
  2908. + strcpy(obj->short_name, name);
  2909. + }
  2910. +
  2911. + obj->sum = yaffs_calc_name_sum(name);
  2912. +}
  2913. +
  2914. +void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
  2915. + const struct yaffs_obj_hdr *oh)
  2916. +{
  2917. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  2918. + YCHAR tmp_name[YAFFS_MAX_NAME_LENGTH + 1];
  2919. + memset(tmp_name, 0, sizeof(tmp_name));
  2920. + yaffs_load_name_from_oh(obj->my_dev, tmp_name, oh->name,
  2921. + YAFFS_MAX_NAME_LENGTH + 1);
  2922. + yaffs_set_obj_name(obj, tmp_name);
  2923. +#else
  2924. + yaffs_set_obj_name(obj, oh->name);
  2925. +#endif
  2926. +}
  2927. +
  2928. +loff_t yaffs_max_file_size(struct yaffs_dev *dev)
  2929. +{
  2930. + if(sizeof(loff_t) < 8)
  2931. + return YAFFS_MAX_FILE_SIZE_32;
  2932. + else
  2933. + return ((loff_t) YAFFS_MAX_CHUNK_ID) * dev->data_bytes_per_chunk;
  2934. +}
  2935. +
  2936. +/*-------------------- TNODES -------------------
  2937. +
  2938. + * List of spare tnodes
  2939. + * The list is hooked together using the first pointer
  2940. + * in the tnode.
  2941. + */
  2942. +
  2943. +struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev)
  2944. +{
  2945. + struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev);
  2946. +
  2947. + if (tn) {
  2948. + memset(tn, 0, dev->tnode_size);
  2949. + dev->n_tnodes++;
  2950. + }
  2951. +
  2952. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  2953. +
  2954. + return tn;
  2955. +}
  2956. +
  2957. +/* FreeTnode frees up a tnode and puts it back on the free list */
  2958. +static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
  2959. +{
  2960. + yaffs_free_raw_tnode(dev, tn);
  2961. + dev->n_tnodes--;
  2962. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  2963. +}
  2964. +
  2965. +static void yaffs_deinit_tnodes_and_objs(struct yaffs_dev *dev)
  2966. +{
  2967. + yaffs_deinit_raw_tnodes_and_objs(dev);
  2968. + dev->n_obj = 0;
  2969. + dev->n_tnodes = 0;
  2970. +}
  2971. +
  2972. +static void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn,
  2973. + unsigned pos, unsigned val)
  2974. +{
  2975. + u32 *map = (u32 *) tn;
  2976. + u32 bit_in_map;
  2977. + u32 bit_in_word;
  2978. + u32 word_in_map;
  2979. + u32 mask;
  2980. +
  2981. + pos &= YAFFS_TNODES_LEVEL0_MASK;
  2982. + val >>= dev->chunk_grp_bits;
  2983. +
  2984. + bit_in_map = pos * dev->tnode_width;
  2985. + word_in_map = bit_in_map / 32;
  2986. + bit_in_word = bit_in_map & (32 - 1);
  2987. +
  2988. + mask = dev->tnode_mask << bit_in_word;
  2989. +
  2990. + map[word_in_map] &= ~mask;
  2991. + map[word_in_map] |= (mask & (val << bit_in_word));
  2992. +
  2993. + if (dev->tnode_width > (32 - bit_in_word)) {
  2994. + bit_in_word = (32 - bit_in_word);
  2995. + word_in_map++;
  2996. + mask =
  2997. + dev->tnode_mask >> bit_in_word;
  2998. + map[word_in_map] &= ~mask;
  2999. + map[word_in_map] |= (mask & (val >> bit_in_word));
  3000. + }
  3001. +}
  3002. +
  3003. +u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
  3004. + unsigned pos)
  3005. +{
  3006. + u32 *map = (u32 *) tn;
  3007. + u32 bit_in_map;
  3008. + u32 bit_in_word;
  3009. + u32 word_in_map;
  3010. + u32 val;
  3011. +
  3012. + pos &= YAFFS_TNODES_LEVEL0_MASK;
  3013. +
  3014. + bit_in_map = pos * dev->tnode_width;
  3015. + word_in_map = bit_in_map / 32;
  3016. + bit_in_word = bit_in_map & (32 - 1);
  3017. +
  3018. + val = map[word_in_map] >> bit_in_word;
  3019. +
  3020. + if (dev->tnode_width > (32 - bit_in_word)) {
  3021. + bit_in_word = (32 - bit_in_word);
  3022. + word_in_map++;
  3023. + val |= (map[word_in_map] << bit_in_word);
  3024. + }
  3025. +
  3026. + val &= dev->tnode_mask;
  3027. + val <<= dev->chunk_grp_bits;
  3028. +
  3029. + return val;
  3030. +}
  3031. +
  3032. +/* ------------------- End of individual tnode manipulation -----------------*/
  3033. +
  3034. +/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
  3035. + * The look up tree is represented by the top tnode and the number of top_level
  3036. + * in the tree. 0 means only the level 0 tnode is in the tree.
  3037. + */
  3038. +
  3039. +/* FindLevel0Tnode finds the level 0 tnode, if one exists. */
  3040. +struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
  3041. + struct yaffs_file_var *file_struct,
  3042. + u32 chunk_id)
  3043. +{
  3044. + struct yaffs_tnode *tn = file_struct->top;
  3045. + u32 i;
  3046. + int required_depth;
  3047. + int level = file_struct->top_level;
  3048. +
  3049. + (void) dev;
  3050. +
  3051. + /* Check sane level and chunk Id */
  3052. + if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL)
  3053. + return NULL;
  3054. +
  3055. + if (chunk_id > YAFFS_MAX_CHUNK_ID)
  3056. + return NULL;
  3057. +
  3058. + /* First check we're tall enough (ie enough top_level) */
  3059. +
  3060. + i = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
  3061. + required_depth = 0;
  3062. + while (i) {
  3063. + i >>= YAFFS_TNODES_INTERNAL_BITS;
  3064. + required_depth++;
  3065. + }
  3066. +
  3067. + if (required_depth > file_struct->top_level)
  3068. + return NULL; /* Not tall enough, so we can't find it */
  3069. +
  3070. + /* Traverse down to level 0 */
  3071. + while (level > 0 && tn) {
  3072. + tn = tn->internal[(chunk_id >>
  3073. + (YAFFS_TNODES_LEVEL0_BITS +
  3074. + (level - 1) *
  3075. + YAFFS_TNODES_INTERNAL_BITS)) &
  3076. + YAFFS_TNODES_INTERNAL_MASK];
  3077. + level--;
  3078. + }
  3079. +
  3080. + return tn;
  3081. +}
  3082. +
  3083. +/* add_find_tnode_0 finds the level 0 tnode if it exists,
  3084. + * otherwise first expands the tree.
  3085. + * This happens in two steps:
  3086. + * 1. If the tree isn't tall enough, then make it taller.
  3087. + * 2. Scan down the tree towards the level 0 tnode adding tnodes if required.
  3088. + *
  3089. + * Used when modifying the tree.
  3090. + *
  3091. + * If the tn argument is NULL, then a fresh tnode will be added otherwise the
  3092. + * specified tn will be plugged into the ttree.
  3093. + */
  3094. +
  3095. +struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
  3096. + struct yaffs_file_var *file_struct,
  3097. + u32 chunk_id,
  3098. + struct yaffs_tnode *passed_tn)
  3099. +{
  3100. + int required_depth;
  3101. + int i;
  3102. + int l;
  3103. + struct yaffs_tnode *tn;
  3104. + u32 x;
  3105. +
  3106. + /* Check sane level and page Id */
  3107. + if (file_struct->top_level < 0 ||
  3108. + file_struct->top_level > YAFFS_TNODES_MAX_LEVEL)
  3109. + return NULL;
  3110. +
  3111. + if (chunk_id > YAFFS_MAX_CHUNK_ID)
  3112. + return NULL;
  3113. +
  3114. + /* First check we're tall enough (ie enough top_level) */
  3115. +
  3116. + x = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
  3117. + required_depth = 0;
  3118. + while (x) {
  3119. + x >>= YAFFS_TNODES_INTERNAL_BITS;
  3120. + required_depth++;
  3121. + }
  3122. +
  3123. + if (required_depth > file_struct->top_level) {
  3124. + /* Not tall enough, gotta make the tree taller */
  3125. + for (i = file_struct->top_level; i < required_depth; i++) {
  3126. +
  3127. + tn = yaffs_get_tnode(dev);
  3128. +
  3129. + if (tn) {
  3130. + tn->internal[0] = file_struct->top;
  3131. + file_struct->top = tn;
  3132. + file_struct->top_level++;
  3133. + } else {
  3134. + yaffs_trace(YAFFS_TRACE_ERROR,
  3135. + "yaffs: no more tnodes");
  3136. + return NULL;
  3137. + }
  3138. + }
  3139. + }
  3140. +
  3141. + /* Traverse down to level 0, adding anything we need */
  3142. +
  3143. + l = file_struct->top_level;
  3144. + tn = file_struct->top;
  3145. +
  3146. + if (l > 0) {
  3147. + while (l > 0 && tn) {
  3148. + x = (chunk_id >>
  3149. + (YAFFS_TNODES_LEVEL0_BITS +
  3150. + (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &
  3151. + YAFFS_TNODES_INTERNAL_MASK;
  3152. +
  3153. + if ((l > 1) && !tn->internal[x]) {
  3154. + /* Add missing non-level-zero tnode */
  3155. + tn->internal[x] = yaffs_get_tnode(dev);
  3156. + if (!tn->internal[x])
  3157. + return NULL;
  3158. + } else if (l == 1) {
  3159. + /* Looking from level 1 at level 0 */
  3160. + if (passed_tn) {
  3161. + /* If we already have one, release it */
  3162. + if (tn->internal[x])
  3163. + yaffs_free_tnode(dev,
  3164. + tn->internal[x]);
  3165. + tn->internal[x] = passed_tn;
  3166. +
  3167. + } else if (!tn->internal[x]) {
  3168. + /* Don't have one, none passed in */
  3169. + tn->internal[x] = yaffs_get_tnode(dev);
  3170. + if (!tn->internal[x])
  3171. + return NULL;
  3172. + }
  3173. + }
  3174. +
  3175. + tn = tn->internal[x];
  3176. + l--;
  3177. + }
  3178. + } else {
  3179. + /* top is level 0 */
  3180. + if (passed_tn) {
  3181. + memcpy(tn, passed_tn,
  3182. + (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8);
  3183. + yaffs_free_tnode(dev, passed_tn);
  3184. + }
  3185. + }
  3186. +
  3187. + return tn;
  3188. +}
  3189. +
  3190. +static int yaffs_tags_match(const struct yaffs_ext_tags *tags, int obj_id,
  3191. + int chunk_obj)
  3192. +{
  3193. + return (tags->chunk_id == chunk_obj &&
  3194. + tags->obj_id == obj_id &&
  3195. + !tags->is_deleted) ? 1 : 0;
  3196. +
  3197. +}
  3198. +
  3199. +static int yaffs_find_chunk_in_group(struct yaffs_dev *dev, int the_chunk,
  3200. + struct yaffs_ext_tags *tags, int obj_id,
  3201. + int inode_chunk)
  3202. +{
  3203. + int j;
  3204. +
  3205. + for (j = 0; the_chunk && j < dev->chunk_grp_size; j++) {
  3206. + if (yaffs_check_chunk_bit
  3207. + (dev, the_chunk / dev->param.chunks_per_block,
  3208. + the_chunk % dev->param.chunks_per_block)) {
  3209. +
  3210. + if (dev->chunk_grp_size == 1)
  3211. + return the_chunk;
  3212. + else {
  3213. + yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
  3214. + tags);
  3215. + if (yaffs_tags_match(tags,
  3216. + obj_id, inode_chunk)) {
  3217. + /* found it; */
  3218. + return the_chunk;
  3219. + }
  3220. + }
  3221. + }
  3222. + the_chunk++;
  3223. + }
  3224. + return -1;
  3225. +}
  3226. +
  3227. +int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  3228. + struct yaffs_ext_tags *tags)
  3229. +{
  3230. + /*Get the Tnode, then get the level 0 offset chunk offset */
  3231. + struct yaffs_tnode *tn;
  3232. + int the_chunk = -1;
  3233. + struct yaffs_ext_tags local_tags;
  3234. + int ret_val = -1;
  3235. + struct yaffs_dev *dev = in->my_dev;
  3236. +
  3237. + if (!tags) {
  3238. + /* Passed a NULL, so use our own tags space */
  3239. + tags = &local_tags;
  3240. + }
  3241. +
  3242. + tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
  3243. +
  3244. + if (!tn)
  3245. + return ret_val;
  3246. +
  3247. + the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
  3248. +
  3249. + ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
  3250. + inode_chunk);
  3251. + return ret_val;
  3252. +}
  3253. +
  3254. +static int yaffs_find_del_file_chunk(struct yaffs_obj *in, int inode_chunk,
  3255. + struct yaffs_ext_tags *tags)
  3256. +{
  3257. + /* Get the Tnode, then get the level 0 offset chunk offset */
  3258. + struct yaffs_tnode *tn;
  3259. + int the_chunk = -1;
  3260. + struct yaffs_ext_tags local_tags;
  3261. + struct yaffs_dev *dev = in->my_dev;
  3262. + int ret_val = -1;
  3263. +
  3264. + if (!tags) {
  3265. + /* Passed a NULL, so use our own tags space */
  3266. + tags = &local_tags;
  3267. + }
  3268. +
  3269. + tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
  3270. +
  3271. + if (!tn)
  3272. + return ret_val;
  3273. +
  3274. + the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
  3275. +
  3276. + ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
  3277. + inode_chunk);
  3278. +
  3279. + /* Delete the entry in the filestructure (if found) */
  3280. + if (ret_val != -1)
  3281. + yaffs_load_tnode_0(dev, tn, inode_chunk, 0);
  3282. +
  3283. + return ret_val;
  3284. +}
  3285. +
  3286. +int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  3287. + int nand_chunk, int in_scan)
  3288. +{
  3289. + /* NB in_scan is zero unless scanning.
  3290. + * For forward scanning, in_scan is > 0;
  3291. + * for backward scanning in_scan is < 0
  3292. + *
  3293. + * nand_chunk = 0 is a dummy insert to make sure the tnodes are there.
  3294. + */
  3295. +
  3296. + struct yaffs_tnode *tn;
  3297. + struct yaffs_dev *dev = in->my_dev;
  3298. + int existing_cunk;
  3299. + struct yaffs_ext_tags existing_tags;
  3300. + struct yaffs_ext_tags new_tags;
  3301. + unsigned existing_serial, new_serial;
  3302. +
  3303. + if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) {
  3304. + /* Just ignore an attempt at putting a chunk into a non-file
  3305. + * during scanning.
  3306. + * If it is not during Scanning then something went wrong!
  3307. + */
  3308. + if (!in_scan) {
  3309. + yaffs_trace(YAFFS_TRACE_ERROR,
  3310. + "yaffs tragedy:attempt to put data chunk into a non-file"
  3311. + );
  3312. + BUG();
  3313. + }
  3314. +
  3315. + yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
  3316. + return YAFFS_OK;
  3317. + }
  3318. +
  3319. + tn = yaffs_add_find_tnode_0(dev,
  3320. + &in->variant.file_variant,
  3321. + inode_chunk, NULL);
  3322. + if (!tn)
  3323. + return YAFFS_FAIL;
  3324. +
  3325. + if (!nand_chunk)
  3326. + /* Dummy insert, bail now */
  3327. + return YAFFS_OK;
  3328. +
  3329. + existing_cunk = yaffs_get_group_base(dev, tn, inode_chunk);
  3330. +
  3331. + if (in_scan != 0) {
  3332. + /* If we're scanning then we need to test for duplicates
  3333. + * NB This does not need to be efficient since it should only
  3334. + * happen when the power fails during a write, then only one
  3335. + * chunk should ever be affected.
  3336. + *
  3337. + * Correction for YAFFS2: This could happen quite a lot and we
  3338. + * need to think about efficiency! TODO
  3339. + * Update: For backward scanning we don't need to re-read tags
  3340. + * so this is quite cheap.
  3341. + */
  3342. +
  3343. + if (existing_cunk > 0) {
  3344. + /* NB Right now existing chunk will not be real
  3345. + * chunk_id if the chunk group size > 1
  3346. + * thus we have to do a FindChunkInFile to get the
  3347. + * real chunk id.
  3348. + *
  3349. + * We have a duplicate now we need to decide which
  3350. + * one to use:
  3351. + *
  3352. + * Backwards scanning YAFFS2: The old one is what
  3353. + * we use, dump the new one.
  3354. + * YAFFS1: Get both sets of tags and compare serial
  3355. + * numbers.
  3356. + */
  3357. +
  3358. + if (in_scan > 0) {
  3359. + /* Only do this for forward scanning */
  3360. + yaffs_rd_chunk_tags_nand(dev,
  3361. + nand_chunk,
  3362. + NULL, &new_tags);
  3363. +
  3364. + /* Do a proper find */
  3365. + existing_cunk =
  3366. + yaffs_find_chunk_in_file(in, inode_chunk,
  3367. + &existing_tags);
  3368. + }
  3369. +
  3370. + if (existing_cunk <= 0) {
  3371. + /*Hoosterman - how did this happen? */
  3372. +
  3373. + yaffs_trace(YAFFS_TRACE_ERROR,
  3374. + "yaffs tragedy: existing chunk < 0 in scan"
  3375. + );
  3376. +
  3377. + }
  3378. +
  3379. + /* NB The deleted flags should be false, otherwise
  3380. + * the chunks will not be loaded during a scan
  3381. + */
  3382. +
  3383. + if (in_scan > 0) {
  3384. + new_serial = new_tags.serial_number;
  3385. + existing_serial = existing_tags.serial_number;
  3386. + }
  3387. +
  3388. + if ((in_scan > 0) &&
  3389. + (existing_cunk <= 0 ||
  3390. + ((existing_serial + 1) & 3) == new_serial)) {
  3391. + /* Forward scanning.
  3392. + * Use new
  3393. + * Delete the old one and drop through to
  3394. + * update the tnode
  3395. + */
  3396. + yaffs_chunk_del(dev, existing_cunk, 1,
  3397. + __LINE__);
  3398. + } else {
  3399. + /* Backward scanning or we want to use the
  3400. + * existing one
  3401. + * Delete the new one and return early so that
  3402. + * the tnode isn't changed
  3403. + */
  3404. + yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
  3405. + return YAFFS_OK;
  3406. + }
  3407. + }
  3408. +
  3409. + }
  3410. +
  3411. + if (existing_cunk == 0)
  3412. + in->n_data_chunks++;
  3413. +
  3414. + yaffs_load_tnode_0(dev, tn, inode_chunk, nand_chunk);
  3415. +
  3416. + return YAFFS_OK;
  3417. +}
  3418. +
  3419. +static void yaffs_soft_del_chunk(struct yaffs_dev *dev, int chunk)
  3420. +{
  3421. + struct yaffs_block_info *the_block;
  3422. + unsigned block_no;
  3423. +
  3424. + yaffs_trace(YAFFS_TRACE_DELETION, "soft delete chunk %d", chunk);
  3425. +
  3426. + block_no = chunk / dev->param.chunks_per_block;
  3427. + the_block = yaffs_get_block_info(dev, block_no);
  3428. + if (the_block) {
  3429. + the_block->soft_del_pages++;
  3430. + dev->n_free_chunks++;
  3431. + yaffs2_update_oldest_dirty_seq(dev, block_no, the_block);
  3432. + }
  3433. +}
  3434. +
  3435. +/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all
  3436. + * the chunks in the file.
  3437. + * All soft deleting does is increment the block's softdelete count and pulls
  3438. + * the chunk out of the tnode.
  3439. + * Thus, essentially this is the same as DeleteWorker except that the chunks
  3440. + * are soft deleted.
  3441. + */
  3442. +
  3443. +static int yaffs_soft_del_worker(struct yaffs_obj *in, struct yaffs_tnode *tn,
  3444. + u32 level, int chunk_offset)
  3445. +{
  3446. + int i;
  3447. + int the_chunk;
  3448. + int all_done = 1;
  3449. + struct yaffs_dev *dev = in->my_dev;
  3450. +
  3451. + if (!tn)
  3452. + return 1;
  3453. +
  3454. + if (level > 0) {
  3455. + for (i = YAFFS_NTNODES_INTERNAL - 1;
  3456. + all_done && i >= 0;
  3457. + i--) {
  3458. + if (tn->internal[i]) {
  3459. + all_done =
  3460. + yaffs_soft_del_worker(in,
  3461. + tn->internal[i],
  3462. + level - 1,
  3463. + (chunk_offset <<
  3464. + YAFFS_TNODES_INTERNAL_BITS)
  3465. + + i);
  3466. + if (all_done) {
  3467. + yaffs_free_tnode(dev,
  3468. + tn->internal[i]);
  3469. + tn->internal[i] = NULL;
  3470. + } else {
  3471. + /* Can this happen? */
  3472. + }
  3473. + }
  3474. + }
  3475. + return (all_done) ? 1 : 0;
  3476. + }
  3477. +
  3478. + /* level 0 */
  3479. + for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
  3480. + the_chunk = yaffs_get_group_base(dev, tn, i);
  3481. + if (the_chunk) {
  3482. + yaffs_soft_del_chunk(dev, the_chunk);
  3483. + yaffs_load_tnode_0(dev, tn, i, 0);
  3484. + }
  3485. + }
  3486. + return 1;
  3487. +}
  3488. +
  3489. +static void yaffs_remove_obj_from_dir(struct yaffs_obj *obj)
  3490. +{
  3491. + struct yaffs_dev *dev = obj->my_dev;
  3492. + struct yaffs_obj *parent;
  3493. +
  3494. + yaffs_verify_obj_in_dir(obj);
  3495. + parent = obj->parent;
  3496. +
  3497. + yaffs_verify_dir(parent);
  3498. +
  3499. + if (dev && dev->param.remove_obj_fn)
  3500. + dev->param.remove_obj_fn(obj);
  3501. +
  3502. + list_del_init(&obj->siblings);
  3503. + obj->parent = NULL;
  3504. +
  3505. + yaffs_verify_dir(parent);
  3506. +}
  3507. +
  3508. +void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj)
  3509. +{
  3510. + if (!directory) {
  3511. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  3512. + "tragedy: Trying to add an object to a null pointer directory"
  3513. + );
  3514. + BUG();
  3515. + return;
  3516. + }
  3517. + if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  3518. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  3519. + "tragedy: Trying to add an object to a non-directory"
  3520. + );
  3521. + BUG();
  3522. + }
  3523. +
  3524. + if (obj->siblings.prev == NULL) {
  3525. + /* Not initialised */
  3526. + BUG();
  3527. + }
  3528. +
  3529. + yaffs_verify_dir(directory);
  3530. +
  3531. + yaffs_remove_obj_from_dir(obj);
  3532. +
  3533. + /* Now add it */
  3534. + list_add(&obj->siblings, &directory->variant.dir_variant.children);
  3535. + obj->parent = directory;
  3536. +
  3537. + if (directory == obj->my_dev->unlinked_dir
  3538. + || directory == obj->my_dev->del_dir) {
  3539. + obj->unlinked = 1;
  3540. + obj->my_dev->n_unlinked_files++;
  3541. + obj->rename_allowed = 0;
  3542. + }
  3543. +
  3544. + yaffs_verify_dir(directory);
  3545. + yaffs_verify_obj_in_dir(obj);
  3546. +}
  3547. +
  3548. +static int yaffs_change_obj_name(struct yaffs_obj *obj,
  3549. + struct yaffs_obj *new_dir,
  3550. + const YCHAR *new_name, int force, int shadows)
  3551. +{
  3552. + int unlink_op;
  3553. + int del_op;
  3554. + struct yaffs_obj *existing_target;
  3555. +
  3556. + if (new_dir == NULL)
  3557. + new_dir = obj->parent; /* use the old directory */
  3558. +
  3559. + if (new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  3560. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  3561. + "tragedy: yaffs_change_obj_name: new_dir is not a directory"
  3562. + );
  3563. + BUG();
  3564. + }
  3565. +
  3566. + unlink_op = (new_dir == obj->my_dev->unlinked_dir);
  3567. + del_op = (new_dir == obj->my_dev->del_dir);
  3568. +
  3569. + existing_target = yaffs_find_by_name(new_dir, new_name);
  3570. +
  3571. + /* If the object is a file going into the unlinked directory,
  3572. + * then it is OK to just stuff it in since duplicate names are OK.
  3573. + * else only proceed if the new name does not exist and we're putting
  3574. + * it into a directory.
  3575. + */
  3576. + if (!(unlink_op || del_op || force ||
  3577. + shadows > 0 || !existing_target) ||
  3578. + new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
  3579. + return YAFFS_FAIL;
  3580. +
  3581. + yaffs_set_obj_name(obj, new_name);
  3582. + obj->dirty = 1;
  3583. + yaffs_add_obj_to_dir(new_dir, obj);
  3584. +
  3585. + if (unlink_op)
  3586. + obj->unlinked = 1;
  3587. +
  3588. + /* If it is a deletion then we mark it as a shrink for gc */
  3589. + if (yaffs_update_oh(obj, new_name, 0, del_op, shadows, NULL) >= 0)
  3590. + return YAFFS_OK;
  3591. +
  3592. + return YAFFS_FAIL;
  3593. +}
  3594. +
  3595. +/*------------------------ Short Operations Cache ------------------------------
  3596. + * In many situations where there is no high level buffering a lot of
  3597. + * reads might be short sequential reads, and a lot of writes may be short
  3598. + * sequential writes. eg. scanning/writing a jpeg file.
  3599. + * In these cases, a short read/write cache can provide a huge perfomance
  3600. + * benefit with dumb-as-a-rock code.
  3601. + * In Linux, the page cache provides read buffering and the short op cache
  3602. + * provides write buffering.
  3603. + *
  3604. + * There are a small number (~10) of cache chunks per device so that we don't
  3605. + * need a very intelligent search.
  3606. + */
  3607. +
  3608. +static int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
  3609. +{
  3610. + struct yaffs_dev *dev = obj->my_dev;
  3611. + int i;
  3612. + struct yaffs_cache *cache;
  3613. + int n_caches = obj->my_dev->param.n_caches;
  3614. +
  3615. + for (i = 0; i < n_caches; i++) {
  3616. + cache = &dev->cache[i];
  3617. + if (cache->object == obj && cache->dirty)
  3618. + return 1;
  3619. + }
  3620. +
  3621. + return 0;
  3622. +}
  3623. +
  3624. +static void yaffs_flush_file_cache(struct yaffs_obj *obj)
  3625. +{
  3626. + struct yaffs_dev *dev = obj->my_dev;
  3627. + int lowest = -99; /* Stop compiler whining. */
  3628. + int i;
  3629. + struct yaffs_cache *cache;
  3630. + int chunk_written = 0;
  3631. + int n_caches = obj->my_dev->param.n_caches;
  3632. +
  3633. + if (n_caches < 1)
  3634. + return;
  3635. + do {
  3636. + cache = NULL;
  3637. +
  3638. + /* Find the lowest dirty chunk for this object */
  3639. + for (i = 0; i < n_caches; i++) {
  3640. + if (dev->cache[i].object == obj &&
  3641. + dev->cache[i].dirty) {
  3642. + if (!cache ||
  3643. + dev->cache[i].chunk_id < lowest) {
  3644. + cache = &dev->cache[i];
  3645. + lowest = cache->chunk_id;
  3646. + }
  3647. + }
  3648. + }
  3649. +
  3650. + if (cache && !cache->locked) {
  3651. + /* Write it out and free it up */
  3652. + chunk_written =
  3653. + yaffs_wr_data_obj(cache->object,
  3654. + cache->chunk_id,
  3655. + cache->data,
  3656. + cache->n_bytes, 1);
  3657. + cache->dirty = 0;
  3658. + cache->object = NULL;
  3659. + }
  3660. + } while (cache && chunk_written > 0);
  3661. +
  3662. + if (cache)
  3663. + /* Hoosterman, disk full while writing cache out. */
  3664. + yaffs_trace(YAFFS_TRACE_ERROR,
  3665. + "yaffs tragedy: no space during cache write");
  3666. +}
  3667. +
  3668. +/*yaffs_flush_whole_cache(dev)
  3669. + *
  3670. + *
  3671. + */
  3672. +
  3673. +void yaffs_flush_whole_cache(struct yaffs_dev *dev)
  3674. +{
  3675. + struct yaffs_obj *obj;
  3676. + int n_caches = dev->param.n_caches;
  3677. + int i;
  3678. +
  3679. + /* Find a dirty object in the cache and flush it...
  3680. + * until there are no further dirty objects.
  3681. + */
  3682. + do {
  3683. + obj = NULL;
  3684. + for (i = 0; i < n_caches && !obj; i++) {
  3685. + if (dev->cache[i].object && dev->cache[i].dirty)
  3686. + obj = dev->cache[i].object;
  3687. + }
  3688. + if (obj)
  3689. + yaffs_flush_file_cache(obj);
  3690. + } while (obj);
  3691. +
  3692. +}
  3693. +
  3694. +/* Grab us a cache chunk for use.
  3695. + * First look for an empty one.
  3696. + * Then look for the least recently used non-dirty one.
  3697. + * Then look for the least recently used dirty one...., flush and look again.
  3698. + */
  3699. +static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
  3700. +{
  3701. + int i;
  3702. +
  3703. + if (dev->param.n_caches > 0) {
  3704. + for (i = 0; i < dev->param.n_caches; i++) {
  3705. + if (!dev->cache[i].object)
  3706. + return &dev->cache[i];
  3707. + }
  3708. + }
  3709. + return NULL;
  3710. +}
  3711. +
  3712. +static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
  3713. +{
  3714. + struct yaffs_cache *cache;
  3715. + struct yaffs_obj *the_obj;
  3716. + int usage;
  3717. + int i;
  3718. + int pushout;
  3719. +
  3720. + if (dev->param.n_caches < 1)
  3721. + return NULL;
  3722. +
  3723. + /* Try find a non-dirty one... */
  3724. +
  3725. + cache = yaffs_grab_chunk_worker(dev);
  3726. +
  3727. + if (!cache) {
  3728. + /* They were all dirty, find the LRU object and flush
  3729. + * its cache, then find again.
  3730. + * NB what's here is not very accurate,
  3731. + * we actually flush the object with the LRU chunk.
  3732. + */
  3733. +
  3734. + /* With locking we can't assume we can use entry zero,
  3735. + * Set the_obj to a valid pointer for Coverity. */
  3736. + the_obj = dev->cache[0].object;
  3737. + usage = -1;
  3738. + cache = NULL;
  3739. + pushout = -1;
  3740. +
  3741. + for (i = 0; i < dev->param.n_caches; i++) {
  3742. + if (dev->cache[i].object &&
  3743. + !dev->cache[i].locked &&
  3744. + (dev->cache[i].last_use < usage ||
  3745. + !cache)) {
  3746. + usage = dev->cache[i].last_use;
  3747. + the_obj = dev->cache[i].object;
  3748. + cache = &dev->cache[i];
  3749. + pushout = i;
  3750. + }
  3751. + }
  3752. +
  3753. + if (!cache || cache->dirty) {
  3754. + /* Flush and try again */
  3755. + yaffs_flush_file_cache(the_obj);
  3756. + cache = yaffs_grab_chunk_worker(dev);
  3757. + }
  3758. + }
  3759. + return cache;
  3760. +}
  3761. +
  3762. +/* Find a cached chunk */
  3763. +static struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
  3764. + int chunk_id)
  3765. +{
  3766. + struct yaffs_dev *dev = obj->my_dev;
  3767. + int i;
  3768. +
  3769. + if (dev->param.n_caches < 1)
  3770. + return NULL;
  3771. +
  3772. + for (i = 0; i < dev->param.n_caches; i++) {
  3773. + if (dev->cache[i].object == obj &&
  3774. + dev->cache[i].chunk_id == chunk_id) {
  3775. + dev->cache_hits++;
  3776. +
  3777. + return &dev->cache[i];
  3778. + }
  3779. + }
  3780. + return NULL;
  3781. +}
  3782. +
  3783. +/* Mark the chunk for the least recently used algorithym */
  3784. +static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
  3785. + int is_write)
  3786. +{
  3787. + int i;
  3788. +
  3789. + if (dev->param.n_caches < 1)
  3790. + return;
  3791. +
  3792. + if (dev->cache_last_use < 0 ||
  3793. + dev->cache_last_use > 100000000) {
  3794. + /* Reset the cache usages */
  3795. + for (i = 1; i < dev->param.n_caches; i++)
  3796. + dev->cache[i].last_use = 0;
  3797. +
  3798. + dev->cache_last_use = 0;
  3799. + }
  3800. + dev->cache_last_use++;
  3801. + cache->last_use = dev->cache_last_use;
  3802. +
  3803. + if (is_write)
  3804. + cache->dirty = 1;
  3805. +}
  3806. +
  3807. +/* Invalidate a single cache page.
  3808. + * Do this when a whole page gets written,
  3809. + * ie the short cache for this page is no longer valid.
  3810. + */
  3811. +static void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id)
  3812. +{
  3813. + struct yaffs_cache *cache;
  3814. +
  3815. + if (object->my_dev->param.n_caches > 0) {
  3816. + cache = yaffs_find_chunk_cache(object, chunk_id);
  3817. +
  3818. + if (cache)
  3819. + cache->object = NULL;
  3820. + }
  3821. +}
  3822. +
  3823. +/* Invalidate all the cache pages associated with this object
  3824. + * Do this whenever ther file is deleted or resized.
  3825. + */
  3826. +static void yaffs_invalidate_whole_cache(struct yaffs_obj *in)
  3827. +{
  3828. + int i;
  3829. + struct yaffs_dev *dev = in->my_dev;
  3830. +
  3831. + if (dev->param.n_caches > 0) {
  3832. + /* Invalidate it. */
  3833. + for (i = 0; i < dev->param.n_caches; i++) {
  3834. + if (dev->cache[i].object == in)
  3835. + dev->cache[i].object = NULL;
  3836. + }
  3837. + }
  3838. +}
  3839. +
  3840. +static void yaffs_unhash_obj(struct yaffs_obj *obj)
  3841. +{
  3842. + int bucket;
  3843. + struct yaffs_dev *dev = obj->my_dev;
  3844. +
  3845. + /* If it is still linked into the bucket list, free from the list */
  3846. + if (!list_empty(&obj->hash_link)) {
  3847. + list_del_init(&obj->hash_link);
  3848. + bucket = yaffs_hash_fn(obj->obj_id);
  3849. + dev->obj_bucket[bucket].count--;
  3850. + }
  3851. +}
  3852. +
  3853. +/* FreeObject frees up a Object and puts it back on the free list */
  3854. +static void yaffs_free_obj(struct yaffs_obj *obj)
  3855. +{
  3856. + struct yaffs_dev *dev;
  3857. +
  3858. + if (!obj) {
  3859. + BUG();
  3860. + return;
  3861. + }
  3862. + dev = obj->my_dev;
  3863. + yaffs_trace(YAFFS_TRACE_OS, "FreeObject %p inode %p",
  3864. + obj, obj->my_inode);
  3865. + if (obj->parent)
  3866. + BUG();
  3867. + if (!list_empty(&obj->siblings))
  3868. + BUG();
  3869. +
  3870. + if (obj->my_inode) {
  3871. + /* We're still hooked up to a cached inode.
  3872. + * Don't delete now, but mark for later deletion
  3873. + */
  3874. + obj->defered_free = 1;
  3875. + return;
  3876. + }
  3877. +
  3878. + yaffs_unhash_obj(obj);
  3879. +
  3880. + yaffs_free_raw_obj(dev, obj);
  3881. + dev->n_obj--;
  3882. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  3883. +}
  3884. +
  3885. +void yaffs_handle_defered_free(struct yaffs_obj *obj)
  3886. +{
  3887. + if (obj->defered_free)
  3888. + yaffs_free_obj(obj);
  3889. +}
  3890. +
  3891. +static int yaffs_generic_obj_del(struct yaffs_obj *in)
  3892. +{
  3893. + /* Iinvalidate the file's data in the cache, without flushing. */
  3894. + yaffs_invalidate_whole_cache(in);
  3895. +
  3896. + if (in->my_dev->param.is_yaffs2 && in->parent != in->my_dev->del_dir) {
  3897. + /* Move to unlinked directory so we have a deletion record */
  3898. + yaffs_change_obj_name(in, in->my_dev->del_dir, _Y("deleted"), 0,
  3899. + 0);
  3900. + }
  3901. +
  3902. + yaffs_remove_obj_from_dir(in);
  3903. + yaffs_chunk_del(in->my_dev, in->hdr_chunk, 1, __LINE__);
  3904. + in->hdr_chunk = 0;
  3905. +
  3906. + yaffs_free_obj(in);
  3907. + return YAFFS_OK;
  3908. +
  3909. +}
  3910. +
  3911. +static void yaffs_soft_del_file(struct yaffs_obj *obj)
  3912. +{
  3913. + if (!obj->deleted ||
  3914. + obj->variant_type != YAFFS_OBJECT_TYPE_FILE ||
  3915. + obj->soft_del)
  3916. + return;
  3917. +
  3918. + if (obj->n_data_chunks <= 0) {
  3919. + /* Empty file with no duplicate object headers,
  3920. + * just delete it immediately */
  3921. + yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
  3922. + obj->variant.file_variant.top = NULL;
  3923. + yaffs_trace(YAFFS_TRACE_TRACING,
  3924. + "yaffs: Deleting empty file %d",
  3925. + obj->obj_id);
  3926. + yaffs_generic_obj_del(obj);
  3927. + } else {
  3928. + yaffs_soft_del_worker(obj,
  3929. + obj->variant.file_variant.top,
  3930. + obj->variant.
  3931. + file_variant.top_level, 0);
  3932. + obj->soft_del = 1;
  3933. + }
  3934. +}
  3935. +
  3936. +/* Pruning removes any part of the file structure tree that is beyond the
  3937. + * bounds of the file (ie that does not point to chunks).
  3938. + *
  3939. + * A file should only get pruned when its size is reduced.
  3940. + *
  3941. + * Before pruning, the chunks must be pulled from the tree and the
  3942. + * level 0 tnode entries must be zeroed out.
  3943. + * Could also use this for file deletion, but that's probably better handled
  3944. + * by a special case.
  3945. + *
  3946. + * This function is recursive. For levels > 0 the function is called again on
  3947. + * any sub-tree. For level == 0 we just check if the sub-tree has data.
  3948. + * If there is no data in a subtree then it is pruned.
  3949. + */
  3950. +
  3951. +static struct yaffs_tnode *yaffs_prune_worker(struct yaffs_dev *dev,
  3952. + struct yaffs_tnode *tn, u32 level,
  3953. + int del0)
  3954. +{
  3955. + int i;
  3956. + int has_data;
  3957. +
  3958. + if (!tn)
  3959. + return tn;
  3960. +
  3961. + has_data = 0;
  3962. +
  3963. + if (level > 0) {
  3964. + for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) {
  3965. + if (tn->internal[i]) {
  3966. + tn->internal[i] =
  3967. + yaffs_prune_worker(dev,
  3968. + tn->internal[i],
  3969. + level - 1,
  3970. + (i == 0) ? del0 : 1);
  3971. + }
  3972. +
  3973. + if (tn->internal[i])
  3974. + has_data++;
  3975. + }
  3976. + } else {
  3977. + int tnode_size_u32 = dev->tnode_size / sizeof(u32);
  3978. + u32 *map = (u32 *) tn;
  3979. +
  3980. + for (i = 0; !has_data && i < tnode_size_u32; i++) {
  3981. + if (map[i])
  3982. + has_data++;
  3983. + }
  3984. + }
  3985. +
  3986. + if (has_data == 0 && del0) {
  3987. + /* Free and return NULL */
  3988. + yaffs_free_tnode(dev, tn);
  3989. + tn = NULL;
  3990. + }
  3991. + return tn;
  3992. +}
  3993. +
  3994. +static int yaffs_prune_tree(struct yaffs_dev *dev,
  3995. + struct yaffs_file_var *file_struct)
  3996. +{
  3997. + int i;
  3998. + int has_data;
  3999. + int done = 0;
  4000. + struct yaffs_tnode *tn;
  4001. +
  4002. + if (file_struct->top_level < 1)
  4003. + return YAFFS_OK;
  4004. +
  4005. + file_struct->top =
  4006. + yaffs_prune_worker(dev, file_struct->top, file_struct->top_level, 0);
  4007. +
  4008. + /* Now we have a tree with all the non-zero branches NULL but
  4009. + * the height is the same as it was.
  4010. + * Let's see if we can trim internal tnodes to shorten the tree.
  4011. + * We can do this if only the 0th element in the tnode is in use
  4012. + * (ie all the non-zero are NULL)
  4013. + */
  4014. +
  4015. + while (file_struct->top_level && !done) {
  4016. + tn = file_struct->top;
  4017. +
  4018. + has_data = 0;
  4019. + for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) {
  4020. + if (tn->internal[i])
  4021. + has_data++;
  4022. + }
  4023. +
  4024. + if (!has_data) {
  4025. + file_struct->top = tn->internal[0];
  4026. + file_struct->top_level--;
  4027. + yaffs_free_tnode(dev, tn);
  4028. + } else {
  4029. + done = 1;
  4030. + }
  4031. + }
  4032. +
  4033. + return YAFFS_OK;
  4034. +}
  4035. +
  4036. +/*-------------------- End of File Structure functions.-------------------*/
  4037. +
  4038. +/* alloc_empty_obj gets us a clean Object.*/
  4039. +static struct yaffs_obj *yaffs_alloc_empty_obj(struct yaffs_dev *dev)
  4040. +{
  4041. + struct yaffs_obj *obj = yaffs_alloc_raw_obj(dev);
  4042. +
  4043. + if (!obj)
  4044. + return obj;
  4045. +
  4046. + dev->n_obj++;
  4047. +
  4048. + /* Now sweeten it up... */
  4049. +
  4050. + memset(obj, 0, sizeof(struct yaffs_obj));
  4051. + obj->being_created = 1;
  4052. +
  4053. + obj->my_dev = dev;
  4054. + obj->hdr_chunk = 0;
  4055. + obj->variant_type = YAFFS_OBJECT_TYPE_UNKNOWN;
  4056. + INIT_LIST_HEAD(&(obj->hard_links));
  4057. + INIT_LIST_HEAD(&(obj->hash_link));
  4058. + INIT_LIST_HEAD(&obj->siblings);
  4059. +
  4060. + /* Now make the directory sane */
  4061. + if (dev->root_dir) {
  4062. + obj->parent = dev->root_dir;
  4063. + list_add(&(obj->siblings),
  4064. + &dev->root_dir->variant.dir_variant.children);
  4065. + }
  4066. +
  4067. + /* Add it to the lost and found directory.
  4068. + * NB Can't put root or lost-n-found in lost-n-found so
  4069. + * check if lost-n-found exists first
  4070. + */
  4071. + if (dev->lost_n_found)
  4072. + yaffs_add_obj_to_dir(dev->lost_n_found, obj);
  4073. +
  4074. + obj->being_created = 0;
  4075. +
  4076. + dev->checkpoint_blocks_required = 0; /* force recalculation */
  4077. +
  4078. + return obj;
  4079. +}
  4080. +
  4081. +static int yaffs_find_nice_bucket(struct yaffs_dev *dev)
  4082. +{
  4083. + int i;
  4084. + int l = 999;
  4085. + int lowest = 999999;
  4086. +
  4087. + /* Search for the shortest list or one that
  4088. + * isn't too long.
  4089. + */
  4090. +
  4091. + for (i = 0; i < 10 && lowest > 4; i++) {
  4092. + dev->bucket_finder++;
  4093. + dev->bucket_finder %= YAFFS_NOBJECT_BUCKETS;
  4094. + if (dev->obj_bucket[dev->bucket_finder].count < lowest) {
  4095. + lowest = dev->obj_bucket[dev->bucket_finder].count;
  4096. + l = dev->bucket_finder;
  4097. + }
  4098. + }
  4099. +
  4100. + return l;
  4101. +}
  4102. +
  4103. +static int yaffs_new_obj_id(struct yaffs_dev *dev)
  4104. +{
  4105. + int bucket = yaffs_find_nice_bucket(dev);
  4106. + int found = 0;
  4107. + struct list_head *i;
  4108. + u32 n = (u32) bucket;
  4109. +
  4110. + /* Now find an object value that has not already been taken
  4111. + * by scanning the list.
  4112. + */
  4113. +
  4114. + while (!found) {
  4115. + found = 1;
  4116. + n += YAFFS_NOBJECT_BUCKETS;
  4117. + if (1 || dev->obj_bucket[bucket].count > 0) {
  4118. + list_for_each(i, &dev->obj_bucket[bucket].list) {
  4119. + /* If there is already one in the list */
  4120. + if (i && list_entry(i, struct yaffs_obj,
  4121. + hash_link)->obj_id == n) {
  4122. + found = 0;
  4123. + }
  4124. + }
  4125. + }
  4126. + }
  4127. + return n;
  4128. +}
  4129. +
  4130. +static void yaffs_hash_obj(struct yaffs_obj *in)
  4131. +{
  4132. + int bucket = yaffs_hash_fn(in->obj_id);
  4133. + struct yaffs_dev *dev = in->my_dev;
  4134. +
  4135. + list_add(&in->hash_link, &dev->obj_bucket[bucket].list);
  4136. + dev->obj_bucket[bucket].count++;
  4137. +}
  4138. +
  4139. +struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number)
  4140. +{
  4141. + int bucket = yaffs_hash_fn(number);
  4142. + struct list_head *i;
  4143. + struct yaffs_obj *in;
  4144. +
  4145. + list_for_each(i, &dev->obj_bucket[bucket].list) {
  4146. + /* Look if it is in the list */
  4147. + in = list_entry(i, struct yaffs_obj, hash_link);
  4148. + if (in->obj_id == number) {
  4149. + /* Don't show if it is defered free */
  4150. + if (in->defered_free)
  4151. + return NULL;
  4152. + return in;
  4153. + }
  4154. + }
  4155. +
  4156. + return NULL;
  4157. +}
  4158. +
  4159. +static struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number,
  4160. + enum yaffs_obj_type type)
  4161. +{
  4162. + struct yaffs_obj *the_obj = NULL;
  4163. + struct yaffs_tnode *tn = NULL;
  4164. +
  4165. + if (number < 0)
  4166. + number = yaffs_new_obj_id(dev);
  4167. +
  4168. + if (type == YAFFS_OBJECT_TYPE_FILE) {
  4169. + tn = yaffs_get_tnode(dev);
  4170. + if (!tn)
  4171. + return NULL;
  4172. + }
  4173. +
  4174. + the_obj = yaffs_alloc_empty_obj(dev);
  4175. + if (!the_obj) {
  4176. + if (tn)
  4177. + yaffs_free_tnode(dev, tn);
  4178. + return NULL;
  4179. + }
  4180. +
  4181. + the_obj->fake = 0;
  4182. + the_obj->rename_allowed = 1;
  4183. + the_obj->unlink_allowed = 1;
  4184. + the_obj->obj_id = number;
  4185. + yaffs_hash_obj(the_obj);
  4186. + the_obj->variant_type = type;
  4187. + yaffs_load_current_time(the_obj, 1, 1);
  4188. +
  4189. + switch (type) {
  4190. + case YAFFS_OBJECT_TYPE_FILE:
  4191. + the_obj->variant.file_variant.file_size = 0;
  4192. + the_obj->variant.file_variant.scanned_size = 0;
  4193. + the_obj->variant.file_variant.shrink_size =
  4194. + yaffs_max_file_size(dev);
  4195. + the_obj->variant.file_variant.top_level = 0;
  4196. + the_obj->variant.file_variant.top = tn;
  4197. + break;
  4198. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  4199. + INIT_LIST_HEAD(&the_obj->variant.dir_variant.children);
  4200. + INIT_LIST_HEAD(&the_obj->variant.dir_variant.dirty);
  4201. + break;
  4202. + case YAFFS_OBJECT_TYPE_SYMLINK:
  4203. + case YAFFS_OBJECT_TYPE_HARDLINK:
  4204. + case YAFFS_OBJECT_TYPE_SPECIAL:
  4205. + /* No action required */
  4206. + break;
  4207. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  4208. + /* todo this should not happen */
  4209. + break;
  4210. + }
  4211. + return the_obj;
  4212. +}
  4213. +
  4214. +static struct yaffs_obj *yaffs_create_fake_dir(struct yaffs_dev *dev,
  4215. + int number, u32 mode)
  4216. +{
  4217. +
  4218. + struct yaffs_obj *obj =
  4219. + yaffs_new_obj(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
  4220. +
  4221. + if (!obj)
  4222. + return NULL;
  4223. +
  4224. + obj->fake = 1; /* it is fake so it might not use NAND */
  4225. + obj->rename_allowed = 0;
  4226. + obj->unlink_allowed = 0;
  4227. + obj->deleted = 0;
  4228. + obj->unlinked = 0;
  4229. + obj->yst_mode = mode;
  4230. + obj->my_dev = dev;
  4231. + obj->hdr_chunk = 0; /* Not a valid chunk. */
  4232. + return obj;
  4233. +
  4234. +}
  4235. +
  4236. +
  4237. +static void yaffs_init_tnodes_and_objs(struct yaffs_dev *dev)
  4238. +{
  4239. + int i;
  4240. +
  4241. + dev->n_obj = 0;
  4242. + dev->n_tnodes = 0;
  4243. + yaffs_init_raw_tnodes_and_objs(dev);
  4244. +
  4245. + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
  4246. + INIT_LIST_HEAD(&dev->obj_bucket[i].list);
  4247. + dev->obj_bucket[i].count = 0;
  4248. + }
  4249. +}
  4250. +
  4251. +struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
  4252. + int number,
  4253. + enum yaffs_obj_type type)
  4254. +{
  4255. + struct yaffs_obj *the_obj = NULL;
  4256. +
  4257. + if (number > 0)
  4258. + the_obj = yaffs_find_by_number(dev, number);
  4259. +
  4260. + if (!the_obj)
  4261. + the_obj = yaffs_new_obj(dev, number, type);
  4262. +
  4263. + return the_obj;
  4264. +
  4265. +}
  4266. +
  4267. +YCHAR *yaffs_clone_str(const YCHAR *str)
  4268. +{
  4269. + YCHAR *new_str = NULL;
  4270. + int len;
  4271. +
  4272. + if (!str)
  4273. + str = _Y("");
  4274. +
  4275. + len = strnlen(str, YAFFS_MAX_ALIAS_LENGTH);
  4276. + new_str = kmalloc((len + 1) * sizeof(YCHAR), GFP_NOFS);
  4277. + if (new_str) {
  4278. + strncpy(new_str, str, len);
  4279. + new_str[len] = 0;
  4280. + }
  4281. + return new_str;
  4282. +
  4283. +}
  4284. +/*
  4285. + *yaffs_update_parent() handles fixing a directories mtime and ctime when a new
  4286. + * link (ie. name) is created or deleted in the directory.
  4287. + *
  4288. + * ie.
  4289. + * create dir/a : update dir's mtime/ctime
  4290. + * rm dir/a: update dir's mtime/ctime
  4291. + * modify dir/a: don't update dir's mtimme/ctime
  4292. + *
  4293. + * This can be handled immediately or defered. Defering helps reduce the number
  4294. + * of updates when many files in a directory are changed within a brief period.
  4295. + *
  4296. + * If the directory updating is defered then yaffs_update_dirty_dirs must be
  4297. + * called periodically.
  4298. + */
  4299. +
  4300. +static void yaffs_update_parent(struct yaffs_obj *obj)
  4301. +{
  4302. + struct yaffs_dev *dev;
  4303. +
  4304. + if (!obj)
  4305. + return;
  4306. + dev = obj->my_dev;
  4307. + obj->dirty = 1;
  4308. + yaffs_load_current_time(obj, 0, 1);
  4309. + if (dev->param.defered_dir_update) {
  4310. + struct list_head *link = &obj->variant.dir_variant.dirty;
  4311. +
  4312. + if (list_empty(link)) {
  4313. + list_add(link, &dev->dirty_dirs);
  4314. + yaffs_trace(YAFFS_TRACE_BACKGROUND,
  4315. + "Added object %d to dirty directories",
  4316. + obj->obj_id);
  4317. + }
  4318. +
  4319. + } else {
  4320. + yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
  4321. + }
  4322. +}
  4323. +
  4324. +void yaffs_update_dirty_dirs(struct yaffs_dev *dev)
  4325. +{
  4326. + struct list_head *link;
  4327. + struct yaffs_obj *obj;
  4328. + struct yaffs_dir_var *d_s;
  4329. + union yaffs_obj_var *o_v;
  4330. +
  4331. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update dirty directories");
  4332. +
  4333. + while (!list_empty(&dev->dirty_dirs)) {
  4334. + link = dev->dirty_dirs.next;
  4335. + list_del_init(link);
  4336. +
  4337. + d_s = list_entry(link, struct yaffs_dir_var, dirty);
  4338. + o_v = list_entry(d_s, union yaffs_obj_var, dir_variant);
  4339. + obj = list_entry(o_v, struct yaffs_obj, variant);
  4340. +
  4341. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update directory %d",
  4342. + obj->obj_id);
  4343. +
  4344. + if (obj->dirty)
  4345. + yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
  4346. + }
  4347. +}
  4348. +
  4349. +/*
  4350. + * Mknod (create) a new object.
  4351. + * equiv_obj only has meaning for a hard link;
  4352. + * alias_str only has meaning for a symlink.
  4353. + * rdev only has meaning for devices (a subset of special objects)
  4354. + */
  4355. +
  4356. +static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type,
  4357. + struct yaffs_obj *parent,
  4358. + const YCHAR *name,
  4359. + u32 mode,
  4360. + u32 uid,
  4361. + u32 gid,
  4362. + struct yaffs_obj *equiv_obj,
  4363. + const YCHAR *alias_str, u32 rdev)
  4364. +{
  4365. + struct yaffs_obj *in;
  4366. + YCHAR *str = NULL;
  4367. + struct yaffs_dev *dev = parent->my_dev;
  4368. +
  4369. + /* Check if the entry exists.
  4370. + * If it does then fail the call since we don't want a dup. */
  4371. + if (yaffs_find_by_name(parent, name))
  4372. + return NULL;
  4373. +
  4374. + if (type == YAFFS_OBJECT_TYPE_SYMLINK) {
  4375. + str = yaffs_clone_str(alias_str);
  4376. + if (!str)
  4377. + return NULL;
  4378. + }
  4379. +
  4380. + in = yaffs_new_obj(dev, -1, type);
  4381. +
  4382. + if (!in) {
  4383. + kfree(str);
  4384. + return NULL;
  4385. + }
  4386. +
  4387. + in->hdr_chunk = 0;
  4388. + in->valid = 1;
  4389. + in->variant_type = type;
  4390. +
  4391. + in->yst_mode = mode;
  4392. +
  4393. + yaffs_attribs_init(in, gid, uid, rdev);
  4394. +
  4395. + in->n_data_chunks = 0;
  4396. +
  4397. + yaffs_set_obj_name(in, name);
  4398. + in->dirty = 1;
  4399. +
  4400. + yaffs_add_obj_to_dir(parent, in);
  4401. +
  4402. + in->my_dev = parent->my_dev;
  4403. +
  4404. + switch (type) {
  4405. + case YAFFS_OBJECT_TYPE_SYMLINK:
  4406. + in->variant.symlink_variant.alias = str;
  4407. + break;
  4408. + case YAFFS_OBJECT_TYPE_HARDLINK:
  4409. + in->variant.hardlink_variant.equiv_obj = equiv_obj;
  4410. + in->variant.hardlink_variant.equiv_id = equiv_obj->obj_id;
  4411. + list_add(&in->hard_links, &equiv_obj->hard_links);
  4412. + break;
  4413. + case YAFFS_OBJECT_TYPE_FILE:
  4414. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  4415. + case YAFFS_OBJECT_TYPE_SPECIAL:
  4416. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  4417. + /* do nothing */
  4418. + break;
  4419. + }
  4420. +
  4421. + if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) {
  4422. + /* Could not create the object header, fail */
  4423. + yaffs_del_obj(in);
  4424. + in = NULL;
  4425. + }
  4426. +
  4427. + if (in)
  4428. + yaffs_update_parent(parent);
  4429. +
  4430. + return in;
  4431. +}
  4432. +
  4433. +struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
  4434. + const YCHAR *name, u32 mode, u32 uid,
  4435. + u32 gid)
  4436. +{
  4437. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,
  4438. + uid, gid, NULL, NULL, 0);
  4439. +}
  4440. +
  4441. +struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name,
  4442. + u32 mode, u32 uid, u32 gid)
  4443. +{
  4444. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,
  4445. + mode, uid, gid, NULL, NULL, 0);
  4446. +}
  4447. +
  4448. +struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
  4449. + const YCHAR *name, u32 mode, u32 uid,
  4450. + u32 gid, u32 rdev)
  4451. +{
  4452. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,
  4453. + uid, gid, NULL, NULL, rdev);
  4454. +}
  4455. +
  4456. +struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
  4457. + const YCHAR *name, u32 mode, u32 uid,
  4458. + u32 gid, const YCHAR *alias)
  4459. +{
  4460. + return yaffs_create_obj(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,
  4461. + uid, gid, NULL, alias, 0);
  4462. +}
  4463. +
  4464. +/* yaffs_link_obj returns the object id of the equivalent object.*/
  4465. +struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR * name,
  4466. + struct yaffs_obj *equiv_obj)
  4467. +{
  4468. + /* Get the real object in case we were fed a hard link obj */
  4469. + equiv_obj = yaffs_get_equivalent_obj(equiv_obj);
  4470. +
  4471. + if (yaffs_create_obj(YAFFS_OBJECT_TYPE_HARDLINK,
  4472. + parent, name, 0, 0, 0,
  4473. + equiv_obj, NULL, 0))
  4474. + return equiv_obj;
  4475. +
  4476. + return NULL;
  4477. +
  4478. +}
  4479. +
  4480. +
  4481. +
  4482. +/*---------------------- Block Management and Page Allocation -------------*/
  4483. +
  4484. +static void yaffs_deinit_blocks(struct yaffs_dev *dev)
  4485. +{
  4486. + if (dev->block_info_alt && dev->block_info)
  4487. + vfree(dev->block_info);
  4488. + else
  4489. + kfree(dev->block_info);
  4490. +
  4491. + dev->block_info_alt = 0;
  4492. +
  4493. + dev->block_info = NULL;
  4494. +
  4495. + if (dev->chunk_bits_alt && dev->chunk_bits)
  4496. + vfree(dev->chunk_bits);
  4497. + else
  4498. + kfree(dev->chunk_bits);
  4499. + dev->chunk_bits_alt = 0;
  4500. + dev->chunk_bits = NULL;
  4501. +}
  4502. +
  4503. +static int yaffs_init_blocks(struct yaffs_dev *dev)
  4504. +{
  4505. + int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
  4506. +
  4507. + dev->block_info = NULL;
  4508. + dev->chunk_bits = NULL;
  4509. + dev->alloc_block = -1; /* force it to get a new one */
  4510. +
  4511. + /* If the first allocation strategy fails, thry the alternate one */
  4512. + dev->block_info =
  4513. + kmalloc(n_blocks * sizeof(struct yaffs_block_info), GFP_NOFS);
  4514. + if (!dev->block_info) {
  4515. + dev->block_info =
  4516. + vmalloc(n_blocks * sizeof(struct yaffs_block_info));
  4517. + dev->block_info_alt = 1;
  4518. + } else {
  4519. + dev->block_info_alt = 0;
  4520. + }
  4521. +
  4522. + if (!dev->block_info)
  4523. + goto alloc_error;
  4524. +
  4525. + /* Set up dynamic blockinfo stuff. Round up bytes. */
  4526. + dev->chunk_bit_stride = (dev->param.chunks_per_block + 7) / 8;
  4527. + dev->chunk_bits =
  4528. + kmalloc(dev->chunk_bit_stride * n_blocks, GFP_NOFS);
  4529. + if (!dev->chunk_bits) {
  4530. + dev->chunk_bits =
  4531. + vmalloc(dev->chunk_bit_stride * n_blocks);
  4532. + dev->chunk_bits_alt = 1;
  4533. + } else {
  4534. + dev->chunk_bits_alt = 0;
  4535. + }
  4536. + if (!dev->chunk_bits)
  4537. + goto alloc_error;
  4538. +
  4539. +
  4540. + memset(dev->block_info, 0, n_blocks * sizeof(struct yaffs_block_info));
  4541. + memset(dev->chunk_bits, 0, dev->chunk_bit_stride * n_blocks);
  4542. + return YAFFS_OK;
  4543. +
  4544. +alloc_error:
  4545. + yaffs_deinit_blocks(dev);
  4546. + return YAFFS_FAIL;
  4547. +}
  4548. +
  4549. +
  4550. +void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no)
  4551. +{
  4552. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, block_no);
  4553. + int erased_ok = 0;
  4554. + int i;
  4555. +
  4556. + /* If the block is still healthy erase it and mark as clean.
  4557. + * If the block has had a data failure, then retire it.
  4558. + */
  4559. +
  4560. + yaffs_trace(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
  4561. + "yaffs_block_became_dirty block %d state %d %s",
  4562. + block_no, bi->block_state,
  4563. + (bi->needs_retiring) ? "needs retiring" : "");
  4564. +
  4565. + yaffs2_clear_oldest_dirty_seq(dev, bi);
  4566. +
  4567. + bi->block_state = YAFFS_BLOCK_STATE_DIRTY;
  4568. +
  4569. + /* If this is the block being garbage collected then stop gc'ing */
  4570. + if (block_no == dev->gc_block)
  4571. + dev->gc_block = 0;
  4572. +
  4573. + /* If this block is currently the best candidate for gc
  4574. + * then drop as a candidate */
  4575. + if (block_no == dev->gc_dirtiest) {
  4576. + dev->gc_dirtiest = 0;
  4577. + dev->gc_pages_in_use = 0;
  4578. + }
  4579. +
  4580. + if (!bi->needs_retiring) {
  4581. + yaffs2_checkpt_invalidate(dev);
  4582. + erased_ok = yaffs_erase_block(dev, block_no);
  4583. + if (!erased_ok) {
  4584. + dev->n_erase_failures++;
  4585. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  4586. + "**>> Erasure failed %d", block_no);
  4587. + }
  4588. + }
  4589. +
  4590. + /* Verify erasure if needed */
  4591. + if (erased_ok &&
  4592. + ((yaffs_trace_mask & YAFFS_TRACE_ERASE) ||
  4593. + !yaffs_skip_verification(dev))) {
  4594. + for (i = 0; i < dev->param.chunks_per_block; i++) {
  4595. + if (!yaffs_check_chunk_erased(dev,
  4596. + block_no * dev->param.chunks_per_block + i)) {
  4597. + yaffs_trace(YAFFS_TRACE_ERROR,
  4598. + ">>Block %d erasure supposedly OK, but chunk %d not erased",
  4599. + block_no, i);
  4600. + }
  4601. + }
  4602. + }
  4603. +
  4604. + if (!erased_ok) {
  4605. + /* We lost a block of free space */
  4606. + dev->n_free_chunks -= dev->param.chunks_per_block;
  4607. + yaffs_retire_block(dev, block_no);
  4608. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  4609. + "**>> Block %d retired", block_no);
  4610. + return;
  4611. + }
  4612. +
  4613. + /* Clean it up... */
  4614. + bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
  4615. + bi->seq_number = 0;
  4616. + dev->n_erased_blocks++;
  4617. + bi->pages_in_use = 0;
  4618. + bi->soft_del_pages = 0;
  4619. + bi->has_shrink_hdr = 0;
  4620. + bi->skip_erased_check = 1; /* Clean, so no need to check */
  4621. + bi->gc_prioritise = 0;
  4622. + bi->has_summary = 0;
  4623. +
  4624. + yaffs_clear_chunk_bits(dev, block_no);
  4625. +
  4626. + yaffs_trace(YAFFS_TRACE_ERASE, "Erased block %d", block_no);
  4627. +}
  4628. +
  4629. +static inline int yaffs_gc_process_chunk(struct yaffs_dev *dev,
  4630. + struct yaffs_block_info *bi,
  4631. + int old_chunk, u8 *buffer)
  4632. +{
  4633. + int new_chunk;
  4634. + int mark_flash = 1;
  4635. + struct yaffs_ext_tags tags;
  4636. + struct yaffs_obj *object;
  4637. + int matching_chunk;
  4638. + int ret_val = YAFFS_OK;
  4639. +
  4640. + memset(&tags, 0, sizeof(tags));
  4641. + yaffs_rd_chunk_tags_nand(dev, old_chunk,
  4642. + buffer, &tags);
  4643. + object = yaffs_find_by_number(dev, tags.obj_id);
  4644. +
  4645. + yaffs_trace(YAFFS_TRACE_GC_DETAIL,
  4646. + "Collecting chunk in block %d, %d %d %d ",
  4647. + dev->gc_chunk, tags.obj_id,
  4648. + tags.chunk_id, tags.n_bytes);
  4649. +
  4650. + if (object && !yaffs_skip_verification(dev)) {
  4651. + if (tags.chunk_id == 0)
  4652. + matching_chunk =
  4653. + object->hdr_chunk;
  4654. + else if (object->soft_del)
  4655. + /* Defeat the test */
  4656. + matching_chunk = old_chunk;
  4657. + else
  4658. + matching_chunk =
  4659. + yaffs_find_chunk_in_file
  4660. + (object, tags.chunk_id,
  4661. + NULL);
  4662. +
  4663. + if (old_chunk != matching_chunk)
  4664. + yaffs_trace(YAFFS_TRACE_ERROR,
  4665. + "gc: page in gc mismatch: %d %d %d %d",
  4666. + old_chunk,
  4667. + matching_chunk,
  4668. + tags.obj_id,
  4669. + tags.chunk_id);
  4670. + }
  4671. +
  4672. + if (!object) {
  4673. + yaffs_trace(YAFFS_TRACE_ERROR,
  4674. + "page %d in gc has no object: %d %d %d ",
  4675. + old_chunk,
  4676. + tags.obj_id, tags.chunk_id,
  4677. + tags.n_bytes);
  4678. + }
  4679. +
  4680. + if (object &&
  4681. + object->deleted &&
  4682. + object->soft_del && tags.chunk_id != 0) {
  4683. + /* Data chunk in a soft deleted file,
  4684. + * throw it away.
  4685. + * It's a soft deleted data chunk,
  4686. + * No need to copy this, just forget
  4687. + * about it and fix up the object.
  4688. + */
  4689. +
  4690. + /* Free chunks already includes
  4691. + * softdeleted chunks, how ever this
  4692. + * chunk is going to soon be really
  4693. + * deleted which will increment free
  4694. + * chunks. We have to decrement free
  4695. + * chunks so this works out properly.
  4696. + */
  4697. + dev->n_free_chunks--;
  4698. + bi->soft_del_pages--;
  4699. +
  4700. + object->n_data_chunks--;
  4701. + if (object->n_data_chunks <= 0) {
  4702. + /* remeber to clean up obj */
  4703. + dev->gc_cleanup_list[dev->n_clean_ups] = tags.obj_id;
  4704. + dev->n_clean_ups++;
  4705. + }
  4706. + mark_flash = 0;
  4707. + } else if (object) {
  4708. + /* It's either a data chunk in a live
  4709. + * file or an ObjectHeader, so we're
  4710. + * interested in it.
  4711. + * NB Need to keep the ObjectHeaders of
  4712. + * deleted files until the whole file
  4713. + * has been deleted off
  4714. + */
  4715. + tags.serial_number++;
  4716. + dev->n_gc_copies++;
  4717. +
  4718. + if (tags.chunk_id == 0) {
  4719. + /* It is an object Id,
  4720. + * We need to nuke the
  4721. + * shrinkheader flags since its
  4722. + * work is done.
  4723. + * Also need to clean up
  4724. + * shadowing.
  4725. + */
  4726. + struct yaffs_obj_hdr *oh;
  4727. + oh = (struct yaffs_obj_hdr *) buffer;
  4728. +
  4729. + oh->is_shrink = 0;
  4730. + tags.extra_is_shrink = 0;
  4731. + oh->shadows_obj = 0;
  4732. + oh->inband_shadowed_obj_id = 0;
  4733. + tags.extra_shadows = 0;
  4734. +
  4735. + /* Update file size */
  4736. + if (object->variant_type == YAFFS_OBJECT_TYPE_FILE) {
  4737. + yaffs_oh_size_load(oh,
  4738. + object->variant.file_variant.file_size);
  4739. + tags.extra_file_size =
  4740. + object->variant.file_variant.file_size;
  4741. + }
  4742. +
  4743. + yaffs_verify_oh(object, oh, &tags, 1);
  4744. + new_chunk =
  4745. + yaffs_write_new_chunk(dev, (u8 *) oh, &tags, 1);
  4746. + } else {
  4747. + new_chunk =
  4748. + yaffs_write_new_chunk(dev, buffer, &tags, 1);
  4749. + }
  4750. +
  4751. + if (new_chunk < 0) {
  4752. + ret_val = YAFFS_FAIL;
  4753. + } else {
  4754. +
  4755. + /* Now fix up the Tnodes etc. */
  4756. +
  4757. + if (tags.chunk_id == 0) {
  4758. + /* It's a header */
  4759. + object->hdr_chunk = new_chunk;
  4760. + object->serial = tags.serial_number;
  4761. + } else {
  4762. + /* It's a data chunk */
  4763. + yaffs_put_chunk_in_file(object, tags.chunk_id,
  4764. + new_chunk, 0);
  4765. + }
  4766. + }
  4767. + }
  4768. + if (ret_val == YAFFS_OK)
  4769. + yaffs_chunk_del(dev, old_chunk, mark_flash, __LINE__);
  4770. + return ret_val;
  4771. +}
  4772. +
  4773. +static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block)
  4774. +{
  4775. + int old_chunk;
  4776. + int ret_val = YAFFS_OK;
  4777. + int i;
  4778. + int is_checkpt_block;
  4779. + int max_copies;
  4780. + int chunks_before = yaffs_get_erased_chunks(dev);
  4781. + int chunks_after;
  4782. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, block);
  4783. +
  4784. + is_checkpt_block = (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT);
  4785. +
  4786. + yaffs_trace(YAFFS_TRACE_TRACING,
  4787. + "Collecting block %d, in use %d, shrink %d, whole_block %d",
  4788. + block, bi->pages_in_use, bi->has_shrink_hdr,
  4789. + whole_block);
  4790. +
  4791. + /*yaffs_verify_free_chunks(dev); */
  4792. +
  4793. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL)
  4794. + bi->block_state = YAFFS_BLOCK_STATE_COLLECTING;
  4795. +
  4796. + bi->has_shrink_hdr = 0; /* clear the flag so that the block can erase */
  4797. +
  4798. + dev->gc_disable = 1;
  4799. +
  4800. + yaffs_summary_gc(dev, block);
  4801. +
  4802. + if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) {
  4803. + yaffs_trace(YAFFS_TRACE_TRACING,
  4804. + "Collecting block %d that has no chunks in use",
  4805. + block);
  4806. + yaffs_block_became_dirty(dev, block);
  4807. + } else {
  4808. +
  4809. + u8 *buffer = yaffs_get_temp_buffer(dev);
  4810. +
  4811. + yaffs_verify_blk(dev, bi, block);
  4812. +
  4813. + max_copies = (whole_block) ? dev->param.chunks_per_block : 5;
  4814. + old_chunk = block * dev->param.chunks_per_block + dev->gc_chunk;
  4815. +
  4816. + for (/* init already done */ ;
  4817. + ret_val == YAFFS_OK &&
  4818. + dev->gc_chunk < dev->param.chunks_per_block &&
  4819. + (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) &&
  4820. + max_copies > 0;
  4821. + dev->gc_chunk++, old_chunk++) {
  4822. + if (yaffs_check_chunk_bit(dev, block, dev->gc_chunk)) {
  4823. + /* Page is in use and might need to be copied */
  4824. + max_copies--;
  4825. + ret_val = yaffs_gc_process_chunk(dev, bi,
  4826. + old_chunk, buffer);
  4827. + }
  4828. + }
  4829. + yaffs_release_temp_buffer(dev, buffer);
  4830. + }
  4831. +
  4832. + yaffs_verify_collected_blk(dev, bi, block);
  4833. +
  4834. + if (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
  4835. + /*
  4836. + * The gc did not complete. Set block state back to FULL
  4837. + * because checkpointing does not restore gc.
  4838. + */
  4839. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  4840. + } else {
  4841. + /* The gc completed. */
  4842. + /* Do any required cleanups */
  4843. + for (i = 0; i < dev->n_clean_ups; i++) {
  4844. + /* Time to delete the file too */
  4845. + struct yaffs_obj *object =
  4846. + yaffs_find_by_number(dev, dev->gc_cleanup_list[i]);
  4847. + if (object) {
  4848. + yaffs_free_tnode(dev,
  4849. + object->variant.file_variant.top);
  4850. + object->variant.file_variant.top = NULL;
  4851. + yaffs_trace(YAFFS_TRACE_GC,
  4852. + "yaffs: About to finally delete object %d",
  4853. + object->obj_id);
  4854. + yaffs_generic_obj_del(object);
  4855. + object->my_dev->n_deleted_files--;
  4856. + }
  4857. +
  4858. + }
  4859. + chunks_after = yaffs_get_erased_chunks(dev);
  4860. + if (chunks_before >= chunks_after)
  4861. + yaffs_trace(YAFFS_TRACE_GC,
  4862. + "gc did not increase free chunks before %d after %d",
  4863. + chunks_before, chunks_after);
  4864. + dev->gc_block = 0;
  4865. + dev->gc_chunk = 0;
  4866. + dev->n_clean_ups = 0;
  4867. + }
  4868. +
  4869. + dev->gc_disable = 0;
  4870. +
  4871. + return ret_val;
  4872. +}
  4873. +
  4874. +/*
  4875. + * find_gc_block() selects the dirtiest block (or close enough)
  4876. + * for garbage collection.
  4877. + */
  4878. +
  4879. +static unsigned yaffs_find_gc_block(struct yaffs_dev *dev,
  4880. + int aggressive, int background)
  4881. +{
  4882. + int i;
  4883. + int iterations;
  4884. + unsigned selected = 0;
  4885. + int prioritised = 0;
  4886. + int prioritised_exist = 0;
  4887. + struct yaffs_block_info *bi;
  4888. + int threshold;
  4889. +
  4890. + /* First let's see if we need to grab a prioritised block */
  4891. + if (dev->has_pending_prioritised_gc && !aggressive) {
  4892. + dev->gc_dirtiest = 0;
  4893. + bi = dev->block_info;
  4894. + for (i = dev->internal_start_block;
  4895. + i <= dev->internal_end_block && !selected; i++) {
  4896. +
  4897. + if (bi->gc_prioritise) {
  4898. + prioritised_exist = 1;
  4899. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
  4900. + yaffs_block_ok_for_gc(dev, bi)) {
  4901. + selected = i;
  4902. + prioritised = 1;
  4903. + }
  4904. + }
  4905. + bi++;
  4906. + }
  4907. +
  4908. + /*
  4909. + * If there is a prioritised block and none was selected then
  4910. + * this happened because there is at least one old dirty block
  4911. + * gumming up the works. Let's gc the oldest dirty block.
  4912. + */
  4913. +
  4914. + if (prioritised_exist &&
  4915. + !selected && dev->oldest_dirty_block > 0)
  4916. + selected = dev->oldest_dirty_block;
  4917. +
  4918. + if (!prioritised_exist) /* None found, so we can clear this */
  4919. + dev->has_pending_prioritised_gc = 0;
  4920. + }
  4921. +
  4922. + /* If we're doing aggressive GC then we are happy to take a less-dirty
  4923. + * block, and search harder.
  4924. + * else (leasurely gc), then we only bother to do this if the
  4925. + * block has only a few pages in use.
  4926. + */
  4927. +
  4928. + if (!selected) {
  4929. + int pages_used;
  4930. + int n_blocks =
  4931. + dev->internal_end_block - dev->internal_start_block + 1;
  4932. + if (aggressive) {
  4933. + threshold = dev->param.chunks_per_block;
  4934. + iterations = n_blocks;
  4935. + } else {
  4936. + int max_threshold;
  4937. +
  4938. + if (background)
  4939. + max_threshold = dev->param.chunks_per_block / 2;
  4940. + else
  4941. + max_threshold = dev->param.chunks_per_block / 8;
  4942. +
  4943. + if (max_threshold < YAFFS_GC_PASSIVE_THRESHOLD)
  4944. + max_threshold = YAFFS_GC_PASSIVE_THRESHOLD;
  4945. +
  4946. + threshold = background ? (dev->gc_not_done + 2) * 2 : 0;
  4947. + if (threshold < YAFFS_GC_PASSIVE_THRESHOLD)
  4948. + threshold = YAFFS_GC_PASSIVE_THRESHOLD;
  4949. + if (threshold > max_threshold)
  4950. + threshold = max_threshold;
  4951. +
  4952. + iterations = n_blocks / 16 + 1;
  4953. + if (iterations > 100)
  4954. + iterations = 100;
  4955. + }
  4956. +
  4957. + for (i = 0;
  4958. + i < iterations &&
  4959. + (dev->gc_dirtiest < 1 ||
  4960. + dev->gc_pages_in_use > YAFFS_GC_GOOD_ENOUGH);
  4961. + i++) {
  4962. + dev->gc_block_finder++;
  4963. + if (dev->gc_block_finder < dev->internal_start_block ||
  4964. + dev->gc_block_finder > dev->internal_end_block)
  4965. + dev->gc_block_finder =
  4966. + dev->internal_start_block;
  4967. +
  4968. + bi = yaffs_get_block_info(dev, dev->gc_block_finder);
  4969. +
  4970. + pages_used = bi->pages_in_use - bi->soft_del_pages;
  4971. +
  4972. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
  4973. + pages_used < dev->param.chunks_per_block &&
  4974. + (dev->gc_dirtiest < 1 ||
  4975. + pages_used < dev->gc_pages_in_use) &&
  4976. + yaffs_block_ok_for_gc(dev, bi)) {
  4977. + dev->gc_dirtiest = dev->gc_block_finder;
  4978. + dev->gc_pages_in_use = pages_used;
  4979. + }
  4980. + }
  4981. +
  4982. + if (dev->gc_dirtiest > 0 && dev->gc_pages_in_use <= threshold)
  4983. + selected = dev->gc_dirtiest;
  4984. + }
  4985. +
  4986. + /*
  4987. + * If nothing has been selected for a while, try the oldest dirty
  4988. + * because that's gumming up the works.
  4989. + */
  4990. +
  4991. + if (!selected && dev->param.is_yaffs2 &&
  4992. + dev->gc_not_done >= (background ? 10 : 20)) {
  4993. + yaffs2_find_oldest_dirty_seq(dev);
  4994. + if (dev->oldest_dirty_block > 0) {
  4995. + selected = dev->oldest_dirty_block;
  4996. + dev->gc_dirtiest = selected;
  4997. + dev->oldest_dirty_gc_count++;
  4998. + bi = yaffs_get_block_info(dev, selected);
  4999. + dev->gc_pages_in_use =
  5000. + bi->pages_in_use - bi->soft_del_pages;
  5001. + } else {
  5002. + dev->gc_not_done = 0;
  5003. + }
  5004. + }
  5005. +
  5006. + if (selected) {
  5007. + yaffs_trace(YAFFS_TRACE_GC,
  5008. + "GC Selected block %d with %d free, prioritised:%d",
  5009. + selected,
  5010. + dev->param.chunks_per_block - dev->gc_pages_in_use,
  5011. + prioritised);
  5012. +
  5013. + dev->n_gc_blocks++;
  5014. + if (background)
  5015. + dev->bg_gcs++;
  5016. +
  5017. + dev->gc_dirtiest = 0;
  5018. + dev->gc_pages_in_use = 0;
  5019. + dev->gc_not_done = 0;
  5020. + if (dev->refresh_skip > 0)
  5021. + dev->refresh_skip--;
  5022. + } else {
  5023. + dev->gc_not_done++;
  5024. + yaffs_trace(YAFFS_TRACE_GC,
  5025. + "GC none: finder %d skip %d threshold %d dirtiest %d using %d oldest %d%s",
  5026. + dev->gc_block_finder, dev->gc_not_done, threshold,
  5027. + dev->gc_dirtiest, dev->gc_pages_in_use,
  5028. + dev->oldest_dirty_block, background ? " bg" : "");
  5029. + }
  5030. +
  5031. + return selected;
  5032. +}
  5033. +
  5034. +/* New garbage collector
  5035. + * If we're very low on erased blocks then we do aggressive garbage collection
  5036. + * otherwise we do "leasurely" garbage collection.
  5037. + * Aggressive gc looks further (whole array) and will accept less dirty blocks.
  5038. + * Passive gc only inspects smaller areas and only accepts more dirty blocks.
  5039. + *
  5040. + * The idea is to help clear out space in a more spread-out manner.
  5041. + * Dunno if it really does anything useful.
  5042. + */
  5043. +static int yaffs_check_gc(struct yaffs_dev *dev, int background)
  5044. +{
  5045. + int aggressive = 0;
  5046. + int gc_ok = YAFFS_OK;
  5047. + int max_tries = 0;
  5048. + int min_erased;
  5049. + int erased_chunks;
  5050. + int checkpt_block_adjust;
  5051. +
  5052. + if (dev->param.gc_control_fn &&
  5053. + (dev->param.gc_control_fn(dev) & 1) == 0)
  5054. + return YAFFS_OK;
  5055. +
  5056. + if (dev->gc_disable)
  5057. + /* Bail out so we don't get recursive gc */
  5058. + return YAFFS_OK;
  5059. +
  5060. + /* This loop should pass the first time.
  5061. + * Only loops here if the collection does not increase space.
  5062. + */
  5063. +
  5064. + do {
  5065. + max_tries++;
  5066. +
  5067. + checkpt_block_adjust = yaffs_calc_checkpt_blocks_required(dev);
  5068. +
  5069. + min_erased =
  5070. + dev->param.n_reserved_blocks + checkpt_block_adjust + 1;
  5071. + erased_chunks =
  5072. + dev->n_erased_blocks * dev->param.chunks_per_block;
  5073. +
  5074. + /* If we need a block soon then do aggressive gc. */
  5075. + if (dev->n_erased_blocks < min_erased)
  5076. + aggressive = 1;
  5077. + else {
  5078. + if (!background
  5079. + && erased_chunks > (dev->n_free_chunks / 4))
  5080. + break;
  5081. +
  5082. + if (dev->gc_skip > 20)
  5083. + dev->gc_skip = 20;
  5084. + if (erased_chunks < dev->n_free_chunks / 2 ||
  5085. + dev->gc_skip < 1 || background)
  5086. + aggressive = 0;
  5087. + else {
  5088. + dev->gc_skip--;
  5089. + break;
  5090. + }
  5091. + }
  5092. +
  5093. + dev->gc_skip = 5;
  5094. +
  5095. + /* If we don't already have a block being gc'd then see if we
  5096. + * should start another */
  5097. +
  5098. + if (dev->gc_block < 1 && !aggressive) {
  5099. + dev->gc_block = yaffs2_find_refresh_block(dev);
  5100. + dev->gc_chunk = 0;
  5101. + dev->n_clean_ups = 0;
  5102. + }
  5103. + if (dev->gc_block < 1) {
  5104. + dev->gc_block =
  5105. + yaffs_find_gc_block(dev, aggressive, background);
  5106. + dev->gc_chunk = 0;
  5107. + dev->n_clean_ups = 0;
  5108. + }
  5109. +
  5110. + if (dev->gc_block > 0) {
  5111. + dev->all_gcs++;
  5112. + if (!aggressive)
  5113. + dev->passive_gc_count++;
  5114. +
  5115. + yaffs_trace(YAFFS_TRACE_GC,
  5116. + "yaffs: GC n_erased_blocks %d aggressive %d",
  5117. + dev->n_erased_blocks, aggressive);
  5118. +
  5119. + gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive);
  5120. + }
  5121. +
  5122. + if (dev->n_erased_blocks < (dev->param.n_reserved_blocks) &&
  5123. + dev->gc_block > 0) {
  5124. + yaffs_trace(YAFFS_TRACE_GC,
  5125. + "yaffs: GC !!!no reclaim!!! n_erased_blocks %d after try %d block %d",
  5126. + dev->n_erased_blocks, max_tries,
  5127. + dev->gc_block);
  5128. + }
  5129. + } while ((dev->n_erased_blocks < dev->param.n_reserved_blocks) &&
  5130. + (dev->gc_block > 0) && (max_tries < 2));
  5131. +
  5132. + return aggressive ? gc_ok : YAFFS_OK;
  5133. +}
  5134. +
  5135. +/*
  5136. + * yaffs_bg_gc()
  5137. + * Garbage collects. Intended to be called from a background thread.
  5138. + * Returns non-zero if at least half the free chunks are erased.
  5139. + */
  5140. +int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency)
  5141. +{
  5142. + int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;
  5143. +
  5144. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "Background gc %u", urgency);
  5145. +
  5146. + yaffs_check_gc(dev, 1);
  5147. + return erased_chunks > dev->n_free_chunks / 2;
  5148. +}
  5149. +
  5150. +/*-------------------- Data file manipulation -----------------*/
  5151. +
  5152. +static int yaffs_rd_data_obj(struct yaffs_obj *in, int inode_chunk, u8 * buffer)
  5153. +{
  5154. + int nand_chunk = yaffs_find_chunk_in_file(in, inode_chunk, NULL);
  5155. +
  5156. + if (nand_chunk >= 0)
  5157. + return yaffs_rd_chunk_tags_nand(in->my_dev, nand_chunk,
  5158. + buffer, NULL);
  5159. + else {
  5160. + yaffs_trace(YAFFS_TRACE_NANDACCESS,
  5161. + "Chunk %d not found zero instead",
  5162. + nand_chunk);
  5163. + /* get sane (zero) data if you read a hole */
  5164. + memset(buffer, 0, in->my_dev->data_bytes_per_chunk);
  5165. + return 0;
  5166. + }
  5167. +
  5168. +}
  5169. +
  5170. +void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
  5171. + int lyn)
  5172. +{
  5173. + int block;
  5174. + int page;
  5175. + struct yaffs_ext_tags tags;
  5176. + struct yaffs_block_info *bi;
  5177. +
  5178. + if (chunk_id <= 0)
  5179. + return;
  5180. +
  5181. + dev->n_deletions++;
  5182. + block = chunk_id / dev->param.chunks_per_block;
  5183. + page = chunk_id % dev->param.chunks_per_block;
  5184. +
  5185. + if (!yaffs_check_chunk_bit(dev, block, page))
  5186. + yaffs_trace(YAFFS_TRACE_VERIFY,
  5187. + "Deleting invalid chunk %d", chunk_id);
  5188. +
  5189. + bi = yaffs_get_block_info(dev, block);
  5190. +
  5191. + yaffs2_update_oldest_dirty_seq(dev, block, bi);
  5192. +
  5193. + yaffs_trace(YAFFS_TRACE_DELETION,
  5194. + "line %d delete of chunk %d",
  5195. + lyn, chunk_id);
  5196. +
  5197. + if (!dev->param.is_yaffs2 && mark_flash &&
  5198. + bi->block_state != YAFFS_BLOCK_STATE_COLLECTING) {
  5199. +
  5200. + memset(&tags, 0, sizeof(tags));
  5201. + tags.is_deleted = 1;
  5202. + yaffs_wr_chunk_tags_nand(dev, chunk_id, NULL, &tags);
  5203. + yaffs_handle_chunk_update(dev, chunk_id, &tags);
  5204. + } else {
  5205. + dev->n_unmarked_deletions++;
  5206. + }
  5207. +
  5208. + /* Pull out of the management area.
  5209. + * If the whole block became dirty, this will kick off an erasure.
  5210. + */
  5211. + if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING ||
  5212. + bi->block_state == YAFFS_BLOCK_STATE_FULL ||
  5213. + bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
  5214. + bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
  5215. + dev->n_free_chunks++;
  5216. + yaffs_clear_chunk_bit(dev, block, page);
  5217. + bi->pages_in_use--;
  5218. +
  5219. + if (bi->pages_in_use == 0 &&
  5220. + !bi->has_shrink_hdr &&
  5221. + bi->block_state != YAFFS_BLOCK_STATE_ALLOCATING &&
  5222. + bi->block_state != YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  5223. + yaffs_block_became_dirty(dev, block);
  5224. + }
  5225. + }
  5226. +}
  5227. +
  5228. +static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
  5229. + const u8 *buffer, int n_bytes, int use_reserve)
  5230. +{
  5231. + /* Find old chunk Need to do this to get serial number
  5232. + * Write new one and patch into tree.
  5233. + * Invalidate old tags.
  5234. + */
  5235. +
  5236. + int prev_chunk_id;
  5237. + struct yaffs_ext_tags prev_tags;
  5238. + int new_chunk_id;
  5239. + struct yaffs_ext_tags new_tags;
  5240. + struct yaffs_dev *dev = in->my_dev;
  5241. +
  5242. + yaffs_check_gc(dev, 0);
  5243. +
  5244. + /* Get the previous chunk at this location in the file if it exists.
  5245. + * If it does not exist then put a zero into the tree. This creates
  5246. + * the tnode now, rather than later when it is harder to clean up.
  5247. + */
  5248. + prev_chunk_id = yaffs_find_chunk_in_file(in, inode_chunk, &prev_tags);
  5249. + if (prev_chunk_id < 1 &&
  5250. + !yaffs_put_chunk_in_file(in, inode_chunk, 0, 0))
  5251. + return 0;
  5252. +
  5253. + /* Set up new tags */
  5254. + memset(&new_tags, 0, sizeof(new_tags));
  5255. +
  5256. + new_tags.chunk_id = inode_chunk;
  5257. + new_tags.obj_id = in->obj_id;
  5258. + new_tags.serial_number =
  5259. + (prev_chunk_id > 0) ? prev_tags.serial_number + 1 : 1;
  5260. + new_tags.n_bytes = n_bytes;
  5261. +
  5262. + if (n_bytes < 1 || n_bytes > dev->param.total_bytes_per_chunk) {
  5263. + yaffs_trace(YAFFS_TRACE_ERROR,
  5264. + "Writing %d bytes to chunk!!!!!!!!!",
  5265. + n_bytes);
  5266. + BUG();
  5267. + }
  5268. +
  5269. + new_chunk_id =
  5270. + yaffs_write_new_chunk(dev, buffer, &new_tags, use_reserve);
  5271. +
  5272. + if (new_chunk_id > 0) {
  5273. + yaffs_put_chunk_in_file(in, inode_chunk, new_chunk_id, 0);
  5274. +
  5275. + if (prev_chunk_id > 0)
  5276. + yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);
  5277. +
  5278. + yaffs_verify_file_sane(in);
  5279. + }
  5280. + return new_chunk_id;
  5281. +
  5282. +}
  5283. +
  5284. +
  5285. +
  5286. +static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set,
  5287. + const YCHAR *name, const void *value, int size,
  5288. + int flags)
  5289. +{
  5290. + struct yaffs_xattr_mod xmod;
  5291. + int result;
  5292. +
  5293. + xmod.set = set;
  5294. + xmod.name = name;
  5295. + xmod.data = value;
  5296. + xmod.size = size;
  5297. + xmod.flags = flags;
  5298. + xmod.result = -ENOSPC;
  5299. +
  5300. + result = yaffs_update_oh(obj, NULL, 0, 0, 0, &xmod);
  5301. +
  5302. + if (result > 0)
  5303. + return xmod.result;
  5304. + else
  5305. + return -ENOSPC;
  5306. +}
  5307. +
  5308. +static int yaffs_apply_xattrib_mod(struct yaffs_obj *obj, char *buffer,
  5309. + struct yaffs_xattr_mod *xmod)
  5310. +{
  5311. + int retval = 0;
  5312. + int x_offs = sizeof(struct yaffs_obj_hdr);
  5313. + struct yaffs_dev *dev = obj->my_dev;
  5314. + int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
  5315. + char *x_buffer = buffer + x_offs;
  5316. +
  5317. + if (xmod->set)
  5318. + retval =
  5319. + nval_set(x_buffer, x_size, xmod->name, xmod->data,
  5320. + xmod->size, xmod->flags);
  5321. + else
  5322. + retval = nval_del(x_buffer, x_size, xmod->name);
  5323. +
  5324. + obj->has_xattr = nval_hasvalues(x_buffer, x_size);
  5325. + obj->xattr_known = 1;
  5326. + xmod->result = retval;
  5327. +
  5328. + return retval;
  5329. +}
  5330. +
  5331. +static int yaffs_do_xattrib_fetch(struct yaffs_obj *obj, const YCHAR *name,
  5332. + void *value, int size)
  5333. +{
  5334. + char *buffer = NULL;
  5335. + int result;
  5336. + struct yaffs_ext_tags tags;
  5337. + struct yaffs_dev *dev = obj->my_dev;
  5338. + int x_offs = sizeof(struct yaffs_obj_hdr);
  5339. + int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
  5340. + char *x_buffer;
  5341. + int retval = 0;
  5342. +
  5343. + if (obj->hdr_chunk < 1)
  5344. + return -ENODATA;
  5345. +
  5346. + /* If we know that the object has no xattribs then don't do all the
  5347. + * reading and parsing.
  5348. + */
  5349. + if (obj->xattr_known && !obj->has_xattr) {
  5350. + if (name)
  5351. + return -ENODATA;
  5352. + else
  5353. + return 0;
  5354. + }
  5355. +
  5356. + buffer = (char *)yaffs_get_temp_buffer(dev);
  5357. + if (!buffer)
  5358. + return -ENOMEM;
  5359. +
  5360. + result =
  5361. + yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, (u8 *) buffer, &tags);
  5362. +
  5363. + if (result != YAFFS_OK)
  5364. + retval = -ENOENT;
  5365. + else {
  5366. + x_buffer = buffer + x_offs;
  5367. +
  5368. + if (!obj->xattr_known) {
  5369. + obj->has_xattr = nval_hasvalues(x_buffer, x_size);
  5370. + obj->xattr_known = 1;
  5371. + }
  5372. +
  5373. + if (name)
  5374. + retval = nval_get(x_buffer, x_size, name, value, size);
  5375. + else
  5376. + retval = nval_list(x_buffer, x_size, value, size);
  5377. + }
  5378. + yaffs_release_temp_buffer(dev, (u8 *) buffer);
  5379. + return retval;
  5380. +}
  5381. +
  5382. +int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR * name,
  5383. + const void *value, int size, int flags)
  5384. +{
  5385. + return yaffs_do_xattrib_mod(obj, 1, name, value, size, flags);
  5386. +}
  5387. +
  5388. +int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR * name)
  5389. +{
  5390. + return yaffs_do_xattrib_mod(obj, 0, name, NULL, 0, 0);
  5391. +}
  5392. +
  5393. +int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR * name, void *value,
  5394. + int size)
  5395. +{
  5396. + return yaffs_do_xattrib_fetch(obj, name, value, size);
  5397. +}
  5398. +
  5399. +int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size)
  5400. +{
  5401. + return yaffs_do_xattrib_fetch(obj, NULL, buffer, size);
  5402. +}
  5403. +
  5404. +static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
  5405. +{
  5406. + u8 *buf;
  5407. + struct yaffs_obj_hdr *oh;
  5408. + struct yaffs_dev *dev;
  5409. + struct yaffs_ext_tags tags;
  5410. + int result;
  5411. + int alloc_failed = 0;
  5412. +
  5413. + if (!in || !in->lazy_loaded || in->hdr_chunk < 1)
  5414. + return;
  5415. +
  5416. + dev = in->my_dev;
  5417. + in->lazy_loaded = 0;
  5418. + buf = yaffs_get_temp_buffer(dev);
  5419. +
  5420. + result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
  5421. + oh = (struct yaffs_obj_hdr *)buf;
  5422. +
  5423. + in->yst_mode = oh->yst_mode;
  5424. + yaffs_load_attribs(in, oh);
  5425. + yaffs_set_obj_name_from_oh(in, oh);
  5426. +
  5427. + if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
  5428. + in->variant.symlink_variant.alias =
  5429. + yaffs_clone_str(oh->alias);
  5430. + if (!in->variant.symlink_variant.alias)
  5431. + alloc_failed = 1; /* Not returned */
  5432. + }
  5433. + yaffs_release_temp_buffer(dev, buf);
  5434. +}
  5435. +
  5436. +static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name,
  5437. + const YCHAR *oh_name, int buff_size)
  5438. +{
  5439. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  5440. + if (dev->param.auto_unicode) {
  5441. + if (*oh_name) {
  5442. + /* It is an ASCII name, do an ASCII to
  5443. + * unicode conversion */
  5444. + const char *ascii_oh_name = (const char *)oh_name;
  5445. + int n = buff_size - 1;
  5446. + while (n > 0 && *ascii_oh_name) {
  5447. + *name = *ascii_oh_name;
  5448. + name++;
  5449. + ascii_oh_name++;
  5450. + n--;
  5451. + }
  5452. + } else {
  5453. + strncpy(name, oh_name + 1, buff_size - 1);
  5454. + }
  5455. + } else {
  5456. +#else
  5457. + (void) dev;
  5458. + {
  5459. +#endif
  5460. + strncpy(name, oh_name, buff_size - 1);
  5461. + }
  5462. +}
  5463. +
  5464. +static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name,
  5465. + const YCHAR *name)
  5466. +{
  5467. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  5468. +
  5469. + int is_ascii;
  5470. + YCHAR *w;
  5471. +
  5472. + if (dev->param.auto_unicode) {
  5473. +
  5474. + is_ascii = 1;
  5475. + w = name;
  5476. +
  5477. + /* Figure out if the name will fit in ascii character set */
  5478. + while (is_ascii && *w) {
  5479. + if ((*w) & 0xff00)
  5480. + is_ascii = 0;
  5481. + w++;
  5482. + }
  5483. +
  5484. + if (is_ascii) {
  5485. + /* It is an ASCII name, so convert unicode to ascii */
  5486. + char *ascii_oh_name = (char *)oh_name;
  5487. + int n = YAFFS_MAX_NAME_LENGTH - 1;
  5488. + while (n > 0 && *name) {
  5489. + *ascii_oh_name = *name;
  5490. + name++;
  5491. + ascii_oh_name++;
  5492. + n--;
  5493. + }
  5494. + } else {
  5495. + /* Unicode name, so save starting at the second YCHAR */
  5496. + *oh_name = 0;
  5497. + strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2);
  5498. + }
  5499. + } else {
  5500. +#else
  5501. + dev = dev;
  5502. + {
  5503. +#endif
  5504. + strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
  5505. + }
  5506. +}
  5507. +
  5508. +/* UpdateObjectHeader updates the header on NAND for an object.
  5509. + * If name is not NULL, then that new name is used.
  5510. + */
  5511. +int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
  5512. + int is_shrink, int shadows, struct yaffs_xattr_mod *xmod)
  5513. +{
  5514. +
  5515. + struct yaffs_block_info *bi;
  5516. + struct yaffs_dev *dev = in->my_dev;
  5517. + int prev_chunk_id;
  5518. + int ret_val = 0;
  5519. + int result = 0;
  5520. + int new_chunk_id;
  5521. + struct yaffs_ext_tags new_tags;
  5522. + struct yaffs_ext_tags old_tags;
  5523. + const YCHAR *alias = NULL;
  5524. + u8 *buffer = NULL;
  5525. + YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1];
  5526. + struct yaffs_obj_hdr *oh = NULL;
  5527. + loff_t file_size = 0;
  5528. +
  5529. + strcpy(old_name, _Y("silly old name"));
  5530. +
  5531. + if (in->fake && in != dev->root_dir && !force && !xmod)
  5532. + return ret_val;
  5533. +
  5534. + yaffs_check_gc(dev, 0);
  5535. + yaffs_check_obj_details_loaded(in);
  5536. +
  5537. + buffer = yaffs_get_temp_buffer(in->my_dev);
  5538. + oh = (struct yaffs_obj_hdr *)buffer;
  5539. +
  5540. + prev_chunk_id = in->hdr_chunk;
  5541. +
  5542. + if (prev_chunk_id > 0) {
  5543. + result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,
  5544. + buffer, &old_tags);
  5545. +
  5546. + yaffs_verify_oh(in, oh, &old_tags, 0);
  5547. + memcpy(old_name, oh->name, sizeof(oh->name));
  5548. + memset(buffer, 0xff, sizeof(struct yaffs_obj_hdr));
  5549. + } else {
  5550. + memset(buffer, 0xff, dev->data_bytes_per_chunk);
  5551. + }
  5552. +
  5553. + oh->type = in->variant_type;
  5554. + oh->yst_mode = in->yst_mode;
  5555. + oh->shadows_obj = oh->inband_shadowed_obj_id = shadows;
  5556. +
  5557. + yaffs_load_attribs_oh(oh, in);
  5558. +
  5559. + if (in->parent)
  5560. + oh->parent_obj_id = in->parent->obj_id;
  5561. + else
  5562. + oh->parent_obj_id = 0;
  5563. +
  5564. + if (name && *name) {
  5565. + memset(oh->name, 0, sizeof(oh->name));
  5566. + yaffs_load_oh_from_name(dev, oh->name, name);
  5567. + } else if (prev_chunk_id > 0) {
  5568. + memcpy(oh->name, old_name, sizeof(oh->name));
  5569. + } else {
  5570. + memset(oh->name, 0, sizeof(oh->name));
  5571. + }
  5572. +
  5573. + oh->is_shrink = is_shrink;
  5574. +
  5575. + switch (in->variant_type) {
  5576. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  5577. + /* Should not happen */
  5578. + break;
  5579. + case YAFFS_OBJECT_TYPE_FILE:
  5580. + if (oh->parent_obj_id != YAFFS_OBJECTID_DELETED &&
  5581. + oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED)
  5582. + file_size = in->variant.file_variant.file_size;
  5583. + yaffs_oh_size_load(oh, file_size);
  5584. + break;
  5585. + case YAFFS_OBJECT_TYPE_HARDLINK:
  5586. + oh->equiv_id = in->variant.hardlink_variant.equiv_id;
  5587. + break;
  5588. + case YAFFS_OBJECT_TYPE_SPECIAL:
  5589. + /* Do nothing */
  5590. + break;
  5591. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  5592. + /* Do nothing */
  5593. + break;
  5594. + case YAFFS_OBJECT_TYPE_SYMLINK:
  5595. + alias = in->variant.symlink_variant.alias;
  5596. + if (!alias)
  5597. + alias = _Y("no alias");
  5598. + strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH);
  5599. + oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
  5600. + break;
  5601. + }
  5602. +
  5603. + /* process any xattrib modifications */
  5604. + if (xmod)
  5605. + yaffs_apply_xattrib_mod(in, (char *)buffer, xmod);
  5606. +
  5607. + /* Tags */
  5608. + memset(&new_tags, 0, sizeof(new_tags));
  5609. + in->serial++;
  5610. + new_tags.chunk_id = 0;
  5611. + new_tags.obj_id = in->obj_id;
  5612. + new_tags.serial_number = in->serial;
  5613. +
  5614. + /* Add extra info for file header */
  5615. + new_tags.extra_available = 1;
  5616. + new_tags.extra_parent_id = oh->parent_obj_id;
  5617. + new_tags.extra_file_size = file_size;
  5618. + new_tags.extra_is_shrink = oh->is_shrink;
  5619. + new_tags.extra_equiv_id = oh->equiv_id;
  5620. + new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0;
  5621. + new_tags.extra_obj_type = in->variant_type;
  5622. + yaffs_verify_oh(in, oh, &new_tags, 1);
  5623. +
  5624. + /* Create new chunk in NAND */
  5625. + new_chunk_id =
  5626. + yaffs_write_new_chunk(dev, buffer, &new_tags,
  5627. + (prev_chunk_id > 0) ? 1 : 0);
  5628. +
  5629. + if (buffer)
  5630. + yaffs_release_temp_buffer(dev, buffer);
  5631. +
  5632. + if (new_chunk_id < 0)
  5633. + return new_chunk_id;
  5634. +
  5635. + in->hdr_chunk = new_chunk_id;
  5636. +
  5637. + if (prev_chunk_id > 0)
  5638. + yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);
  5639. +
  5640. + if (!yaffs_obj_cache_dirty(in))
  5641. + in->dirty = 0;
  5642. +
  5643. + /* If this was a shrink, then mark the block
  5644. + * that the chunk lives on */
  5645. + if (is_shrink) {
  5646. + bi = yaffs_get_block_info(in->my_dev,
  5647. + new_chunk_id /
  5648. + in->my_dev->param.chunks_per_block);
  5649. + bi->has_shrink_hdr = 1;
  5650. + }
  5651. +
  5652. +
  5653. + return new_chunk_id;
  5654. +}
  5655. +
  5656. +/*--------------------- File read/write ------------------------
  5657. + * Read and write have very similar structures.
  5658. + * In general the read/write has three parts to it
  5659. + * An incomplete chunk to start with (if the read/write is not chunk-aligned)
  5660. + * Some complete chunks
  5661. + * An incomplete chunk to end off with
  5662. + *
  5663. + * Curve-balls: the first chunk might also be the last chunk.
  5664. + */
  5665. +
  5666. +int yaffs_file_rd(struct yaffs_obj *in, u8 * buffer, loff_t offset, int n_bytes)
  5667. +{
  5668. + int chunk;
  5669. + u32 start;
  5670. + int n_copy;
  5671. + int n = n_bytes;
  5672. + int n_done = 0;
  5673. + struct yaffs_cache *cache;
  5674. + struct yaffs_dev *dev;
  5675. +
  5676. + dev = in->my_dev;
  5677. +
  5678. + while (n > 0) {
  5679. + yaffs_addr_to_chunk(dev, offset, &chunk, &start);
  5680. + chunk++;
  5681. +
  5682. + /* OK now check for the curveball where the start and end are in
  5683. + * the same chunk.
  5684. + */
  5685. + if ((start + n) < dev->data_bytes_per_chunk)
  5686. + n_copy = n;
  5687. + else
  5688. + n_copy = dev->data_bytes_per_chunk - start;
  5689. +
  5690. + cache = yaffs_find_chunk_cache(in, chunk);
  5691. +
  5692. + /* If the chunk is already in the cache or it is less than
  5693. + * a whole chunk or we're using inband tags then use the cache
  5694. + * (if there is caching) else bypass the cache.
  5695. + */
  5696. + if (cache || n_copy != dev->data_bytes_per_chunk ||
  5697. + dev->param.inband_tags) {
  5698. + if (dev->param.n_caches > 0) {
  5699. +
  5700. + /* If we can't find the data in the cache,
  5701. + * then load it up. */
  5702. +
  5703. + if (!cache) {
  5704. + cache =
  5705. + yaffs_grab_chunk_cache(in->my_dev);
  5706. + cache->object = in;
  5707. + cache->chunk_id = chunk;
  5708. + cache->dirty = 0;
  5709. + cache->locked = 0;
  5710. + yaffs_rd_data_obj(in, chunk,
  5711. + cache->data);
  5712. + cache->n_bytes = 0;
  5713. + }
  5714. +
  5715. + yaffs_use_cache(dev, cache, 0);
  5716. +
  5717. + cache->locked = 1;
  5718. +
  5719. + memcpy(buffer, &cache->data[start], n_copy);
  5720. +
  5721. + cache->locked = 0;
  5722. + } else {
  5723. + /* Read into the local buffer then copy.. */
  5724. +
  5725. + u8 *local_buffer =
  5726. + yaffs_get_temp_buffer(dev);
  5727. + yaffs_rd_data_obj(in, chunk, local_buffer);
  5728. +
  5729. + memcpy(buffer, &local_buffer[start], n_copy);
  5730. +
  5731. + yaffs_release_temp_buffer(dev, local_buffer);
  5732. + }
  5733. + } else {
  5734. + /* A full chunk. Read directly into the buffer. */
  5735. + yaffs_rd_data_obj(in, chunk, buffer);
  5736. + }
  5737. + n -= n_copy;
  5738. + offset += n_copy;
  5739. + buffer += n_copy;
  5740. + n_done += n_copy;
  5741. + }
  5742. + return n_done;
  5743. +}
  5744. +
  5745. +int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
  5746. + int n_bytes, int write_through)
  5747. +{
  5748. +
  5749. + int chunk;
  5750. + u32 start;
  5751. + int n_copy;
  5752. + int n = n_bytes;
  5753. + int n_done = 0;
  5754. + int n_writeback;
  5755. + loff_t start_write = offset;
  5756. + int chunk_written = 0;
  5757. + u32 n_bytes_read;
  5758. + loff_t chunk_start;
  5759. + struct yaffs_dev *dev;
  5760. +
  5761. + dev = in->my_dev;
  5762. +
  5763. + while (n > 0 && chunk_written >= 0) {
  5764. + yaffs_addr_to_chunk(dev, offset, &chunk, &start);
  5765. +
  5766. + if (((loff_t)chunk) *
  5767. + dev->data_bytes_per_chunk + start != offset ||
  5768. + start >= dev->data_bytes_per_chunk) {
  5769. + yaffs_trace(YAFFS_TRACE_ERROR,
  5770. + "AddrToChunk of offset %lld gives chunk %d start %d",
  5771. + offset, chunk, start);
  5772. + }
  5773. + chunk++; /* File pos to chunk in file offset */
  5774. +
  5775. + /* OK now check for the curveball where the start and end are in
  5776. + * the same chunk.
  5777. + */
  5778. +
  5779. + if ((start + n) < dev->data_bytes_per_chunk) {
  5780. + n_copy = n;
  5781. +
  5782. + /* Now calculate how many bytes to write back....
  5783. + * If we're overwriting and not writing to then end of
  5784. + * file then we need to write back as much as was there
  5785. + * before.
  5786. + */
  5787. +
  5788. + chunk_start = (((loff_t)(chunk - 1)) *
  5789. + dev->data_bytes_per_chunk);
  5790. +
  5791. + if (chunk_start > in->variant.file_variant.file_size)
  5792. + n_bytes_read = 0; /* Past end of file */
  5793. + else
  5794. + n_bytes_read =
  5795. + in->variant.file_variant.file_size -
  5796. + chunk_start;
  5797. +
  5798. + if (n_bytes_read > dev->data_bytes_per_chunk)
  5799. + n_bytes_read = dev->data_bytes_per_chunk;
  5800. +
  5801. + n_writeback =
  5802. + (n_bytes_read >
  5803. + (start + n)) ? n_bytes_read : (start + n);
  5804. +
  5805. + if (n_writeback < 0 ||
  5806. + n_writeback > dev->data_bytes_per_chunk)
  5807. + BUG();
  5808. +
  5809. + } else {
  5810. + n_copy = dev->data_bytes_per_chunk - start;
  5811. + n_writeback = dev->data_bytes_per_chunk;
  5812. + }
  5813. +
  5814. + if (n_copy != dev->data_bytes_per_chunk ||
  5815. + !dev->param.cache_bypass_aligned ||
  5816. + dev->param.inband_tags) {
  5817. + /* An incomplete start or end chunk (or maybe both
  5818. + * start and end chunk), or we're using inband tags,
  5819. + * or we're forcing writes through the cache,
  5820. + * so we want to use the cache buffers.
  5821. + */
  5822. + if (dev->param.n_caches > 0) {
  5823. + struct yaffs_cache *cache;
  5824. +
  5825. + /* If we can't find the data in the cache, then
  5826. + * load the cache */
  5827. + cache = yaffs_find_chunk_cache(in, chunk);
  5828. +
  5829. + if (!cache &&
  5830. + yaffs_check_alloc_available(dev, 1)) {
  5831. + cache = yaffs_grab_chunk_cache(dev);
  5832. + cache->object = in;
  5833. + cache->chunk_id = chunk;
  5834. + cache->dirty = 0;
  5835. + cache->locked = 0;
  5836. + yaffs_rd_data_obj(in, chunk,
  5837. + cache->data);
  5838. + } else if (cache &&
  5839. + !cache->dirty &&
  5840. + !yaffs_check_alloc_available(dev,
  5841. + 1)) {
  5842. + /* Drop the cache if it was a read cache
  5843. + * item and no space check has been made
  5844. + * for it.
  5845. + */
  5846. + cache = NULL;
  5847. + }
  5848. +
  5849. + if (cache) {
  5850. + yaffs_use_cache(dev, cache, 1);
  5851. + cache->locked = 1;
  5852. +
  5853. + memcpy(&cache->data[start], buffer,
  5854. + n_copy);
  5855. +
  5856. + cache->locked = 0;
  5857. + cache->n_bytes = n_writeback;
  5858. +
  5859. + if (write_through) {
  5860. + chunk_written =
  5861. + yaffs_wr_data_obj
  5862. + (cache->object,
  5863. + cache->chunk_id,
  5864. + cache->data,
  5865. + cache->n_bytes, 1);
  5866. + cache->dirty = 0;
  5867. + }
  5868. + } else {
  5869. + chunk_written = -1; /* fail write */
  5870. + }
  5871. + } else {
  5872. + /* An incomplete start or end chunk (or maybe
  5873. + * both start and end chunk). Read into the
  5874. + * local buffer then copy over and write back.
  5875. + */
  5876. +
  5877. + u8 *local_buffer = yaffs_get_temp_buffer(dev);
  5878. +
  5879. + yaffs_rd_data_obj(in, chunk, local_buffer);
  5880. + memcpy(&local_buffer[start], buffer, n_copy);
  5881. +
  5882. + chunk_written =
  5883. + yaffs_wr_data_obj(in, chunk,
  5884. + local_buffer,
  5885. + n_writeback, 0);
  5886. +
  5887. + yaffs_release_temp_buffer(dev, local_buffer);
  5888. + }
  5889. + } else {
  5890. + /* A full chunk. Write directly from the buffer. */
  5891. +
  5892. + chunk_written =
  5893. + yaffs_wr_data_obj(in, chunk, buffer,
  5894. + dev->data_bytes_per_chunk, 0);
  5895. +
  5896. + /* Since we've overwritten the cached data,
  5897. + * we better invalidate it. */
  5898. + yaffs_invalidate_chunk_cache(in, chunk);
  5899. + }
  5900. +
  5901. + if (chunk_written >= 0) {
  5902. + n -= n_copy;
  5903. + offset += n_copy;
  5904. + buffer += n_copy;
  5905. + n_done += n_copy;
  5906. + }
  5907. + }
  5908. +
  5909. + /* Update file object */
  5910. +
  5911. + if ((start_write + n_done) > in->variant.file_variant.file_size)
  5912. + in->variant.file_variant.file_size = (start_write + n_done);
  5913. +
  5914. + in->dirty = 1;
  5915. + return n_done;
  5916. +}
  5917. +
  5918. +int yaffs_wr_file(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
  5919. + int n_bytes, int write_through)
  5920. +{
  5921. + yaffs2_handle_hole(in, offset);
  5922. + return yaffs_do_file_wr(in, buffer, offset, n_bytes, write_through);
  5923. +}
  5924. +
  5925. +/* ---------------------- File resizing stuff ------------------ */
  5926. +
  5927. +static void yaffs_prune_chunks(struct yaffs_obj *in, loff_t new_size)
  5928. +{
  5929. +
  5930. + struct yaffs_dev *dev = in->my_dev;
  5931. + loff_t old_size = in->variant.file_variant.file_size;
  5932. + int i;
  5933. + int chunk_id;
  5934. + u32 dummy;
  5935. + int last_del;
  5936. + int start_del;
  5937. +
  5938. + if (old_size > 0)
  5939. + yaffs_addr_to_chunk(dev, old_size - 1, &last_del, &dummy);
  5940. + else
  5941. + last_del = 0;
  5942. +
  5943. + yaffs_addr_to_chunk(dev, new_size + dev->data_bytes_per_chunk - 1,
  5944. + &start_del, &dummy);
  5945. + last_del++;
  5946. + start_del++;
  5947. +
  5948. + /* Delete backwards so that we don't end up with holes if
  5949. + * power is lost part-way through the operation.
  5950. + */
  5951. + for (i = last_del; i >= start_del; i--) {
  5952. + /* NB this could be optimised somewhat,
  5953. + * eg. could retrieve the tags and write them without
  5954. + * using yaffs_chunk_del
  5955. + */
  5956. +
  5957. + chunk_id = yaffs_find_del_file_chunk(in, i, NULL);
  5958. +
  5959. + if (chunk_id < 1)
  5960. + continue;
  5961. +
  5962. + if (chunk_id <
  5963. + (dev->internal_start_block * dev->param.chunks_per_block) ||
  5964. + chunk_id >=
  5965. + ((dev->internal_end_block + 1) *
  5966. + dev->param.chunks_per_block)) {
  5967. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  5968. + "Found daft chunk_id %d for %d",
  5969. + chunk_id, i);
  5970. + } else {
  5971. + in->n_data_chunks--;
  5972. + yaffs_chunk_del(dev, chunk_id, 1, __LINE__);
  5973. + }
  5974. + }
  5975. +}
  5976. +
  5977. +void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size)
  5978. +{
  5979. + int new_full;
  5980. + u32 new_partial;
  5981. + struct yaffs_dev *dev = obj->my_dev;
  5982. +
  5983. + yaffs_addr_to_chunk(dev, new_size, &new_full, &new_partial);
  5984. +
  5985. + yaffs_prune_chunks(obj, new_size);
  5986. +
  5987. + if (new_partial != 0) {
  5988. + int last_chunk = 1 + new_full;
  5989. + u8 *local_buffer = yaffs_get_temp_buffer(dev);
  5990. +
  5991. + /* Rewrite the last chunk with its new size and zero pad */
  5992. + yaffs_rd_data_obj(obj, last_chunk, local_buffer);
  5993. + memset(local_buffer + new_partial, 0,
  5994. + dev->data_bytes_per_chunk - new_partial);
  5995. +
  5996. + yaffs_wr_data_obj(obj, last_chunk, local_buffer,
  5997. + new_partial, 1);
  5998. +
  5999. + yaffs_release_temp_buffer(dev, local_buffer);
  6000. + }
  6001. +
  6002. + obj->variant.file_variant.file_size = new_size;
  6003. +
  6004. + yaffs_prune_tree(dev, &obj->variant.file_variant);
  6005. +}
  6006. +
  6007. +int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
  6008. +{
  6009. + struct yaffs_dev *dev = in->my_dev;
  6010. + loff_t old_size = in->variant.file_variant.file_size;
  6011. +
  6012. + yaffs_flush_file_cache(in);
  6013. + yaffs_invalidate_whole_cache(in);
  6014. +
  6015. + yaffs_check_gc(dev, 0);
  6016. +
  6017. + if (in->variant_type != YAFFS_OBJECT_TYPE_FILE)
  6018. + return YAFFS_FAIL;
  6019. +
  6020. + if (new_size == old_size)
  6021. + return YAFFS_OK;
  6022. +
  6023. + if (new_size > old_size) {
  6024. + yaffs2_handle_hole(in, new_size);
  6025. + in->variant.file_variant.file_size = new_size;
  6026. + } else {
  6027. + /* new_size < old_size */
  6028. + yaffs_resize_file_down(in, new_size);
  6029. + }
  6030. +
  6031. + /* Write a new object header to reflect the resize.
  6032. + * show we've shrunk the file, if need be
  6033. + * Do this only if the file is not in the deleted directories
  6034. + * and is not shadowed.
  6035. + */
  6036. + if (in->parent &&
  6037. + !in->is_shadowed &&
  6038. + in->parent->obj_id != YAFFS_OBJECTID_UNLINKED &&
  6039. + in->parent->obj_id != YAFFS_OBJECTID_DELETED)
  6040. + yaffs_update_oh(in, NULL, 0, 0, 0, NULL);
  6041. +
  6042. + return YAFFS_OK;
  6043. +}
  6044. +
  6045. +int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync)
  6046. +{
  6047. + if (!in->dirty)
  6048. + return YAFFS_OK;
  6049. +
  6050. + yaffs_flush_file_cache(in);
  6051. +
  6052. + if (data_sync)
  6053. + return YAFFS_OK;
  6054. +
  6055. + if (update_time)
  6056. + yaffs_load_current_time(in, 0, 0);
  6057. +
  6058. + return (yaffs_update_oh(in, NULL, 0, 0, 0, NULL) >= 0) ?
  6059. + YAFFS_OK : YAFFS_FAIL;
  6060. +}
  6061. +
  6062. +
  6063. +/* yaffs_del_file deletes the whole file data
  6064. + * and the inode associated with the file.
  6065. + * It does not delete the links associated with the file.
  6066. + */
  6067. +static int yaffs_unlink_file_if_needed(struct yaffs_obj *in)
  6068. +{
  6069. + int ret_val;
  6070. + int del_now = 0;
  6071. + struct yaffs_dev *dev = in->my_dev;
  6072. +
  6073. + if (!in->my_inode)
  6074. + del_now = 1;
  6075. +
  6076. + if (del_now) {
  6077. + ret_val =
  6078. + yaffs_change_obj_name(in, in->my_dev->del_dir,
  6079. + _Y("deleted"), 0, 0);
  6080. + yaffs_trace(YAFFS_TRACE_TRACING,
  6081. + "yaffs: immediate deletion of file %d",
  6082. + in->obj_id);
  6083. + in->deleted = 1;
  6084. + in->my_dev->n_deleted_files++;
  6085. + if (dev->param.disable_soft_del || dev->param.is_yaffs2)
  6086. + yaffs_resize_file(in, 0);
  6087. + yaffs_soft_del_file(in);
  6088. + } else {
  6089. + ret_val =
  6090. + yaffs_change_obj_name(in, in->my_dev->unlinked_dir,
  6091. + _Y("unlinked"), 0, 0);
  6092. + }
  6093. + return ret_val;
  6094. +}
  6095. +
  6096. +static int yaffs_del_file(struct yaffs_obj *in)
  6097. +{
  6098. + int ret_val = YAFFS_OK;
  6099. + int deleted; /* Need to cache value on stack if in is freed */
  6100. + struct yaffs_dev *dev = in->my_dev;
  6101. +
  6102. + if (dev->param.disable_soft_del || dev->param.is_yaffs2)
  6103. + yaffs_resize_file(in, 0);
  6104. +
  6105. + if (in->n_data_chunks > 0) {
  6106. + /* Use soft deletion if there is data in the file.
  6107. + * That won't be the case if it has been resized to zero.
  6108. + */
  6109. + if (!in->unlinked)
  6110. + ret_val = yaffs_unlink_file_if_needed(in);
  6111. +
  6112. + deleted = in->deleted;
  6113. +
  6114. + if (ret_val == YAFFS_OK && in->unlinked && !in->deleted) {
  6115. + in->deleted = 1;
  6116. + deleted = 1;
  6117. + in->my_dev->n_deleted_files++;
  6118. + yaffs_soft_del_file(in);
  6119. + }
  6120. + return deleted ? YAFFS_OK : YAFFS_FAIL;
  6121. + } else {
  6122. + /* The file has no data chunks so we toss it immediately */
  6123. + yaffs_free_tnode(in->my_dev, in->variant.file_variant.top);
  6124. + in->variant.file_variant.top = NULL;
  6125. + yaffs_generic_obj_del(in);
  6126. +
  6127. + return YAFFS_OK;
  6128. + }
  6129. +}
  6130. +
  6131. +int yaffs_is_non_empty_dir(struct yaffs_obj *obj)
  6132. +{
  6133. + return (obj &&
  6134. + obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) &&
  6135. + !(list_empty(&obj->variant.dir_variant.children));
  6136. +}
  6137. +
  6138. +static int yaffs_del_dir(struct yaffs_obj *obj)
  6139. +{
  6140. + /* First check that the directory is empty. */
  6141. + if (yaffs_is_non_empty_dir(obj))
  6142. + return YAFFS_FAIL;
  6143. +
  6144. + return yaffs_generic_obj_del(obj);
  6145. +}
  6146. +
  6147. +static int yaffs_del_symlink(struct yaffs_obj *in)
  6148. +{
  6149. + kfree(in->variant.symlink_variant.alias);
  6150. + in->variant.symlink_variant.alias = NULL;
  6151. +
  6152. + return yaffs_generic_obj_del(in);
  6153. +}
  6154. +
  6155. +static int yaffs_del_link(struct yaffs_obj *in)
  6156. +{
  6157. + /* remove this hardlink from the list associated with the equivalent
  6158. + * object
  6159. + */
  6160. + list_del_init(&in->hard_links);
  6161. + return yaffs_generic_obj_del(in);
  6162. +}
  6163. +
  6164. +int yaffs_del_obj(struct yaffs_obj *obj)
  6165. +{
  6166. + int ret_val = -1;
  6167. +
  6168. + switch (obj->variant_type) {
  6169. + case YAFFS_OBJECT_TYPE_FILE:
  6170. + ret_val = yaffs_del_file(obj);
  6171. + break;
  6172. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  6173. + if (!list_empty(&obj->variant.dir_variant.dirty)) {
  6174. + yaffs_trace(YAFFS_TRACE_BACKGROUND,
  6175. + "Remove object %d from dirty directories",
  6176. + obj->obj_id);
  6177. + list_del_init(&obj->variant.dir_variant.dirty);
  6178. + }
  6179. + return yaffs_del_dir(obj);
  6180. + break;
  6181. + case YAFFS_OBJECT_TYPE_SYMLINK:
  6182. + ret_val = yaffs_del_symlink(obj);
  6183. + break;
  6184. + case YAFFS_OBJECT_TYPE_HARDLINK:
  6185. + ret_val = yaffs_del_link(obj);
  6186. + break;
  6187. + case YAFFS_OBJECT_TYPE_SPECIAL:
  6188. + ret_val = yaffs_generic_obj_del(obj);
  6189. + break;
  6190. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  6191. + ret_val = 0;
  6192. + break; /* should not happen. */
  6193. + }
  6194. + return ret_val;
  6195. +}
  6196. +
  6197. +
  6198. +static void yaffs_empty_dir_to_dir(struct yaffs_obj *from_dir,
  6199. + struct yaffs_obj *to_dir)
  6200. +{
  6201. + struct yaffs_obj *obj;
  6202. + struct list_head *lh;
  6203. + struct list_head *n;
  6204. +
  6205. + list_for_each_safe(lh, n, &from_dir->variant.dir_variant.children) {
  6206. + obj = list_entry(lh, struct yaffs_obj, siblings);
  6207. + yaffs_add_obj_to_dir(to_dir, obj);
  6208. + }
  6209. +}
  6210. +
  6211. +struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
  6212. + enum yaffs_obj_type type)
  6213. +{
  6214. + /* Tear down the old variant */
  6215. + switch (obj->variant_type) {
  6216. + case YAFFS_OBJECT_TYPE_FILE:
  6217. + /* Nuke file data */
  6218. + yaffs_resize_file(obj, 0);
  6219. + yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
  6220. + obj->variant.file_variant.top = NULL;
  6221. + break;
  6222. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  6223. + /* Put the children in lost and found. */
  6224. + yaffs_empty_dir_to_dir(obj, obj->my_dev->lost_n_found);
  6225. + if (!list_empty(&obj->variant.dir_variant.dirty))
  6226. + list_del_init(&obj->variant.dir_variant.dirty);
  6227. + break;
  6228. + case YAFFS_OBJECT_TYPE_SYMLINK:
  6229. + /* Nuke symplink data */
  6230. + kfree(obj->variant.symlink_variant.alias);
  6231. + obj->variant.symlink_variant.alias = NULL;
  6232. + break;
  6233. + case YAFFS_OBJECT_TYPE_HARDLINK:
  6234. + list_del_init(&obj->hard_links);
  6235. + break;
  6236. + default:
  6237. + break;
  6238. + }
  6239. +
  6240. + memset(&obj->variant, 0, sizeof(obj->variant));
  6241. +
  6242. + /*Set up new variant if the memset is not enough. */
  6243. + switch (type) {
  6244. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  6245. + INIT_LIST_HEAD(&obj->variant.dir_variant.children);
  6246. + INIT_LIST_HEAD(&obj->variant.dir_variant.dirty);
  6247. + break;
  6248. + case YAFFS_OBJECT_TYPE_FILE:
  6249. + case YAFFS_OBJECT_TYPE_SYMLINK:
  6250. + case YAFFS_OBJECT_TYPE_HARDLINK:
  6251. + default:
  6252. + break;
  6253. + }
  6254. +
  6255. + obj->variant_type = type;
  6256. +
  6257. + return obj;
  6258. +
  6259. +}
  6260. +
  6261. +static int yaffs_unlink_worker(struct yaffs_obj *obj)
  6262. +{
  6263. + int del_now = 0;
  6264. +
  6265. + if (!obj)
  6266. + return YAFFS_FAIL;
  6267. +
  6268. + if (!obj->my_inode)
  6269. + del_now = 1;
  6270. +
  6271. + yaffs_update_parent(obj->parent);
  6272. +
  6273. + if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
  6274. + return yaffs_del_link(obj);
  6275. + } else if (!list_empty(&obj->hard_links)) {
  6276. + /* Curve ball: We're unlinking an object that has a hardlink.
  6277. + *
  6278. + * This problem arises because we are not strictly following
  6279. + * The Linux link/inode model.
  6280. + *
  6281. + * We can't really delete the object.
  6282. + * Instead, we do the following:
  6283. + * - Select a hardlink.
  6284. + * - Unhook it from the hard links
  6285. + * - Move it from its parent directory so that the rename works.
  6286. + * - Rename the object to the hardlink's name.
  6287. + * - Delete the hardlink
  6288. + */
  6289. +
  6290. + struct yaffs_obj *hl;
  6291. + struct yaffs_obj *parent;
  6292. + int ret_val;
  6293. + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
  6294. +
  6295. + hl = list_entry(obj->hard_links.next, struct yaffs_obj,
  6296. + hard_links);
  6297. +
  6298. + yaffs_get_obj_name(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
  6299. + parent = hl->parent;
  6300. +
  6301. + list_del_init(&hl->hard_links);
  6302. +
  6303. + yaffs_add_obj_to_dir(obj->my_dev->unlinked_dir, hl);
  6304. +
  6305. + ret_val = yaffs_change_obj_name(obj, parent, name, 0, 0);
  6306. +
  6307. + if (ret_val == YAFFS_OK)
  6308. + ret_val = yaffs_generic_obj_del(hl);
  6309. +
  6310. + return ret_val;
  6311. +
  6312. + } else if (del_now) {
  6313. + switch (obj->variant_type) {
  6314. + case YAFFS_OBJECT_TYPE_FILE:
  6315. + return yaffs_del_file(obj);
  6316. + break;
  6317. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  6318. + list_del_init(&obj->variant.dir_variant.dirty);
  6319. + return yaffs_del_dir(obj);
  6320. + break;
  6321. + case YAFFS_OBJECT_TYPE_SYMLINK:
  6322. + return yaffs_del_symlink(obj);
  6323. + break;
  6324. + case YAFFS_OBJECT_TYPE_SPECIAL:
  6325. + return yaffs_generic_obj_del(obj);
  6326. + break;
  6327. + case YAFFS_OBJECT_TYPE_HARDLINK:
  6328. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  6329. + default:
  6330. + return YAFFS_FAIL;
  6331. + }
  6332. + } else if (yaffs_is_non_empty_dir(obj)) {
  6333. + return YAFFS_FAIL;
  6334. + } else {
  6335. + return yaffs_change_obj_name(obj, obj->my_dev->unlinked_dir,
  6336. + _Y("unlinked"), 0, 0);
  6337. + }
  6338. +}
  6339. +
  6340. +static int yaffs_unlink_obj(struct yaffs_obj *obj)
  6341. +{
  6342. + if (obj && obj->unlink_allowed)
  6343. + return yaffs_unlink_worker(obj);
  6344. +
  6345. + return YAFFS_FAIL;
  6346. +}
  6347. +
  6348. +int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR *name)
  6349. +{
  6350. + struct yaffs_obj *obj;
  6351. +
  6352. + obj = yaffs_find_by_name(dir, name);
  6353. + return yaffs_unlink_obj(obj);
  6354. +}
  6355. +
  6356. +/* Note:
  6357. + * If old_name is NULL then we take old_dir as the object to be renamed.
  6358. + */
  6359. +int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR *old_name,
  6360. + struct yaffs_obj *new_dir, const YCHAR *new_name)
  6361. +{
  6362. + struct yaffs_obj *obj = NULL;
  6363. + struct yaffs_obj *existing_target = NULL;
  6364. + int force = 0;
  6365. + int result;
  6366. + struct yaffs_dev *dev;
  6367. +
  6368. + if (!old_dir || old_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  6369. + BUG();
  6370. + return YAFFS_FAIL;
  6371. + }
  6372. + if (!new_dir || new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  6373. + BUG();
  6374. + return YAFFS_FAIL;
  6375. + }
  6376. +
  6377. + dev = old_dir->my_dev;
  6378. +
  6379. +#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
  6380. + /* Special case for case insemsitive systems.
  6381. + * While look-up is case insensitive, the name isn't.
  6382. + * Therefore we might want to change x.txt to X.txt
  6383. + */
  6384. + if (old_dir == new_dir &&
  6385. + old_name && new_name &&
  6386. + strcmp(old_name, new_name) == 0)
  6387. + force = 1;
  6388. +#endif
  6389. +
  6390. + if (strnlen(new_name, YAFFS_MAX_NAME_LENGTH + 1) >
  6391. + YAFFS_MAX_NAME_LENGTH)
  6392. + /* ENAMETOOLONG */
  6393. + return YAFFS_FAIL;
  6394. +
  6395. + if (old_name)
  6396. + obj = yaffs_find_by_name(old_dir, old_name);
  6397. + else{
  6398. + obj = old_dir;
  6399. + old_dir = obj->parent;
  6400. + }
  6401. +
  6402. + if (obj && obj->rename_allowed) {
  6403. + /* Now handle an existing target, if there is one */
  6404. + existing_target = yaffs_find_by_name(new_dir, new_name);
  6405. + if (yaffs_is_non_empty_dir(existing_target)) {
  6406. + return YAFFS_FAIL; /* ENOTEMPTY */
  6407. + } else if (existing_target && existing_target != obj) {
  6408. + /* Nuke the target first, using shadowing,
  6409. + * but only if it isn't the same object.
  6410. + *
  6411. + * Note we must disable gc here otherwise it can mess
  6412. + * up the shadowing.
  6413. + *
  6414. + */
  6415. + dev->gc_disable = 1;
  6416. + yaffs_change_obj_name(obj, new_dir, new_name, force,
  6417. + existing_target->obj_id);
  6418. + existing_target->is_shadowed = 1;
  6419. + yaffs_unlink_obj(existing_target);
  6420. + dev->gc_disable = 0;
  6421. + }
  6422. +
  6423. + result = yaffs_change_obj_name(obj, new_dir, new_name, 1, 0);
  6424. +
  6425. + yaffs_update_parent(old_dir);
  6426. + if (new_dir != old_dir)
  6427. + yaffs_update_parent(new_dir);
  6428. +
  6429. + return result;
  6430. + }
  6431. + return YAFFS_FAIL;
  6432. +}
  6433. +
  6434. +/*----------------------- Initialisation Scanning ---------------------- */
  6435. +
  6436. +void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id,
  6437. + int backward_scanning)
  6438. +{
  6439. + struct yaffs_obj *obj;
  6440. +
  6441. + if (backward_scanning) {
  6442. + /* Handle YAFFS2 case (backward scanning)
  6443. + * If the shadowed object exists then ignore.
  6444. + */
  6445. + obj = yaffs_find_by_number(dev, obj_id);
  6446. + if (obj)
  6447. + return;
  6448. + }
  6449. +
  6450. + /* Let's create it (if it does not exist) assuming it is a file so that
  6451. + * it can do shrinking etc.
  6452. + * We put it in unlinked dir to be cleaned up after the scanning
  6453. + */
  6454. + obj =
  6455. + yaffs_find_or_create_by_number(dev, obj_id, YAFFS_OBJECT_TYPE_FILE);
  6456. + if (!obj)
  6457. + return;
  6458. + obj->is_shadowed = 1;
  6459. + yaffs_add_obj_to_dir(dev->unlinked_dir, obj);
  6460. + obj->variant.file_variant.shrink_size = 0;
  6461. + obj->valid = 1; /* So that we don't read any other info. */
  6462. +}
  6463. +
  6464. +void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list)
  6465. +{
  6466. + struct list_head *lh;
  6467. + struct list_head *save;
  6468. + struct yaffs_obj *hl;
  6469. + struct yaffs_obj *in;
  6470. +
  6471. + list_for_each_safe(lh, save, hard_list) {
  6472. + hl = list_entry(lh, struct yaffs_obj, hard_links);
  6473. + in = yaffs_find_by_number(dev,
  6474. + hl->variant.hardlink_variant.equiv_id);
  6475. +
  6476. + if (in) {
  6477. + /* Add the hardlink pointers */
  6478. + hl->variant.hardlink_variant.equiv_obj = in;
  6479. + list_add(&hl->hard_links, &in->hard_links);
  6480. + } else {
  6481. + /* Todo Need to report/handle this better.
  6482. + * Got a problem... hardlink to a non-existant object
  6483. + */
  6484. + hl->variant.hardlink_variant.equiv_obj = NULL;
  6485. + INIT_LIST_HEAD(&hl->hard_links);
  6486. + }
  6487. + }
  6488. +}
  6489. +
  6490. +static void yaffs_strip_deleted_objs(struct yaffs_dev *dev)
  6491. +{
  6492. + /*
  6493. + * Sort out state of unlinked and deleted objects after scanning.
  6494. + */
  6495. + struct list_head *i;
  6496. + struct list_head *n;
  6497. + struct yaffs_obj *l;
  6498. +
  6499. + if (dev->read_only)
  6500. + return;
  6501. +
  6502. + /* Soft delete all the unlinked files */
  6503. + list_for_each_safe(i, n,
  6504. + &dev->unlinked_dir->variant.dir_variant.children) {
  6505. + l = list_entry(i, struct yaffs_obj, siblings);
  6506. + yaffs_del_obj(l);
  6507. + }
  6508. +
  6509. + list_for_each_safe(i, n, &dev->del_dir->variant.dir_variant.children) {
  6510. + l = list_entry(i, struct yaffs_obj, siblings);
  6511. + yaffs_del_obj(l);
  6512. + }
  6513. +}
  6514. +
  6515. +/*
  6516. + * This code iterates through all the objects making sure that they are rooted.
  6517. + * Any unrooted objects are re-rooted in lost+found.
  6518. + * An object needs to be in one of:
  6519. + * - Directly under deleted, unlinked
  6520. + * - Directly or indirectly under root.
  6521. + *
  6522. + * Note:
  6523. + * This code assumes that we don't ever change the current relationships
  6524. + * between directories:
  6525. + * root_dir->parent == unlinked_dir->parent == del_dir->parent == NULL
  6526. + * lost-n-found->parent == root_dir
  6527. + *
  6528. + * This fixes the problem where directories might have inadvertently been
  6529. + * deleted leaving the object "hanging" without being rooted in the
  6530. + * directory tree.
  6531. + */
  6532. +
  6533. +static int yaffs_has_null_parent(struct yaffs_dev *dev, struct yaffs_obj *obj)
  6534. +{
  6535. + return (obj == dev->del_dir ||
  6536. + obj == dev->unlinked_dir || obj == dev->root_dir);
  6537. +}
  6538. +
  6539. +static void yaffs_fix_hanging_objs(struct yaffs_dev *dev)
  6540. +{
  6541. + struct yaffs_obj *obj;
  6542. + struct yaffs_obj *parent;
  6543. + int i;
  6544. + struct list_head *lh;
  6545. + struct list_head *n;
  6546. + int depth_limit;
  6547. + int hanging;
  6548. +
  6549. + if (dev->read_only)
  6550. + return;
  6551. +
  6552. + /* Iterate through the objects in each hash entry,
  6553. + * looking at each object.
  6554. + * Make sure it is rooted.
  6555. + */
  6556. +
  6557. + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
  6558. + list_for_each_safe(lh, n, &dev->obj_bucket[i].list) {
  6559. + obj = list_entry(lh, struct yaffs_obj, hash_link);
  6560. + parent = obj->parent;
  6561. +
  6562. + if (yaffs_has_null_parent(dev, obj)) {
  6563. + /* These directories are not hanging */
  6564. + hanging = 0;
  6565. + } else if (!parent ||
  6566. + parent->variant_type !=
  6567. + YAFFS_OBJECT_TYPE_DIRECTORY) {
  6568. + hanging = 1;
  6569. + } else if (yaffs_has_null_parent(dev, parent)) {
  6570. + hanging = 0;
  6571. + } else {
  6572. + /*
  6573. + * Need to follow the parent chain to
  6574. + * see if it is hanging.
  6575. + */
  6576. + hanging = 0;
  6577. + depth_limit = 100;
  6578. +
  6579. + while (parent != dev->root_dir &&
  6580. + parent->parent &&
  6581. + parent->parent->variant_type ==
  6582. + YAFFS_OBJECT_TYPE_DIRECTORY &&
  6583. + depth_limit > 0) {
  6584. + parent = parent->parent;
  6585. + depth_limit--;
  6586. + }
  6587. + if (parent != dev->root_dir)
  6588. + hanging = 1;
  6589. + }
  6590. + if (hanging) {
  6591. + yaffs_trace(YAFFS_TRACE_SCAN,
  6592. + "Hanging object %d moved to lost and found",
  6593. + obj->obj_id);
  6594. + yaffs_add_obj_to_dir(dev->lost_n_found, obj);
  6595. + }
  6596. + }
  6597. + }
  6598. +}
  6599. +
  6600. +/*
  6601. + * Delete directory contents for cleaning up lost and found.
  6602. + */
  6603. +static void yaffs_del_dir_contents(struct yaffs_obj *dir)
  6604. +{
  6605. + struct yaffs_obj *obj;
  6606. + struct list_head *lh;
  6607. + struct list_head *n;
  6608. +
  6609. + if (dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
  6610. + BUG();
  6611. +
  6612. + list_for_each_safe(lh, n, &dir->variant.dir_variant.children) {
  6613. + obj = list_entry(lh, struct yaffs_obj, siblings);
  6614. + if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
  6615. + yaffs_del_dir_contents(obj);
  6616. + yaffs_trace(YAFFS_TRACE_SCAN,
  6617. + "Deleting lost_found object %d",
  6618. + obj->obj_id);
  6619. + yaffs_unlink_obj(obj);
  6620. + }
  6621. +}
  6622. +
  6623. +static void yaffs_empty_l_n_f(struct yaffs_dev *dev)
  6624. +{
  6625. + yaffs_del_dir_contents(dev->lost_n_found);
  6626. +}
  6627. +
  6628. +
  6629. +struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *directory,
  6630. + const YCHAR *name)
  6631. +{
  6632. + int sum;
  6633. + struct list_head *i;
  6634. + YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
  6635. + struct yaffs_obj *l;
  6636. +
  6637. + if (!name)
  6638. + return NULL;
  6639. +
  6640. + if (!directory) {
  6641. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6642. + "tragedy: yaffs_find_by_name: null pointer directory"
  6643. + );
  6644. + BUG();
  6645. + return NULL;
  6646. + }
  6647. + if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  6648. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6649. + "tragedy: yaffs_find_by_name: non-directory"
  6650. + );
  6651. + BUG();
  6652. + }
  6653. +
  6654. + sum = yaffs_calc_name_sum(name);
  6655. +
  6656. + list_for_each(i, &directory->variant.dir_variant.children) {
  6657. + l = list_entry(i, struct yaffs_obj, siblings);
  6658. +
  6659. + if (l->parent != directory)
  6660. + BUG();
  6661. +
  6662. + yaffs_check_obj_details_loaded(l);
  6663. +
  6664. + /* Special case for lost-n-found */
  6665. + if (l->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
  6666. + if (!strcmp(name, YAFFS_LOSTNFOUND_NAME))
  6667. + return l;
  6668. + } else if (l->sum == sum || l->hdr_chunk <= 0) {
  6669. + /* LostnFound chunk called Objxxx
  6670. + * Do a real check
  6671. + */
  6672. + yaffs_get_obj_name(l, buffer,
  6673. + YAFFS_MAX_NAME_LENGTH + 1);
  6674. + if (!strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH))
  6675. + return l;
  6676. + }
  6677. + }
  6678. + return NULL;
  6679. +}
  6680. +
  6681. +/* GetEquivalentObject dereferences any hard links to get to the
  6682. + * actual object.
  6683. + */
  6684. +
  6685. +struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj)
  6686. +{
  6687. + if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
  6688. + obj = obj->variant.hardlink_variant.equiv_obj;
  6689. + yaffs_check_obj_details_loaded(obj);
  6690. + }
  6691. + return obj;
  6692. +}
  6693. +
  6694. +/*
  6695. + * A note or two on object names.
  6696. + * * If the object name is missing, we then make one up in the form objnnn
  6697. + *
  6698. + * * ASCII names are stored in the object header's name field from byte zero
  6699. + * * Unicode names are historically stored starting from byte zero.
  6700. + *
  6701. + * Then there are automatic Unicode names...
  6702. + * The purpose of these is to save names in a way that can be read as
  6703. + * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII
  6704. + * system to share files.
  6705. + *
  6706. + * These automatic unicode are stored slightly differently...
  6707. + * - If the name can fit in the ASCII character space then they are saved as
  6708. + * ascii names as per above.
  6709. + * - If the name needs Unicode then the name is saved in Unicode
  6710. + * starting at oh->name[1].
  6711. +
  6712. + */
  6713. +static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
  6714. + int buffer_size)
  6715. +{
  6716. + /* Create an object name if we could not find one. */
  6717. + if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0) {
  6718. + YCHAR local_name[20];
  6719. + YCHAR num_string[20];
  6720. + YCHAR *x = &num_string[19];
  6721. + unsigned v = obj->obj_id;
  6722. + num_string[19] = 0;
  6723. + while (v > 0) {
  6724. + x--;
  6725. + *x = '0' + (v % 10);
  6726. + v /= 10;
  6727. + }
  6728. + /* make up a name */
  6729. + strcpy(local_name, YAFFS_LOSTNFOUND_PREFIX);
  6730. + strcat(local_name, x);
  6731. + strncpy(name, local_name, buffer_size - 1);
  6732. + }
  6733. +}
  6734. +
  6735. +int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size)
  6736. +{
  6737. + memset(name, 0, buffer_size * sizeof(YCHAR));
  6738. + yaffs_check_obj_details_loaded(obj);
  6739. + if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
  6740. + strncpy(name, YAFFS_LOSTNFOUND_NAME, buffer_size - 1);
  6741. + } else if (obj->short_name[0]) {
  6742. + strcpy(name, obj->short_name);
  6743. + } else if (obj->hdr_chunk > 0) {
  6744. + int result;
  6745. + u8 *buffer = yaffs_get_temp_buffer(obj->my_dev);
  6746. +
  6747. + struct yaffs_obj_hdr *oh = (struct yaffs_obj_hdr *)buffer;
  6748. +
  6749. + memset(buffer, 0, obj->my_dev->data_bytes_per_chunk);
  6750. +
  6751. + if (obj->hdr_chunk > 0) {
  6752. + result = yaffs_rd_chunk_tags_nand(obj->my_dev,
  6753. + obj->hdr_chunk,
  6754. + buffer, NULL);
  6755. + }
  6756. + yaffs_load_name_from_oh(obj->my_dev, name, oh->name,
  6757. + buffer_size);
  6758. +
  6759. + yaffs_release_temp_buffer(obj->my_dev, buffer);
  6760. + }
  6761. +
  6762. + yaffs_fix_null_name(obj, name, buffer_size);
  6763. +
  6764. + return strnlen(name, YAFFS_MAX_NAME_LENGTH);
  6765. +}
  6766. +
  6767. +loff_t yaffs_get_obj_length(struct yaffs_obj *obj)
  6768. +{
  6769. + /* Dereference any hard linking */
  6770. + obj = yaffs_get_equivalent_obj(obj);
  6771. +
  6772. + if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
  6773. + return obj->variant.file_variant.file_size;
  6774. + if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
  6775. + if (!obj->variant.symlink_variant.alias)
  6776. + return 0;
  6777. + return strnlen(obj->variant.symlink_variant.alias,
  6778. + YAFFS_MAX_ALIAS_LENGTH);
  6779. + } else {
  6780. + /* Only a directory should drop through to here */
  6781. + return obj->my_dev->data_bytes_per_chunk;
  6782. + }
  6783. +}
  6784. +
  6785. +int yaffs_get_obj_link_count(struct yaffs_obj *obj)
  6786. +{
  6787. + int count = 0;
  6788. + struct list_head *i;
  6789. +
  6790. + if (!obj->unlinked)
  6791. + count++; /* the object itself */
  6792. +
  6793. + list_for_each(i, &obj->hard_links)
  6794. + count++; /* add the hard links; */
  6795. +
  6796. + return count;
  6797. +}
  6798. +
  6799. +int yaffs_get_obj_inode(struct yaffs_obj *obj)
  6800. +{
  6801. + obj = yaffs_get_equivalent_obj(obj);
  6802. +
  6803. + return obj->obj_id;
  6804. +}
  6805. +
  6806. +unsigned yaffs_get_obj_type(struct yaffs_obj *obj)
  6807. +{
  6808. + obj = yaffs_get_equivalent_obj(obj);
  6809. +
  6810. + switch (obj->variant_type) {
  6811. + case YAFFS_OBJECT_TYPE_FILE:
  6812. + return DT_REG;
  6813. + break;
  6814. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  6815. + return DT_DIR;
  6816. + break;
  6817. + case YAFFS_OBJECT_TYPE_SYMLINK:
  6818. + return DT_LNK;
  6819. + break;
  6820. + case YAFFS_OBJECT_TYPE_HARDLINK:
  6821. + return DT_REG;
  6822. + break;
  6823. + case YAFFS_OBJECT_TYPE_SPECIAL:
  6824. + if (S_ISFIFO(obj->yst_mode))
  6825. + return DT_FIFO;
  6826. + if (S_ISCHR(obj->yst_mode))
  6827. + return DT_CHR;
  6828. + if (S_ISBLK(obj->yst_mode))
  6829. + return DT_BLK;
  6830. + if (S_ISSOCK(obj->yst_mode))
  6831. + return DT_SOCK;
  6832. + return DT_REG;
  6833. + break;
  6834. + default:
  6835. + return DT_REG;
  6836. + break;
  6837. + }
  6838. +}
  6839. +
  6840. +YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj)
  6841. +{
  6842. + obj = yaffs_get_equivalent_obj(obj);
  6843. + if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK)
  6844. + return yaffs_clone_str(obj->variant.symlink_variant.alias);
  6845. + else
  6846. + return yaffs_clone_str(_Y(""));
  6847. +}
  6848. +
  6849. +/*--------------------------- Initialisation code -------------------------- */
  6850. +
  6851. +static int yaffs_check_dev_fns(struct yaffs_dev *dev)
  6852. +{
  6853. + struct yaffs_driver *drv = &dev->drv;
  6854. + struct yaffs_tags_handler *tagger = &dev->tagger;
  6855. +
  6856. + /* Common functions, gotta have */
  6857. + if (!drv->drv_read_chunk_fn ||
  6858. + !drv->drv_write_chunk_fn ||
  6859. + !drv->drv_erase_fn)
  6860. + return 0;
  6861. +
  6862. + if (dev->param.is_yaffs2 &&
  6863. + (!drv->drv_mark_bad_fn || !drv->drv_check_bad_fn))
  6864. + return 0;
  6865. +
  6866. + /* Install the default tags marshalling functions if needed. */
  6867. + yaffs_tags_compat_install(dev);
  6868. + yaffs_tags_marshall_install(dev);
  6869. +
  6870. + /* Check we now have the marshalling functions required. */
  6871. + if (!tagger->write_chunk_tags_fn ||
  6872. + !tagger->read_chunk_tags_fn ||
  6873. + !tagger->query_block_fn ||
  6874. + !tagger->mark_bad_fn)
  6875. + return 0;
  6876. +
  6877. + return 1;
  6878. +}
  6879. +
  6880. +static int yaffs_create_initial_dir(struct yaffs_dev *dev)
  6881. +{
  6882. + /* Initialise the unlinked, deleted, root and lost+found directories */
  6883. + dev->lost_n_found = dev->root_dir = NULL;
  6884. + dev->unlinked_dir = dev->del_dir = NULL;
  6885. + dev->unlinked_dir =
  6886. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
  6887. + dev->del_dir =
  6888. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
  6889. + dev->root_dir =
  6890. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_ROOT,
  6891. + YAFFS_ROOT_MODE | S_IFDIR);
  6892. + dev->lost_n_found =
  6893. + yaffs_create_fake_dir(dev, YAFFS_OBJECTID_LOSTNFOUND,
  6894. + YAFFS_LOSTNFOUND_MODE | S_IFDIR);
  6895. +
  6896. + if (dev->lost_n_found && dev->root_dir && dev->unlinked_dir
  6897. + && dev->del_dir) {
  6898. + yaffs_add_obj_to_dir(dev->root_dir, dev->lost_n_found);
  6899. + return YAFFS_OK;
  6900. + }
  6901. + return YAFFS_FAIL;
  6902. +}
  6903. +
  6904. +/* Low level init.
  6905. + * Typically only used by yaffs_guts_initialise, but also used by the
  6906. + * Low level yaffs driver tests.
  6907. + */
  6908. +
  6909. +int yaffs_guts_ll_init(struct yaffs_dev *dev)
  6910. +{
  6911. +
  6912. +
  6913. + yaffs_trace(YAFFS_TRACE_TRACING, "yaffs: yaffs_ll_init()");
  6914. +
  6915. + if (!dev) {
  6916. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6917. + "yaffs: Need a device"
  6918. + );
  6919. + return YAFFS_FAIL;
  6920. + }
  6921. +
  6922. + if (dev->ll_init)
  6923. + return YAFFS_OK;
  6924. +
  6925. + dev->internal_start_block = dev->param.start_block;
  6926. + dev->internal_end_block = dev->param.end_block;
  6927. + dev->block_offset = 0;
  6928. + dev->chunk_offset = 0;
  6929. + dev->n_free_chunks = 0;
  6930. +
  6931. + dev->gc_block = 0;
  6932. +
  6933. + if (dev->param.start_block == 0) {
  6934. + dev->internal_start_block = dev->param.start_block + 1;
  6935. + dev->internal_end_block = dev->param.end_block + 1;
  6936. + dev->block_offset = 1;
  6937. + dev->chunk_offset = dev->param.chunks_per_block;
  6938. + }
  6939. +
  6940. + /* Check geometry parameters. */
  6941. +
  6942. + if ((!dev->param.inband_tags && dev->param.is_yaffs2 &&
  6943. + dev->param.total_bytes_per_chunk < 1024) ||
  6944. + (!dev->param.is_yaffs2 &&
  6945. + dev->param.total_bytes_per_chunk < 512) ||
  6946. + (dev->param.inband_tags && !dev->param.is_yaffs2) ||
  6947. + dev->param.chunks_per_block < 2 ||
  6948. + dev->param.n_reserved_blocks < 2 ||
  6949. + dev->internal_start_block <= 0 ||
  6950. + dev->internal_end_block <= 0 ||
  6951. + dev->internal_end_block <=
  6952. + (dev->internal_start_block + dev->param.n_reserved_blocks + 2)
  6953. + ) {
  6954. + /* otherwise it is too small */
  6955. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6956. + "NAND geometry problems: chunk size %d, type is yaffs%s, inband_tags %d ",
  6957. + dev->param.total_bytes_per_chunk,
  6958. + dev->param.is_yaffs2 ? "2" : "",
  6959. + dev->param.inband_tags);
  6960. + return YAFFS_FAIL;
  6961. + }
  6962. +
  6963. + /* Sort out space for inband tags, if required */
  6964. + if (dev->param.inband_tags)
  6965. + dev->data_bytes_per_chunk =
  6966. + dev->param.total_bytes_per_chunk -
  6967. + sizeof(struct yaffs_packed_tags2_tags_only);
  6968. + else
  6969. + dev->data_bytes_per_chunk = dev->param.total_bytes_per_chunk;
  6970. +
  6971. + /* Got the right mix of functions? */
  6972. + if (!yaffs_check_dev_fns(dev)) {
  6973. + /* Function missing */
  6974. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  6975. + "device function(s) missing or wrong");
  6976. +
  6977. + return YAFFS_FAIL;
  6978. + }
  6979. +
  6980. + if (yaffs_init_nand(dev) != YAFFS_OK) {
  6981. + yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed");
  6982. + return YAFFS_FAIL;
  6983. + }
  6984. +
  6985. + return YAFFS_OK;
  6986. +}
  6987. +
  6988. +
  6989. +int yaffs_guts_format_dev(struct yaffs_dev *dev)
  6990. +{
  6991. + int i;
  6992. + enum yaffs_block_state state;
  6993. + u32 dummy;
  6994. +
  6995. + if(yaffs_guts_ll_init(dev) != YAFFS_OK)
  6996. + return YAFFS_FAIL;
  6997. +
  6998. + if(dev->is_mounted)
  6999. + return YAFFS_FAIL;
  7000. +
  7001. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  7002. + yaffs_query_init_block_state(dev, i, &state, &dummy);
  7003. + if (state != YAFFS_BLOCK_STATE_DEAD)
  7004. + yaffs_erase_block(dev, i);
  7005. + }
  7006. +
  7007. + return YAFFS_OK;
  7008. +}
  7009. +
  7010. +
  7011. +int yaffs_guts_initialise(struct yaffs_dev *dev)
  7012. +{
  7013. + int init_failed = 0;
  7014. + unsigned x;
  7015. + int bits;
  7016. +
  7017. + if(yaffs_guts_ll_init(dev) != YAFFS_OK)
  7018. + return YAFFS_FAIL;
  7019. +
  7020. + if (dev->is_mounted) {
  7021. + yaffs_trace(YAFFS_TRACE_ALWAYS, "device already mounted");
  7022. + return YAFFS_FAIL;
  7023. + }
  7024. +
  7025. + dev->is_mounted = 1;
  7026. +
  7027. + /* OK now calculate a few things for the device */
  7028. +
  7029. + /*
  7030. + * Calculate all the chunk size manipulation numbers:
  7031. + */
  7032. + x = dev->data_bytes_per_chunk;
  7033. + /* We always use dev->chunk_shift and dev->chunk_div */
  7034. + dev->chunk_shift = calc_shifts(x);
  7035. + x >>= dev->chunk_shift;
  7036. + dev->chunk_div = x;
  7037. + /* We only use chunk mask if chunk_div is 1 */
  7038. + dev->chunk_mask = (1 << dev->chunk_shift) - 1;
  7039. +
  7040. + /*
  7041. + * Calculate chunk_grp_bits.
  7042. + * We need to find the next power of 2 > than internal_end_block
  7043. + */
  7044. +
  7045. + x = dev->param.chunks_per_block * (dev->internal_end_block + 1);
  7046. +
  7047. + bits = calc_shifts_ceiling(x);
  7048. +
  7049. + /* Set up tnode width if wide tnodes are enabled. */
  7050. + if (!dev->param.wide_tnodes_disabled) {
  7051. + /* bits must be even so that we end up with 32-bit words */
  7052. + if (bits & 1)
  7053. + bits++;
  7054. + if (bits < 16)
  7055. + dev->tnode_width = 16;
  7056. + else
  7057. + dev->tnode_width = bits;
  7058. + } else {
  7059. + dev->tnode_width = 16;
  7060. + }
  7061. +
  7062. + dev->tnode_mask = (1 << dev->tnode_width) - 1;
  7063. +
  7064. + /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
  7065. + * so if the bitwidth of the
  7066. + * chunk range we're using is greater than 16 we need
  7067. + * to figure out chunk shift and chunk_grp_size
  7068. + */
  7069. +
  7070. + if (bits <= dev->tnode_width)
  7071. + dev->chunk_grp_bits = 0;
  7072. + else
  7073. + dev->chunk_grp_bits = bits - dev->tnode_width;
  7074. +
  7075. + dev->tnode_size = (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8;
  7076. + if (dev->tnode_size < sizeof(struct yaffs_tnode))
  7077. + dev->tnode_size = sizeof(struct yaffs_tnode);
  7078. +
  7079. + dev->chunk_grp_size = 1 << dev->chunk_grp_bits;
  7080. +
  7081. + if (dev->param.chunks_per_block < dev->chunk_grp_size) {
  7082. + /* We have a problem because the soft delete won't work if
  7083. + * the chunk group size > chunks per block.
  7084. + * This can be remedied by using larger "virtual blocks".
  7085. + */
  7086. + yaffs_trace(YAFFS_TRACE_ALWAYS, "chunk group too large");
  7087. +
  7088. + return YAFFS_FAIL;
  7089. + }
  7090. +
  7091. + /* Finished verifying the device, continue with initialisation */
  7092. +
  7093. + /* More device initialisation */
  7094. + dev->all_gcs = 0;
  7095. + dev->passive_gc_count = 0;
  7096. + dev->oldest_dirty_gc_count = 0;
  7097. + dev->bg_gcs = 0;
  7098. + dev->gc_block_finder = 0;
  7099. + dev->buffered_block = -1;
  7100. + dev->doing_buffered_block_rewrite = 0;
  7101. + dev->n_deleted_files = 0;
  7102. + dev->n_bg_deletions = 0;
  7103. + dev->n_unlinked_files = 0;
  7104. + dev->n_ecc_fixed = 0;
  7105. + dev->n_ecc_unfixed = 0;
  7106. + dev->n_tags_ecc_fixed = 0;
  7107. + dev->n_tags_ecc_unfixed = 0;
  7108. + dev->n_erase_failures = 0;
  7109. + dev->n_erased_blocks = 0;
  7110. + dev->gc_disable = 0;
  7111. + dev->has_pending_prioritised_gc = 1;
  7112. + /* Assume the worst for now, will get fixed on first GC */
  7113. + INIT_LIST_HEAD(&dev->dirty_dirs);
  7114. + dev->oldest_dirty_seq = 0;
  7115. + dev->oldest_dirty_block = 0;
  7116. +
  7117. + /* Initialise temporary buffers and caches. */
  7118. + if (!yaffs_init_tmp_buffers(dev))
  7119. + init_failed = 1;
  7120. +
  7121. + dev->cache = NULL;
  7122. + dev->gc_cleanup_list = NULL;
  7123. +
  7124. + if (!init_failed && dev->param.n_caches > 0) {
  7125. + int i;
  7126. + void *buf;
  7127. + int cache_bytes =
  7128. + dev->param.n_caches * sizeof(struct yaffs_cache);
  7129. +
  7130. + if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES)
  7131. + dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES;
  7132. +
  7133. + dev->cache = kmalloc(cache_bytes, GFP_NOFS);
  7134. +
  7135. + buf = (u8 *) dev->cache;
  7136. +
  7137. + if (dev->cache)
  7138. + memset(dev->cache, 0, cache_bytes);
  7139. +
  7140. + for (i = 0; i < dev->param.n_caches && buf; i++) {
  7141. + dev->cache[i].object = NULL;
  7142. + dev->cache[i].last_use = 0;
  7143. + dev->cache[i].dirty = 0;
  7144. + dev->cache[i].data = buf =
  7145. + kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
  7146. + }
  7147. + if (!buf)
  7148. + init_failed = 1;
  7149. +
  7150. + dev->cache_last_use = 0;
  7151. + }
  7152. +
  7153. + dev->cache_hits = 0;
  7154. +
  7155. + if (!init_failed) {
  7156. + dev->gc_cleanup_list =
  7157. + kmalloc(dev->param.chunks_per_block * sizeof(u32),
  7158. + GFP_NOFS);
  7159. + if (!dev->gc_cleanup_list)
  7160. + init_failed = 1;
  7161. + }
  7162. +
  7163. + if (dev->param.is_yaffs2)
  7164. + dev->param.use_header_file_size = 1;
  7165. +
  7166. + if (!init_failed && !yaffs_init_blocks(dev))
  7167. + init_failed = 1;
  7168. +
  7169. + yaffs_init_tnodes_and_objs(dev);
  7170. +
  7171. + if (!init_failed && !yaffs_create_initial_dir(dev))
  7172. + init_failed = 1;
  7173. +
  7174. + if (!init_failed && dev->param.is_yaffs2 &&
  7175. + !dev->param.disable_summary &&
  7176. + !yaffs_summary_init(dev))
  7177. + init_failed = 1;
  7178. +
  7179. + if (!init_failed) {
  7180. + /* Now scan the flash. */
  7181. + if (dev->param.is_yaffs2) {
  7182. + if (yaffs2_checkpt_restore(dev)) {
  7183. + yaffs_check_obj_details_loaded(dev->root_dir);
  7184. + yaffs_trace(YAFFS_TRACE_CHECKPOINT |
  7185. + YAFFS_TRACE_MOUNT,
  7186. + "yaffs: restored from checkpoint"
  7187. + );
  7188. + } else {
  7189. +
  7190. + /* Clean up the mess caused by an aborted
  7191. + * checkpoint load then scan backwards.
  7192. + */
  7193. + yaffs_deinit_blocks(dev);
  7194. +
  7195. + yaffs_deinit_tnodes_and_objs(dev);
  7196. +
  7197. + dev->n_erased_blocks = 0;
  7198. + dev->n_free_chunks = 0;
  7199. + dev->alloc_block = -1;
  7200. + dev->alloc_page = -1;
  7201. + dev->n_deleted_files = 0;
  7202. + dev->n_unlinked_files = 0;
  7203. + dev->n_bg_deletions = 0;
  7204. +
  7205. + if (!init_failed && !yaffs_init_blocks(dev))
  7206. + init_failed = 1;
  7207. +
  7208. + yaffs_init_tnodes_and_objs(dev);
  7209. +
  7210. + if (!init_failed
  7211. + && !yaffs_create_initial_dir(dev))
  7212. + init_failed = 1;
  7213. +
  7214. + if (!init_failed && !yaffs2_scan_backwards(dev))
  7215. + init_failed = 1;
  7216. + }
  7217. + } else if (!yaffs1_scan(dev)) {
  7218. + init_failed = 1;
  7219. + }
  7220. +
  7221. + yaffs_strip_deleted_objs(dev);
  7222. + yaffs_fix_hanging_objs(dev);
  7223. + if (dev->param.empty_lost_n_found)
  7224. + yaffs_empty_l_n_f(dev);
  7225. + }
  7226. +
  7227. + if (init_failed) {
  7228. + /* Clean up the mess */
  7229. + yaffs_trace(YAFFS_TRACE_TRACING,
  7230. + "yaffs: yaffs_guts_initialise() aborted.");
  7231. +
  7232. + yaffs_deinitialise(dev);
  7233. + return YAFFS_FAIL;
  7234. + }
  7235. +
  7236. + /* Zero out stats */
  7237. + dev->n_page_reads = 0;
  7238. + dev->n_page_writes = 0;
  7239. + dev->n_erasures = 0;
  7240. + dev->n_gc_copies = 0;
  7241. + dev->n_retried_writes = 0;
  7242. +
  7243. + dev->n_retired_blocks = 0;
  7244. +
  7245. + yaffs_verify_free_chunks(dev);
  7246. + yaffs_verify_blocks(dev);
  7247. +
  7248. + /* Clean up any aborted checkpoint data */
  7249. + if (!dev->is_checkpointed && dev->blocks_in_checkpt > 0)
  7250. + yaffs2_checkpt_invalidate(dev);
  7251. +
  7252. + yaffs_trace(YAFFS_TRACE_TRACING,
  7253. + "yaffs: yaffs_guts_initialise() done.");
  7254. + return YAFFS_OK;
  7255. +}
  7256. +
  7257. +void yaffs_deinitialise(struct yaffs_dev *dev)
  7258. +{
  7259. + if (dev->is_mounted) {
  7260. + int i;
  7261. +
  7262. + yaffs_deinit_blocks(dev);
  7263. + yaffs_deinit_tnodes_and_objs(dev);
  7264. + yaffs_summary_deinit(dev);
  7265. +
  7266. + if (dev->param.n_caches > 0 && dev->cache) {
  7267. +
  7268. + for (i = 0; i < dev->param.n_caches; i++) {
  7269. + kfree(dev->cache[i].data);
  7270. + dev->cache[i].data = NULL;
  7271. + }
  7272. +
  7273. + kfree(dev->cache);
  7274. + dev->cache = NULL;
  7275. + }
  7276. +
  7277. + kfree(dev->gc_cleanup_list);
  7278. +
  7279. + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
  7280. + kfree(dev->temp_buffer[i].buffer);
  7281. +
  7282. + dev->is_mounted = 0;
  7283. +
  7284. + yaffs_deinit_nand(dev);
  7285. + }
  7286. +}
  7287. +
  7288. +int yaffs_count_free_chunks(struct yaffs_dev *dev)
  7289. +{
  7290. + int n_free = 0;
  7291. + int b;
  7292. + struct yaffs_block_info *blk;
  7293. +
  7294. + blk = dev->block_info;
  7295. + for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) {
  7296. + switch (blk->block_state) {
  7297. + case YAFFS_BLOCK_STATE_EMPTY:
  7298. + case YAFFS_BLOCK_STATE_ALLOCATING:
  7299. + case YAFFS_BLOCK_STATE_COLLECTING:
  7300. + case YAFFS_BLOCK_STATE_FULL:
  7301. + n_free +=
  7302. + (dev->param.chunks_per_block - blk->pages_in_use +
  7303. + blk->soft_del_pages);
  7304. + break;
  7305. + default:
  7306. + break;
  7307. + }
  7308. + blk++;
  7309. + }
  7310. + return n_free;
  7311. +}
  7312. +
  7313. +int yaffs_get_n_free_chunks(struct yaffs_dev *dev)
  7314. +{
  7315. + /* This is what we report to the outside world */
  7316. + int n_free;
  7317. + int n_dirty_caches;
  7318. + int blocks_for_checkpt;
  7319. + int i;
  7320. +
  7321. + n_free = dev->n_free_chunks;
  7322. + n_free += dev->n_deleted_files;
  7323. +
  7324. + /* Now count and subtract the number of dirty chunks in the cache. */
  7325. +
  7326. + for (n_dirty_caches = 0, i = 0; i < dev->param.n_caches; i++) {
  7327. + if (dev->cache[i].dirty)
  7328. + n_dirty_caches++;
  7329. + }
  7330. +
  7331. + n_free -= n_dirty_caches;
  7332. +
  7333. + n_free -=
  7334. + ((dev->param.n_reserved_blocks + 1) * dev->param.chunks_per_block);
  7335. +
  7336. + /* Now figure checkpoint space and report that... */
  7337. + blocks_for_checkpt = yaffs_calc_checkpt_blocks_required(dev);
  7338. +
  7339. + n_free -= (blocks_for_checkpt * dev->param.chunks_per_block);
  7340. +
  7341. + if (n_free < 0)
  7342. + n_free = 0;
  7343. +
  7344. + return n_free;
  7345. +}
  7346. +
  7347. +
  7348. +
  7349. +/*
  7350. + * Marshalling functions to get loff_t file sizes into and out of
  7351. + * object headers.
  7352. + */
  7353. +void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize)
  7354. +{
  7355. + oh->file_size_low = (fsize & 0xFFFFFFFF);
  7356. + oh->file_size_high = ((fsize >> 32) & 0xFFFFFFFF);
  7357. +}
  7358. +
  7359. +loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh)
  7360. +{
  7361. + loff_t retval;
  7362. +
  7363. + if (sizeof(loff_t) >= 8 && ~(oh->file_size_high))
  7364. + retval = (((loff_t) oh->file_size_high) << 32) |
  7365. + (((loff_t) oh->file_size_low) & 0xFFFFFFFF);
  7366. + else
  7367. + retval = (loff_t) oh->file_size_low;
  7368. +
  7369. + return retval;
  7370. +}
  7371. +
  7372. +
  7373. +void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10])
  7374. +{
  7375. + int i;
  7376. + struct yaffs_block_info *bi;
  7377. + int s;
  7378. +
  7379. + for(i = 0; i < 10; i++)
  7380. + bs[i] = 0;
  7381. +
  7382. + for(i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  7383. + bi = yaffs_get_block_info(dev, i);
  7384. + s = bi->block_state;
  7385. + if(s > YAFFS_BLOCK_STATE_DEAD || s < YAFFS_BLOCK_STATE_UNKNOWN)
  7386. + bs[0]++;
  7387. + else
  7388. + bs[s]++;
  7389. + }
  7390. +}
  7391. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_guts.h linux-3.14.4/fs/yaffs2/yaffs_guts.h
  7392. --- linux-3.14.4.orig/fs/yaffs2/yaffs_guts.h 1970-01-01 01:00:00.000000000 +0100
  7393. +++ linux-3.14.4/fs/yaffs2/yaffs_guts.h 2014-05-14 12:41:23.984792448 +0200
  7394. @@ -0,0 +1,1007 @@
  7395. +/*
  7396. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  7397. + *
  7398. + * Copyright (C) 2002-2011 Aleph One Ltd.
  7399. + * for Toby Churchill Ltd and Brightstar Engineering
  7400. + *
  7401. + * Created by Charles Manning <charles@aleph1.co.uk>
  7402. + *
  7403. + * This program is free software; you can redistribute it and/or modify
  7404. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  7405. + * published by the Free Software Foundation.
  7406. + *
  7407. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  7408. + */
  7409. +
  7410. +#ifndef __YAFFS_GUTS_H__
  7411. +#define __YAFFS_GUTS_H__
  7412. +
  7413. +#include "yportenv.h"
  7414. +
  7415. +#define YAFFS_OK 1
  7416. +#define YAFFS_FAIL 0
  7417. +
  7418. +/* Give us a Y=0x59,
  7419. + * Give us an A=0x41,
  7420. + * Give us an FF=0xff
  7421. + * Give us an S=0x53
  7422. + * And what have we got...
  7423. + */
  7424. +#define YAFFS_MAGIC 0x5941ff53
  7425. +
  7426. +/*
  7427. + * Tnodes form a tree with the tnodes in "levels"
  7428. + * Levels greater than 0 hold 8 slots which point to other tnodes.
  7429. + * Those at level 0 hold 16 slots which point to chunks in NAND.
  7430. + *
  7431. + * A maximum level of 8 thust supports files of size up to:
  7432. + *
  7433. + * 2^(3*MAX_LEVEL+4)
  7434. + *
  7435. + * Thus a max level of 8 supports files with up to 2^^28 chunks which gives
  7436. + * a maximum file size of around 512Gbytees with 2k chunks.
  7437. + */
  7438. +#define YAFFS_NTNODES_LEVEL0 16
  7439. +#define YAFFS_TNODES_LEVEL0_BITS 4
  7440. +#define YAFFS_TNODES_LEVEL0_MASK 0xf
  7441. +
  7442. +#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2)
  7443. +#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1)
  7444. +#define YAFFS_TNODES_INTERNAL_MASK 0x7
  7445. +#define YAFFS_TNODES_MAX_LEVEL 8
  7446. +#define YAFFS_TNODES_MAX_BITS (YAFFS_TNODES_LEVEL0_BITS + \
  7447. + YAFFS_TNODES_INTERNAL_BITS * \
  7448. + YAFFS_TNODES_MAX_LEVEL)
  7449. +#define YAFFS_MAX_CHUNK_ID ((1 << YAFFS_TNODES_MAX_BITS) - 1)
  7450. +
  7451. +#define YAFFS_MAX_FILE_SIZE_32 0x7fffffff
  7452. +
  7453. +/* Constants for YAFFS1 mode */
  7454. +#define YAFFS_BYTES_PER_SPARE 16
  7455. +#define YAFFS_BYTES_PER_CHUNK 512
  7456. +#define YAFFS_CHUNK_SIZE_SHIFT 9
  7457. +#define YAFFS_CHUNKS_PER_BLOCK 32
  7458. +#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
  7459. +
  7460. +#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024
  7461. +#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32
  7462. +
  7463. +
  7464. +
  7465. +#define YAFFS_ALLOCATION_NOBJECTS 100
  7466. +#define YAFFS_ALLOCATION_NTNODES 100
  7467. +#define YAFFS_ALLOCATION_NLINKS 100
  7468. +
  7469. +#define YAFFS_NOBJECT_BUCKETS 256
  7470. +
  7471. +#define YAFFS_OBJECT_SPACE 0x40000
  7472. +#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1)
  7473. +
  7474. +/* Binary data version stamps */
  7475. +#define YAFFS_SUMMARY_VERSION 1
  7476. +#define YAFFS_CHECKPOINT_VERSION 7
  7477. +
  7478. +#ifdef CONFIG_YAFFS_UNICODE
  7479. +#define YAFFS_MAX_NAME_LENGTH 127
  7480. +#define YAFFS_MAX_ALIAS_LENGTH 79
  7481. +#else
  7482. +#define YAFFS_MAX_NAME_LENGTH 255
  7483. +#define YAFFS_MAX_ALIAS_LENGTH 159
  7484. +#endif
  7485. +
  7486. +#define YAFFS_SHORT_NAME_LENGTH 15
  7487. +
  7488. +/* Some special object ids for pseudo objects */
  7489. +#define YAFFS_OBJECTID_ROOT 1
  7490. +#define YAFFS_OBJECTID_LOSTNFOUND 2
  7491. +#define YAFFS_OBJECTID_UNLINKED 3
  7492. +#define YAFFS_OBJECTID_DELETED 4
  7493. +
  7494. +/* Fake object Id for summary data */
  7495. +#define YAFFS_OBJECTID_SUMMARY 0x10
  7496. +
  7497. +/* Pseudo object ids for checkpointing */
  7498. +#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20
  7499. +#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21
  7500. +
  7501. +#define YAFFS_MAX_SHORT_OP_CACHES 20
  7502. +
  7503. +#define YAFFS_N_TEMP_BUFFERS 6
  7504. +
  7505. +/* We limit the number attempts at sucessfully saving a chunk of data.
  7506. + * Small-page devices have 32 pages per block; large-page devices have 64.
  7507. + * Default to something in the order of 5 to 10 blocks worth of chunks.
  7508. + */
  7509. +#define YAFFS_WR_ATTEMPTS (5*64)
  7510. +
  7511. +/* Sequence numbers are used in YAFFS2 to determine block allocation order.
  7512. + * The range is limited slightly to help distinguish bad numbers from good.
  7513. + * This also allows us to perhaps in the future use special numbers for
  7514. + * special purposes.
  7515. + * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years,
  7516. + * and is a larger number than the lifetime of a 2GB device.
  7517. + */
  7518. +#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000
  7519. +#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xefffff00
  7520. +
  7521. +/* Special sequence number for bad block that failed to be marked bad */
  7522. +#define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000
  7523. +
  7524. +/* ChunkCache is used for short read/write operations.*/
  7525. +struct yaffs_cache {
  7526. + struct yaffs_obj *object;
  7527. + int chunk_id;
  7528. + int last_use;
  7529. + int dirty;
  7530. + int n_bytes; /* Only valid if the cache is dirty */
  7531. + int locked; /* Can't push out or flush while locked. */
  7532. + u8 *data;
  7533. +};
  7534. +
  7535. +/* yaffs1 tags structures in RAM
  7536. + * NB This uses bitfield. Bitfields should not straddle a u32 boundary
  7537. + * otherwise the structure size will get blown out.
  7538. + */
  7539. +
  7540. +struct yaffs_tags {
  7541. + u32 chunk_id:20;
  7542. + u32 serial_number:2;
  7543. + u32 n_bytes_lsb:10;
  7544. + u32 obj_id:18;
  7545. + u32 ecc:12;
  7546. + u32 n_bytes_msb:2;
  7547. +};
  7548. +
  7549. +union yaffs_tags_union {
  7550. + struct yaffs_tags as_tags;
  7551. + u8 as_bytes[8];
  7552. +};
  7553. +
  7554. +
  7555. +/* Stuff used for extended tags in YAFFS2 */
  7556. +
  7557. +enum yaffs_ecc_result {
  7558. + YAFFS_ECC_RESULT_UNKNOWN,
  7559. + YAFFS_ECC_RESULT_NO_ERROR,
  7560. + YAFFS_ECC_RESULT_FIXED,
  7561. + YAFFS_ECC_RESULT_UNFIXED
  7562. +};
  7563. +
  7564. +enum yaffs_obj_type {
  7565. + YAFFS_OBJECT_TYPE_UNKNOWN,
  7566. + YAFFS_OBJECT_TYPE_FILE,
  7567. + YAFFS_OBJECT_TYPE_SYMLINK,
  7568. + YAFFS_OBJECT_TYPE_DIRECTORY,
  7569. + YAFFS_OBJECT_TYPE_HARDLINK,
  7570. + YAFFS_OBJECT_TYPE_SPECIAL
  7571. +};
  7572. +
  7573. +#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL
  7574. +
  7575. +struct yaffs_ext_tags {
  7576. + unsigned chunk_used; /* Status of the chunk: used or unused */
  7577. + unsigned obj_id; /* If 0 this is not used */
  7578. + unsigned chunk_id; /* If 0 this is a header, else a data chunk */
  7579. + unsigned n_bytes; /* Only valid for data chunks */
  7580. +
  7581. + /* The following stuff only has meaning when we read */
  7582. + enum yaffs_ecc_result ecc_result;
  7583. + unsigned block_bad;
  7584. +
  7585. + /* YAFFS 1 stuff */
  7586. + unsigned is_deleted; /* The chunk is marked deleted */
  7587. + unsigned serial_number; /* Yaffs1 2-bit serial number */
  7588. +
  7589. + /* YAFFS2 stuff */
  7590. + unsigned seq_number; /* The sequence number of this block */
  7591. +
  7592. + /* Extra info if this is an object header (YAFFS2 only) */
  7593. +
  7594. + unsigned extra_available; /* Extra info available if not zero */
  7595. + unsigned extra_parent_id; /* The parent object */
  7596. + unsigned extra_is_shrink; /* Is it a shrink header? */
  7597. + unsigned extra_shadows; /* Does this shadow another object? */
  7598. +
  7599. + enum yaffs_obj_type extra_obj_type; /* What object type? */
  7600. +
  7601. + loff_t extra_file_size; /* Length if it is a file */
  7602. + unsigned extra_equiv_id; /* Equivalent object for a hard link */
  7603. +};
  7604. +
  7605. +/* Spare structure for YAFFS1 */
  7606. +struct yaffs_spare {
  7607. + u8 tb0;
  7608. + u8 tb1;
  7609. + u8 tb2;
  7610. + u8 tb3;
  7611. + u8 page_status; /* set to 0 to delete the chunk */
  7612. + u8 block_status;
  7613. + u8 tb4;
  7614. + u8 tb5;
  7615. + u8 ecc1[3];
  7616. + u8 tb6;
  7617. + u8 tb7;
  7618. + u8 ecc2[3];
  7619. +};
  7620. +
  7621. +/*Special structure for passing through to mtd */
  7622. +struct yaffs_nand_spare {
  7623. + struct yaffs_spare spare;
  7624. + int eccres1;
  7625. + int eccres2;
  7626. +};
  7627. +
  7628. +/* Block data in RAM */
  7629. +
  7630. +enum yaffs_block_state {
  7631. + YAFFS_BLOCK_STATE_UNKNOWN = 0,
  7632. +
  7633. + YAFFS_BLOCK_STATE_SCANNING,
  7634. + /* Being scanned */
  7635. +
  7636. + YAFFS_BLOCK_STATE_NEEDS_SCAN,
  7637. + /* The block might have something on it (ie it is allocating or full,
  7638. + * perhaps empty) but it needs to be scanned to determine its true
  7639. + * state.
  7640. + * This state is only valid during scanning.
  7641. + * NB We tolerate empty because the pre-scanner might be incapable of
  7642. + * deciding
  7643. + * However, if this state is returned on a YAFFS2 device,
  7644. + * then we expect a sequence number
  7645. + */
  7646. +
  7647. + YAFFS_BLOCK_STATE_EMPTY,
  7648. + /* This block is empty */
  7649. +
  7650. + YAFFS_BLOCK_STATE_ALLOCATING,
  7651. + /* This block is partially allocated.
  7652. + * At least one page holds valid data.
  7653. + * This is the one currently being used for page
  7654. + * allocation. Should never be more than one of these.
  7655. + * If a block is only partially allocated at mount it is treated as
  7656. + * full.
  7657. + */
  7658. +
  7659. + YAFFS_BLOCK_STATE_FULL,
  7660. + /* All the pages in this block have been allocated.
  7661. + * If a block was only partially allocated when mounted we treat
  7662. + * it as fully allocated.
  7663. + */
  7664. +
  7665. + YAFFS_BLOCK_STATE_DIRTY,
  7666. + /* The block was full and now all chunks have been deleted.
  7667. + * Erase me, reuse me.
  7668. + */
  7669. +
  7670. + YAFFS_BLOCK_STATE_CHECKPOINT,
  7671. + /* This block is assigned to holding checkpoint data. */
  7672. +
  7673. + YAFFS_BLOCK_STATE_COLLECTING,
  7674. + /* This block is being garbage collected */
  7675. +
  7676. + YAFFS_BLOCK_STATE_DEAD
  7677. + /* This block has failed and is not in use */
  7678. +};
  7679. +
  7680. +#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1)
  7681. +
  7682. +struct yaffs_block_info {
  7683. +
  7684. + s32 soft_del_pages:10; /* number of soft deleted pages */
  7685. + s32 pages_in_use:10; /* number of pages in use */
  7686. + u32 block_state:4; /* One of the above block states. */
  7687. + /* NB use unsigned because enum is sometimes
  7688. + * an int */
  7689. + u32 needs_retiring:1; /* Data has failed on this block, */
  7690. + /*need to get valid data off and retire*/
  7691. + u32 skip_erased_check:1;/* Skip the erased check on this block */
  7692. + u32 gc_prioritise:1; /* An ECC check or blank check has failed.
  7693. + Block should be prioritised for GC */
  7694. + u32 chunk_error_strikes:3; /* How many times we've had ecc etc
  7695. + failures on this block and tried to reuse it */
  7696. + u32 has_summary:1; /* The block has a summary */
  7697. +
  7698. + u32 has_shrink_hdr:1; /* This block has at least one shrink header */
  7699. + u32 seq_number; /* block sequence number for yaffs2 */
  7700. +
  7701. +};
  7702. +
  7703. +/* -------------------------- Object structure -------------------------------*/
  7704. +/* This is the object structure as stored on NAND */
  7705. +
  7706. +struct yaffs_obj_hdr {
  7707. + enum yaffs_obj_type type;
  7708. +
  7709. + /* Apply to everything */
  7710. + int parent_obj_id;
  7711. + u16 sum_no_longer_used; /* checksum of name. No longer used */
  7712. + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
  7713. +
  7714. + /* The following apply to all object types except for hard links */
  7715. + u32 yst_mode; /* protection */
  7716. +
  7717. + u32 yst_uid;
  7718. + u32 yst_gid;
  7719. + u32 yst_atime;
  7720. + u32 yst_mtime;
  7721. + u32 yst_ctime;
  7722. +
  7723. + /* File size applies to files only */
  7724. + u32 file_size_low;
  7725. +
  7726. + /* Equivalent object id applies to hard links only. */
  7727. + int equiv_id;
  7728. +
  7729. + /* Alias is for symlinks only. */
  7730. + YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1];
  7731. +
  7732. + u32 yst_rdev; /* stuff for block and char devices (major/min) */
  7733. +
  7734. + u32 win_ctime[2];
  7735. + u32 win_atime[2];
  7736. + u32 win_mtime[2];
  7737. +
  7738. + u32 inband_shadowed_obj_id;
  7739. + u32 inband_is_shrink;
  7740. +
  7741. + u32 file_size_high;
  7742. + u32 reserved[1];
  7743. + int shadows_obj; /* This object header shadows the
  7744. + specified object if > 0 */
  7745. +
  7746. + /* is_shrink applies to object headers written when wemake a hole. */
  7747. + u32 is_shrink;
  7748. +
  7749. +};
  7750. +
  7751. +/*--------------------------- Tnode -------------------------- */
  7752. +
  7753. +struct yaffs_tnode {
  7754. + struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL];
  7755. +};
  7756. +
  7757. +/*------------------------ Object -----------------------------*/
  7758. +/* An object can be one of:
  7759. + * - a directory (no data, has children links
  7760. + * - a regular file (data.... not prunes :->).
  7761. + * - a symlink [symbolic link] (the alias).
  7762. + * - a hard link
  7763. + */
  7764. +
  7765. +struct yaffs_file_var {
  7766. + loff_t file_size;
  7767. + loff_t scanned_size;
  7768. + loff_t shrink_size;
  7769. + int top_level;
  7770. + struct yaffs_tnode *top;
  7771. +};
  7772. +
  7773. +struct yaffs_dir_var {
  7774. + struct list_head children; /* list of child links */
  7775. + struct list_head dirty; /* Entry for list of dirty directories */
  7776. +};
  7777. +
  7778. +struct yaffs_symlink_var {
  7779. + YCHAR *alias;
  7780. +};
  7781. +
  7782. +struct yaffs_hardlink_var {
  7783. + struct yaffs_obj *equiv_obj;
  7784. + u32 equiv_id;
  7785. +};
  7786. +
  7787. +union yaffs_obj_var {
  7788. + struct yaffs_file_var file_variant;
  7789. + struct yaffs_dir_var dir_variant;
  7790. + struct yaffs_symlink_var symlink_variant;
  7791. + struct yaffs_hardlink_var hardlink_variant;
  7792. +};
  7793. +
  7794. +struct yaffs_obj {
  7795. + u8 deleted:1; /* This should only apply to unlinked files. */
  7796. + u8 soft_del:1; /* it has also been soft deleted */
  7797. + u8 unlinked:1; /* An unlinked file.*/
  7798. + u8 fake:1; /* A fake object has no presence on NAND. */
  7799. + u8 rename_allowed:1; /* Some objects cannot be renamed. */
  7800. + u8 unlink_allowed:1;
  7801. + u8 dirty:1; /* the object needs to be written to flash */
  7802. + u8 valid:1; /* When the file system is being loaded up, this
  7803. + * object might be created before the data
  7804. + * is available
  7805. + * ie. file data chunks encountered before
  7806. + * the header.
  7807. + */
  7808. + u8 lazy_loaded:1; /* This object has been lazy loaded and
  7809. + * is missing some detail */
  7810. +
  7811. + u8 defered_free:1; /* Object is removed from NAND, but is
  7812. + * still in the inode cache.
  7813. + * Free of object is defered.
  7814. + * until the inode is released.
  7815. + */
  7816. + u8 being_created:1; /* This object is still being created
  7817. + * so skip some verification checks. */
  7818. + u8 is_shadowed:1; /* This object is shadowed on the way
  7819. + * to being renamed. */
  7820. +
  7821. + u8 xattr_known:1; /* We know if this has object has xattribs
  7822. + * or not. */
  7823. + u8 has_xattr:1; /* This object has xattribs.
  7824. + * Only valid if xattr_known. */
  7825. +
  7826. + u8 serial; /* serial number of chunk in NAND.*/
  7827. + u16 sum; /* sum of the name to speed searching */
  7828. +
  7829. + struct yaffs_dev *my_dev; /* The device I'm on */
  7830. +
  7831. + struct list_head hash_link; /* list of objects in hash bucket */
  7832. +
  7833. + struct list_head hard_links; /* hard linked object chain*/
  7834. +
  7835. + /* directory structure stuff */
  7836. + /* also used for linking up the free list */
  7837. + struct yaffs_obj *parent;
  7838. + struct list_head siblings;
  7839. +
  7840. + /* Where's my object header in NAND? */
  7841. + int hdr_chunk;
  7842. +
  7843. + int n_data_chunks; /* Number of data chunks for this file. */
  7844. +
  7845. + u32 obj_id; /* the object id value */
  7846. +
  7847. + u32 yst_mode;
  7848. +
  7849. + YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1];
  7850. +
  7851. +#ifdef CONFIG_YAFFS_WINCE
  7852. + u32 win_ctime[2];
  7853. + u32 win_mtime[2];
  7854. + u32 win_atime[2];
  7855. +#else
  7856. + u32 yst_uid;
  7857. + u32 yst_gid;
  7858. + u32 yst_atime;
  7859. + u32 yst_mtime;
  7860. + u32 yst_ctime;
  7861. +#endif
  7862. +
  7863. + u32 yst_rdev;
  7864. +
  7865. + void *my_inode;
  7866. +
  7867. + enum yaffs_obj_type variant_type;
  7868. +
  7869. + union yaffs_obj_var variant;
  7870. +
  7871. +};
  7872. +
  7873. +struct yaffs_obj_bucket {
  7874. + struct list_head list;
  7875. + int count;
  7876. +};
  7877. +
  7878. +/* yaffs_checkpt_obj holds the definition of an object as dumped
  7879. + * by checkpointing.
  7880. + */
  7881. +
  7882. +struct yaffs_checkpt_obj {
  7883. + int struct_type;
  7884. + u32 obj_id;
  7885. + u32 parent_id;
  7886. + int hdr_chunk;
  7887. + enum yaffs_obj_type variant_type:3;
  7888. + u8 deleted:1;
  7889. + u8 soft_del:1;
  7890. + u8 unlinked:1;
  7891. + u8 fake:1;
  7892. + u8 rename_allowed:1;
  7893. + u8 unlink_allowed:1;
  7894. + u8 serial;
  7895. + int n_data_chunks;
  7896. + loff_t size_or_equiv_obj;
  7897. +};
  7898. +
  7899. +/*--------------------- Temporary buffers ----------------
  7900. + *
  7901. + * These are chunk-sized working buffers. Each device has a few.
  7902. + */
  7903. +
  7904. +struct yaffs_buffer {
  7905. + u8 *buffer;
  7906. + int in_use;
  7907. +};
  7908. +
  7909. +/*----------------- Device ---------------------------------*/
  7910. +
  7911. +struct yaffs_param {
  7912. + const YCHAR *name;
  7913. +
  7914. + /*
  7915. + * Entry parameters set up way early. Yaffs sets up the rest.
  7916. + * The structure should be zeroed out before use so that unused
  7917. + * and default values are zero.
  7918. + */
  7919. +
  7920. + int inband_tags; /* Use unband tags */
  7921. + u32 total_bytes_per_chunk; /* Should be >= 512, does not need to
  7922. + be a power of 2 */
  7923. + int chunks_per_block; /* does not need to be a power of 2 */
  7924. + int spare_bytes_per_chunk; /* spare area size */
  7925. + int start_block; /* Start block we're allowed to use */
  7926. + int end_block; /* End block we're allowed to use */
  7927. + int n_reserved_blocks; /* Tuneable so that we can reduce
  7928. + * reserved blocks on NOR and RAM. */
  7929. +
  7930. + int n_caches; /* If <= 0, then short op caching is disabled,
  7931. + * else the number of short op caches.
  7932. + */
  7933. + int cache_bypass_aligned; /* If non-zero then bypass the cache for
  7934. + * aligned writes.
  7935. + */
  7936. +
  7937. + int use_nand_ecc; /* Flag to decide whether or not to use
  7938. + * NAND driver ECC on data (yaffs1) */
  7939. + int tags_9bytes; /* Use 9 byte tags */
  7940. + int no_tags_ecc; /* Flag to decide whether or not to do ECC
  7941. + * on packed tags (yaffs2) */
  7942. +
  7943. + int is_yaffs2; /* Use yaffs2 mode on this device */
  7944. +
  7945. + int empty_lost_n_found; /* Auto-empty lost+found directory on mount */
  7946. +
  7947. + int refresh_period; /* How often to check for a block refresh */
  7948. +
  7949. + /* Checkpoint control. Can be set before or after initialisation */
  7950. + u8 skip_checkpt_rd;
  7951. + u8 skip_checkpt_wr;
  7952. +
  7953. + int enable_xattr; /* Enable xattribs */
  7954. +
  7955. + int max_objects; /*
  7956. + * Set to limit the number of objects created.
  7957. + * 0 = no limit.
  7958. + */
  7959. +
  7960. + /* The remove_obj_fn function must be supplied by OS flavours that
  7961. + * need it.
  7962. + * yaffs direct uses it to implement the faster readdir.
  7963. + * Linux uses it to protect the directory during unlocking.
  7964. + */
  7965. + void (*remove_obj_fn) (struct yaffs_obj *obj);
  7966. +
  7967. + /* Callback to mark the superblock dirty */
  7968. + void (*sb_dirty_fn) (struct yaffs_dev *dev);
  7969. +
  7970. + /* Callback to control garbage collection. */
  7971. + unsigned (*gc_control_fn) (struct yaffs_dev *dev);
  7972. +
  7973. + /* Debug control flags. Don't use unless you know what you're doing */
  7974. + int use_header_file_size; /* Flag to determine if we should use
  7975. + * file sizes from the header */
  7976. + int disable_lazy_load; /* Disable lazy loading on this device */
  7977. + int wide_tnodes_disabled; /* Set to disable wide tnodes */
  7978. + int disable_soft_del; /* yaffs 1 only: Set to disable the use of
  7979. + * softdeletion. */
  7980. +
  7981. + int defered_dir_update; /* Set to defer directory updates */
  7982. +
  7983. +#ifdef CONFIG_YAFFS_AUTO_UNICODE
  7984. + int auto_unicode;
  7985. +#endif
  7986. + int always_check_erased; /* Force chunk erased check always on */
  7987. +
  7988. + int disable_summary;
  7989. + int disable_bad_block_marking;
  7990. +
  7991. +};
  7992. +
  7993. +struct yaffs_driver {
  7994. + int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
  7995. + const u8 *data, int data_len,
  7996. + const u8 *oob, int oob_len);
  7997. + int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
  7998. + u8 *data, int data_len,
  7999. + u8 *oob, int oob_len,
  8000. + enum yaffs_ecc_result *ecc_result);
  8001. + int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no);
  8002. + int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no);
  8003. + int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no);
  8004. + int (*drv_initialise_fn) (struct yaffs_dev *dev);
  8005. + int (*drv_deinitialise_fn) (struct yaffs_dev *dev);
  8006. +};
  8007. +
  8008. +struct yaffs_tags_handler {
  8009. + int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
  8010. + int nand_chunk, const u8 *data,
  8011. + const struct yaffs_ext_tags *tags);
  8012. + int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
  8013. + int nand_chunk, u8 *data,
  8014. + struct yaffs_ext_tags *tags);
  8015. +
  8016. + int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
  8017. + enum yaffs_block_state *state,
  8018. + u32 *seq_number);
  8019. + int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no);
  8020. +};
  8021. +
  8022. +struct yaffs_dev {
  8023. + struct yaffs_param param;
  8024. + struct yaffs_driver drv;
  8025. + struct yaffs_tags_handler tagger;
  8026. +
  8027. + /* Context storage. Holds extra OS specific data for this device */
  8028. +
  8029. + void *os_context;
  8030. + void *driver_context;
  8031. +
  8032. + struct list_head dev_list;
  8033. +
  8034. + int ll_init;
  8035. + /* Runtime parameters. Set up by YAFFS. */
  8036. + int data_bytes_per_chunk;
  8037. +
  8038. + /* Non-wide tnode stuff */
  8039. + u16 chunk_grp_bits; /* Number of bits that need to be resolved if
  8040. + * the tnodes are not wide enough.
  8041. + */
  8042. + u16 chunk_grp_size; /* == 2^^chunk_grp_bits */
  8043. +
  8044. + /* Stuff to support wide tnodes */
  8045. + u32 tnode_width;
  8046. + u32 tnode_mask;
  8047. + u32 tnode_size;
  8048. +
  8049. + /* Stuff for figuring out file offset to chunk conversions */
  8050. + u32 chunk_shift; /* Shift value */
  8051. + u32 chunk_div; /* Divisor after shifting: 1 for 2^n sizes */
  8052. + u32 chunk_mask; /* Mask to use for power-of-2 case */
  8053. +
  8054. + int is_mounted;
  8055. + int read_only;
  8056. + int is_checkpointed;
  8057. +
  8058. + /* Stuff to support block offsetting to support start block zero */
  8059. + int internal_start_block;
  8060. + int internal_end_block;
  8061. + int block_offset;
  8062. + int chunk_offset;
  8063. +
  8064. + /* Runtime checkpointing stuff */
  8065. + int checkpt_page_seq; /* running sequence number of checkpt pages */
  8066. + int checkpt_byte_count;
  8067. + int checkpt_byte_offs;
  8068. + u8 *checkpt_buffer;
  8069. + int checkpt_open_write;
  8070. + int blocks_in_checkpt;
  8071. + int checkpt_cur_chunk;
  8072. + int checkpt_cur_block;
  8073. + int checkpt_next_block;
  8074. + int *checkpt_block_list;
  8075. + int checkpt_max_blocks;
  8076. + u32 checkpt_sum;
  8077. + u32 checkpt_xor;
  8078. +
  8079. + int checkpoint_blocks_required; /* Number of blocks needed to store
  8080. + * current checkpoint set */
  8081. +
  8082. + /* Block Info */
  8083. + struct yaffs_block_info *block_info;
  8084. + u8 *chunk_bits; /* bitmap of chunks in use */
  8085. + u8 block_info_alt:1; /* allocated using alternative alloc */
  8086. + u8 chunk_bits_alt:1; /* allocated using alternative alloc */
  8087. + int chunk_bit_stride; /* Number of bytes of chunk_bits per block.
  8088. + * Must be consistent with chunks_per_block.
  8089. + */
  8090. +
  8091. + int n_erased_blocks;
  8092. + int alloc_block; /* Current block being allocated off */
  8093. + u32 alloc_page;
  8094. + int alloc_block_finder; /* Used to search for next allocation block */
  8095. +
  8096. + /* Object and Tnode memory management */
  8097. + void *allocator;
  8098. + int n_obj;
  8099. + int n_tnodes;
  8100. +
  8101. + int n_hardlinks;
  8102. +
  8103. + struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS];
  8104. + u32 bucket_finder;
  8105. +
  8106. + int n_free_chunks;
  8107. +
  8108. + /* Garbage collection control */
  8109. + u32 *gc_cleanup_list; /* objects to delete at the end of a GC. */
  8110. + u32 n_clean_ups;
  8111. +
  8112. + unsigned has_pending_prioritised_gc; /* We think this device might
  8113. + have pending prioritised gcs */
  8114. + unsigned gc_disable;
  8115. + unsigned gc_block_finder;
  8116. + unsigned gc_dirtiest;
  8117. + unsigned gc_pages_in_use;
  8118. + unsigned gc_not_done;
  8119. + unsigned gc_block;
  8120. + unsigned gc_chunk;
  8121. + unsigned gc_skip;
  8122. + struct yaffs_summary_tags *gc_sum_tags;
  8123. +
  8124. + /* Special directories */
  8125. + struct yaffs_obj *root_dir;
  8126. + struct yaffs_obj *lost_n_found;
  8127. +
  8128. + int buffered_block; /* Which block is buffered here? */
  8129. + int doing_buffered_block_rewrite;
  8130. +
  8131. + struct yaffs_cache *cache;
  8132. + int cache_last_use;
  8133. +
  8134. + /* Stuff for background deletion and unlinked files. */
  8135. + struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted
  8136. + files live. */
  8137. + struct yaffs_obj *del_dir; /* Directory where deleted objects are
  8138. + sent to disappear. */
  8139. + struct yaffs_obj *unlinked_deletion; /* Current file being
  8140. + background deleted. */
  8141. + int n_deleted_files; /* Count of files awaiting deletion; */
  8142. + int n_unlinked_files; /* Count of unlinked files. */
  8143. + int n_bg_deletions; /* Count of background deletions. */
  8144. +
  8145. + /* Temporary buffer management */
  8146. + struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS];
  8147. + int max_temp;
  8148. + int temp_in_use;
  8149. + int unmanaged_buffer_allocs;
  8150. + int unmanaged_buffer_deallocs;
  8151. +
  8152. + /* yaffs2 runtime stuff */
  8153. + unsigned seq_number; /* Sequence number of currently
  8154. + allocating block */
  8155. + unsigned oldest_dirty_seq;
  8156. + unsigned oldest_dirty_block;
  8157. +
  8158. + /* Block refreshing */
  8159. + int refresh_skip; /* A skip down counter.
  8160. + * Refresh happens when this gets to zero. */
  8161. +
  8162. + /* Dirty directory handling */
  8163. + struct list_head dirty_dirs; /* List of dirty directories */
  8164. +
  8165. + /* Summary */
  8166. + int chunks_per_summary;
  8167. + struct yaffs_summary_tags *sum_tags;
  8168. +
  8169. + /* Statistics */
  8170. + u32 n_page_writes;
  8171. + u32 n_page_reads;
  8172. + u32 n_erasures;
  8173. + u32 n_bad_queries;
  8174. + u32 n_bad_markings;
  8175. + u32 n_erase_failures;
  8176. + u32 n_gc_copies;
  8177. + u32 all_gcs;
  8178. + u32 passive_gc_count;
  8179. + u32 oldest_dirty_gc_count;
  8180. + u32 n_gc_blocks;
  8181. + u32 bg_gcs;
  8182. + u32 n_retried_writes;
  8183. + u32 n_retired_blocks;
  8184. + u32 n_ecc_fixed;
  8185. + u32 n_ecc_unfixed;
  8186. + u32 n_tags_ecc_fixed;
  8187. + u32 n_tags_ecc_unfixed;
  8188. + u32 n_deletions;
  8189. + u32 n_unmarked_deletions;
  8190. + u32 refresh_count;
  8191. + u32 cache_hits;
  8192. + u32 tags_used;
  8193. + u32 summary_used;
  8194. +
  8195. +};
  8196. +
  8197. +/* The CheckpointDevice structure holds the device information that changes
  8198. + *at runtime and must be preserved over unmount/mount cycles.
  8199. + */
  8200. +struct yaffs_checkpt_dev {
  8201. + int struct_type;
  8202. + int n_erased_blocks;
  8203. + int alloc_block; /* Current block being allocated off */
  8204. + u32 alloc_page;
  8205. + int n_free_chunks;
  8206. +
  8207. + int n_deleted_files; /* Count of files awaiting deletion; */
  8208. + int n_unlinked_files; /* Count of unlinked files. */
  8209. + int n_bg_deletions; /* Count of background deletions. */
  8210. +
  8211. + /* yaffs2 runtime stuff */
  8212. + unsigned seq_number; /* Sequence number of currently
  8213. + * allocating block */
  8214. +
  8215. +};
  8216. +
  8217. +struct yaffs_checkpt_validity {
  8218. + int struct_type;
  8219. + u32 magic;
  8220. + u32 version;
  8221. + u32 head;
  8222. +};
  8223. +
  8224. +struct yaffs_shadow_fixer {
  8225. + int obj_id;
  8226. + int shadowed_id;
  8227. + struct yaffs_shadow_fixer *next;
  8228. +};
  8229. +
  8230. +/* Structure for doing xattr modifications */
  8231. +struct yaffs_xattr_mod {
  8232. + int set; /* If 0 then this is a deletion */
  8233. + const YCHAR *name;
  8234. + const void *data;
  8235. + int size;
  8236. + int flags;
  8237. + int result;
  8238. +};
  8239. +
  8240. +/*----------------------- YAFFS Functions -----------------------*/
  8241. +
  8242. +int yaffs_guts_initialise(struct yaffs_dev *dev);
  8243. +void yaffs_deinitialise(struct yaffs_dev *dev);
  8244. +
  8245. +int yaffs_get_n_free_chunks(struct yaffs_dev *dev);
  8246. +
  8247. +int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
  8248. + struct yaffs_obj *new_dir, const YCHAR * new_name);
  8249. +
  8250. +int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name);
  8251. +int yaffs_del_obj(struct yaffs_obj *obj);
  8252. +struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
  8253. + enum yaffs_obj_type type);
  8254. +
  8255. +
  8256. +int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
  8257. +loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
  8258. +int yaffs_get_obj_inode(struct yaffs_obj *obj);
  8259. +unsigned yaffs_get_obj_type(struct yaffs_obj *obj);
  8260. +int yaffs_get_obj_link_count(struct yaffs_obj *obj);
  8261. +
  8262. +/* File operations */
  8263. +int yaffs_file_rd(struct yaffs_obj *obj, u8 * buffer, loff_t offset,
  8264. + int n_bytes);
  8265. +int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset,
  8266. + int n_bytes, int write_trhrough);
  8267. +int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size);
  8268. +
  8269. +struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
  8270. + const YCHAR *name, u32 mode, u32 uid,
  8271. + u32 gid);
  8272. +
  8273. +int yaffs_flush_file(struct yaffs_obj *obj, int update_time, int data_sync);
  8274. +
  8275. +/* Flushing and checkpointing */
  8276. +void yaffs_flush_whole_cache(struct yaffs_dev *dev);
  8277. +
  8278. +int yaffs_checkpoint_save(struct yaffs_dev *dev);
  8279. +int yaffs_checkpoint_restore(struct yaffs_dev *dev);
  8280. +
  8281. +/* Directory operations */
  8282. +struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name,
  8283. + u32 mode, u32 uid, u32 gid);
  8284. +struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir,
  8285. + const YCHAR *name);
  8286. +struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number);
  8287. +
  8288. +/* Link operations */
  8289. +struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name,
  8290. + struct yaffs_obj *equiv_obj);
  8291. +
  8292. +struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj);
  8293. +
  8294. +/* Symlink operations */
  8295. +struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
  8296. + const YCHAR *name, u32 mode, u32 uid,
  8297. + u32 gid, const YCHAR *alias);
  8298. +YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj);
  8299. +
  8300. +/* Special inodes (fifos, sockets and devices) */
  8301. +struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
  8302. + const YCHAR *name, u32 mode, u32 uid,
  8303. + u32 gid, u32 rdev);
  8304. +
  8305. +int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name,
  8306. + const void *value, int size, int flags);
  8307. +int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value,
  8308. + int size);
  8309. +int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size);
  8310. +int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name);
  8311. +
  8312. +/* Special directories */
  8313. +struct yaffs_obj *yaffs_root(struct yaffs_dev *dev);
  8314. +struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev);
  8315. +
  8316. +void yaffs_handle_defered_free(struct yaffs_obj *obj);
  8317. +
  8318. +void yaffs_update_dirty_dirs(struct yaffs_dev *dev);
  8319. +
  8320. +int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency);
  8321. +
  8322. +/* Debug dump */
  8323. +int yaffs_dump_obj(struct yaffs_obj *obj);
  8324. +
  8325. +void yaffs_guts_test(struct yaffs_dev *dev);
  8326. +int yaffs_guts_ll_init(struct yaffs_dev *dev);
  8327. +
  8328. +
  8329. +/* A few useful functions to be used within the core files*/
  8330. +void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
  8331. + int lyn);
  8332. +int yaffs_check_ff(u8 *buffer, int n_bytes);
  8333. +void yaffs_handle_chunk_error(struct yaffs_dev *dev,
  8334. + struct yaffs_block_info *bi);
  8335. +
  8336. +u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev);
  8337. +void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer);
  8338. +
  8339. +struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
  8340. + int number,
  8341. + enum yaffs_obj_type type);
  8342. +int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  8343. + int nand_chunk, int in_scan);
  8344. +void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name);
  8345. +void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
  8346. + const struct yaffs_obj_hdr *oh);
  8347. +void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj);
  8348. +YCHAR *yaffs_clone_str(const YCHAR *str);
  8349. +void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list);
  8350. +void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no);
  8351. +int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name,
  8352. + int force, int is_shrink, int shadows,
  8353. + struct yaffs_xattr_mod *xop);
  8354. +void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id,
  8355. + int backward_scanning);
  8356. +int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks);
  8357. +struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev);
  8358. +struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
  8359. + struct yaffs_file_var *file_struct,
  8360. + u32 chunk_id,
  8361. + struct yaffs_tnode *passed_tn);
  8362. +
  8363. +int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
  8364. + int n_bytes, int write_trhrough);
  8365. +void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size);
  8366. +void yaffs_skip_rest_of_block(struct yaffs_dev *dev);
  8367. +
  8368. +int yaffs_count_free_chunks(struct yaffs_dev *dev);
  8369. +
  8370. +struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
  8371. + struct yaffs_file_var *file_struct,
  8372. + u32 chunk_id);
  8373. +
  8374. +u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
  8375. + unsigned pos);
  8376. +
  8377. +int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
  8378. +
  8379. +int yaffs_guts_format_dev(struct yaffs_dev *dev);
  8380. +
  8381. +void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
  8382. + int *chunk_out, u32 *offset_out);
  8383. +/*
  8384. + * Marshalling functions to get loff_t file sizes into aand out of
  8385. + * object headers.
  8386. + */
  8387. +void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize);
  8388. +loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh);
  8389. +loff_t yaffs_max_file_size(struct yaffs_dev *dev);
  8390. +
  8391. +/*
  8392. + * Debug function to count number of blocks in each state
  8393. + * NB Needs to be called with correct number of integers
  8394. + */
  8395. +
  8396. +void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10]);
  8397. +
  8398. +int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
  8399. + struct yaffs_ext_tags *tags);
  8400. +
  8401. +#endif
  8402. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_linux.h linux-3.14.4/fs/yaffs2/yaffs_linux.h
  8403. --- linux-3.14.4.orig/fs/yaffs2/yaffs_linux.h 1970-01-01 01:00:00.000000000 +0100
  8404. +++ linux-3.14.4/fs/yaffs2/yaffs_linux.h 2014-05-14 12:41:23.984792448 +0200
  8405. @@ -0,0 +1,48 @@
  8406. +/*
  8407. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  8408. + *
  8409. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8410. + * for Toby Churchill Ltd and Brightstar Engineering
  8411. + *
  8412. + * Created by Charles Manning <charles@aleph1.co.uk>
  8413. + *
  8414. + * This program is free software; you can redistribute it and/or modify
  8415. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  8416. + * published by the Free Software Foundation.
  8417. + *
  8418. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  8419. + */
  8420. +
  8421. +#ifndef __YAFFS_LINUX_H__
  8422. +#define __YAFFS_LINUX_H__
  8423. +
  8424. +#include "yportenv.h"
  8425. +
  8426. +struct yaffs_linux_context {
  8427. + struct list_head context_list; /* List of these we have mounted */
  8428. + struct yaffs_dev *dev;
  8429. + struct super_block *super;
  8430. + struct task_struct *bg_thread; /* Background thread for this device */
  8431. + int bg_running;
  8432. + struct mutex gross_lock; /* Gross locking mutex*/
  8433. + u8 *spare_buffer; /* For mtdif2 use. Don't know the buffer size
  8434. + * at compile time so we have to allocate it.
  8435. + */
  8436. + struct list_head search_contexts;
  8437. + struct task_struct *readdir_process;
  8438. + unsigned mount_id;
  8439. + int dirty;
  8440. +};
  8441. +
  8442. +#define yaffs_dev_to_lc(dev) ((struct yaffs_linux_context *)((dev)->os_context))
  8443. +#define yaffs_dev_to_mtd(dev) ((struct mtd_info *)((dev)->driver_context))
  8444. +
  8445. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  8446. +#define WRITE_SIZE_STR "writesize"
  8447. +#define WRITE_SIZE(mtd) ((mtd)->writesize)
  8448. +#else
  8449. +#define WRITE_SIZE_STR "oobblock"
  8450. +#define WRITE_SIZE(mtd) ((mtd)->oobblock)
  8451. +#endif
  8452. +
  8453. +#endif
  8454. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_mtdif.c linux-3.14.4/fs/yaffs2/yaffs_mtdif.c
  8455. --- linux-3.14.4.orig/fs/yaffs2/yaffs_mtdif.c 1970-01-01 01:00:00.000000000 +0100
  8456. +++ linux-3.14.4/fs/yaffs2/yaffs_mtdif.c 2014-05-14 15:31:25.487474877 +0200
  8457. @@ -0,0 +1,309 @@
  8458. +/*
  8459. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  8460. + *
  8461. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8462. + * for Toby Churchill Ltd and Brightstar Engineering
  8463. + *
  8464. + * Created by Charles Manning <charles@aleph1.co.uk>
  8465. + *
  8466. + * This program is free software; you can redistribute it and/or modify
  8467. + * it under the terms of the GNU General Public License version 2 as
  8468. + * published by the Free Software Foundation.
  8469. + */
  8470. +
  8471. +#include "yportenv.h"
  8472. +
  8473. +#include "yaffs_mtdif.h"
  8474. +
  8475. +#include "linux/mtd/mtd.h"
  8476. +#include "linux/types.h"
  8477. +#include "linux/time.h"
  8478. +#include "linux/major.h"
  8479. +#include "linux/mtd/nand.h"
  8480. +#include "linux/kernel.h"
  8481. +#include "linux/version.h"
  8482. +#include "linux/types.h"
  8483. +
  8484. +#include "yaffs_trace.h"
  8485. +#include "yaffs_guts.h"
  8486. +#include "yaffs_linux.h"
  8487. +
  8488. +
  8489. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
  8490. +#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
  8491. +#endif
  8492. +
  8493. +
  8494. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
  8495. +#define mtd_erase(m, ei) (m)->erase(m, ei)
  8496. +#define mtd_write_oob(m, addr, pops) (m)->write_oob(m, addr, pops)
  8497. +#define mtd_read_oob(m, addr, pops) (m)->read_oob(m, addr, pops)
  8498. +#define mtd_block_isbad(m, offs) (m)->block_isbad(m, offs)
  8499. +#define mtd_block_markbad(m, offs) (m)->block_markbad(m, offs)
  8500. +#endif
  8501. +
  8502. +
  8503. +
  8504. +int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
  8505. +{
  8506. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8507. + u32 addr =
  8508. + ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
  8509. + dev->param.chunks_per_block;
  8510. + struct erase_info ei;
  8511. + int retval = 0;
  8512. +
  8513. + ei.mtd = mtd;
  8514. + ei.addr = addr;
  8515. + ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
  8516. + ei.time = 1000;
  8517. + ei.retries = 2;
  8518. + ei.callback = NULL;
  8519. + ei.priv = (u_long) dev;
  8520. +
  8521. + retval = mtd_erase(mtd, &ei);
  8522. +
  8523. + if (retval == 0)
  8524. + return YAFFS_OK;
  8525. +
  8526. + return YAFFS_FAIL;
  8527. +}
  8528. +
  8529. +
  8530. +static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
  8531. + const u8 *data, int data_len,
  8532. + const u8 *oob, int oob_len)
  8533. +{
  8534. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8535. + loff_t addr;
  8536. + struct mtd_oob_ops ops;
  8537. + int retval;
  8538. +
  8539. + yaffs_trace(YAFFS_TRACE_MTD,
  8540. + "yaffs_mtd_write(%p, %d, %p, %d, %p, %d)\n",
  8541. + dev, nand_chunk, data, data_len, oob, oob_len);
  8542. +
  8543. + if (!data || !data_len) {
  8544. + data = NULL;
  8545. + data_len = 0;
  8546. + }
  8547. +
  8548. + if (!oob || !oob_len) {
  8549. + oob = NULL;
  8550. + oob_len = 0;
  8551. + }
  8552. +
  8553. + addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
  8554. + memset(&ops, 0, sizeof(ops));
  8555. + ops.mode = MTD_OPS_AUTO_OOB;
  8556. + ops.len = (data) ? data_len : 0;
  8557. + ops.ooblen = oob_len;
  8558. + ops.datbuf = (u8 *)data;
  8559. + ops.oobbuf = (u8 *)oob;
  8560. +
  8561. + retval = mtd_write_oob(mtd, addr, &ops);
  8562. + if (retval) {
  8563. + yaffs_trace(YAFFS_TRACE_MTD,
  8564. + "write_oob failed, chunk %d, mtd error %d",
  8565. + nand_chunk, retval);
  8566. + }
  8567. + return retval ? YAFFS_FAIL : YAFFS_OK;
  8568. +}
  8569. +
  8570. +static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk,
  8571. + u8 *data, int data_len,
  8572. + u8 *oob, int oob_len,
  8573. + enum yaffs_ecc_result *ecc_result)
  8574. +{
  8575. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8576. + loff_t addr;
  8577. + struct mtd_oob_ops ops;
  8578. + int retval;
  8579. +
  8580. + addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
  8581. + memset(&ops, 0, sizeof(ops));
  8582. + ops.mode = MTD_OPS_AUTO_OOB;
  8583. + ops.len = (data) ? data_len : 0;
  8584. + ops.ooblen = oob_len;
  8585. + ops.datbuf = data;
  8586. + ops.oobbuf = oob;
  8587. +
  8588. +#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
  8589. + /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
  8590. + * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
  8591. + */
  8592. + ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
  8593. +#endif
  8594. + /* Read page and oob using MTD.
  8595. + * Check status and determine ECC result.
  8596. + */
  8597. + retval = mtd_read_oob(mtd, addr, &ops);
  8598. + if (retval)
  8599. + yaffs_trace(YAFFS_TRACE_MTD,
  8600. + "read_oob failed, chunk %d, mtd error %d",
  8601. + nand_chunk, retval);
  8602. +
  8603. + switch (retval) {
  8604. + case 0:
  8605. + /* no error */
  8606. + if(ecc_result)
  8607. + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  8608. + break;
  8609. +
  8610. + case -EUCLEAN:
  8611. + /* MTD's ECC fixed the data */
  8612. + if(ecc_result)
  8613. + *ecc_result = YAFFS_ECC_RESULT_FIXED;
  8614. + dev->n_ecc_fixed++;
  8615. + break;
  8616. +
  8617. + case -EBADMSG:
  8618. + default:
  8619. + /* MTD's ECC could not fix the data */
  8620. + dev->n_ecc_unfixed++;
  8621. + if(ecc_result)
  8622. + *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  8623. + return YAFFS_FAIL;
  8624. + }
  8625. +
  8626. + return YAFFS_OK;
  8627. +}
  8628. +
  8629. +static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
  8630. +{
  8631. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8632. +
  8633. + loff_t addr;
  8634. + struct erase_info ei;
  8635. + int retval = 0;
  8636. + u32 block_size;
  8637. +
  8638. + block_size = dev->param.total_bytes_per_chunk *
  8639. + dev->param.chunks_per_block;
  8640. + addr = ((loff_t) block_no) * block_size;
  8641. +
  8642. + ei.mtd = mtd;
  8643. + ei.addr = addr;
  8644. + ei.len = block_size;
  8645. + ei.time = 1000;
  8646. + ei.retries = 2;
  8647. + ei.callback = NULL;
  8648. + ei.priv = (u_long) dev;
  8649. +
  8650. + retval = mtd_erase(mtd, &ei);
  8651. +
  8652. + if (retval == 0)
  8653. + return YAFFS_OK;
  8654. +
  8655. + return YAFFS_FAIL;
  8656. +}
  8657. +
  8658. +static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no)
  8659. +{
  8660. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8661. + int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk;
  8662. + int retval;
  8663. +
  8664. + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
  8665. +
  8666. + retval = mtd_block_markbad(mtd, (loff_t) blocksize * block_no);
  8667. + return (retval) ? YAFFS_FAIL : YAFFS_OK;
  8668. +}
  8669. +
  8670. +static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no)
  8671. +{
  8672. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  8673. + int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk;
  8674. + int retval;
  8675. +
  8676. + yaffs_trace(YAFFS_TRACE_MTD, "checking block %d bad", block_no);
  8677. +
  8678. + retval = mtd_block_isbad(mtd, (loff_t) blocksize * block_no);
  8679. + return (retval) ? YAFFS_FAIL : YAFFS_OK;
  8680. +}
  8681. +
  8682. +static int yaffs_mtd_initialise(struct yaffs_dev *dev)
  8683. +{
  8684. + return YAFFS_OK;
  8685. +}
  8686. +
  8687. +static int yaffs_mtd_deinitialise(struct yaffs_dev *dev)
  8688. +{
  8689. + return YAFFS_OK;
  8690. +}
  8691. +
  8692. +
  8693. +void yaffs_mtd_drv_install(struct yaffs_dev *dev)
  8694. +{
  8695. + struct yaffs_driver *drv = &dev->drv;
  8696. +
  8697. + drv->drv_write_chunk_fn = yaffs_mtd_write;
  8698. + drv->drv_read_chunk_fn = yaffs_mtd_read;
  8699. + drv->drv_erase_fn = yaffs_mtd_erase;
  8700. + drv->drv_mark_bad_fn = yaffs_mtd_mark_bad;
  8701. + drv->drv_check_bad_fn = yaffs_mtd_check_bad;
  8702. + drv->drv_initialise_fn = yaffs_mtd_initialise;
  8703. + drv->drv_deinitialise_fn = yaffs_mtd_deinitialise;
  8704. +}
  8705. +
  8706. +
  8707. +struct mtd_info * yaffs_get_mtd_device(dev_t sdev)
  8708. +{
  8709. + struct mtd_info *mtd;
  8710. +
  8711. + mtd = yaffs_get_mtd_device(sdev);
  8712. +
  8713. + /* Check it's an mtd device..... */
  8714. + if (MAJOR(sdev) != MTD_BLOCK_MAJOR)
  8715. + return NULL; /* This isn't an mtd device */
  8716. +
  8717. + /* Check it's NAND */
  8718. + if (mtd->type != MTD_NANDFLASH) {
  8719. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  8720. + "yaffs: MTD device is not NAND it's type %d",
  8721. + mtd->type);
  8722. + return NULL;
  8723. + }
  8724. +
  8725. + yaffs_trace(YAFFS_TRACE_OS, " %s %d", WRITE_SIZE_STR, WRITE_SIZE(mtd));
  8726. + yaffs_trace(YAFFS_TRACE_OS, " oobsize %d", mtd->oobsize);
  8727. + yaffs_trace(YAFFS_TRACE_OS, " erasesize %d", mtd->erasesize);
  8728. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
  8729. + yaffs_trace(YAFFS_TRACE_OS, " size %u", mtd->size);
  8730. +#else
  8731. + yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size);
  8732. +#endif
  8733. +
  8734. + return mtd;
  8735. +}
  8736. +
  8737. +int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags)
  8738. +{
  8739. + if (yaffs_version == 2) {
  8740. + if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
  8741. + mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
  8742. + !inband_tags) {
  8743. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  8744. + "MTD device does not have the right page sizes"
  8745. + );
  8746. + return -1;
  8747. + }
  8748. + } else {
  8749. + if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK ||
  8750. + mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
  8751. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  8752. + "MTD device does not support have the right page sizes"
  8753. + );
  8754. + return -1;
  8755. + }
  8756. + }
  8757. +
  8758. + return 0;
  8759. +}
  8760. +
  8761. +
  8762. +void yaffs_put_mtd_device(struct mtd_info *mtd)
  8763. +{
  8764. + if(mtd)
  8765. + put_mtd_device(mtd);
  8766. +}
  8767. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_mtdif.h linux-3.14.4/fs/yaffs2/yaffs_mtdif.h
  8768. --- linux-3.14.4.orig/fs/yaffs2/yaffs_mtdif.h 1970-01-01 01:00:00.000000000 +0100
  8769. +++ linux-3.14.4/fs/yaffs2/yaffs_mtdif.h 2014-05-14 12:41:23.984792448 +0200
  8770. @@ -0,0 +1,25 @@
  8771. +/*
  8772. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  8773. + *
  8774. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8775. + * for Toby Churchill Ltd and Brightstar Engineering
  8776. + *
  8777. + * Created by Charles Manning <charles@aleph1.co.uk>
  8778. + *
  8779. + * This program is free software; you can redistribute it and/or modify
  8780. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  8781. + * published by the Free Software Foundation.
  8782. + *
  8783. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  8784. + */
  8785. +
  8786. +#ifndef __YAFFS_MTDIF_H__
  8787. +#define __YAFFS_MTDIF_H__
  8788. +
  8789. +#include "yaffs_guts.h"
  8790. +
  8791. +void yaffs_mtd_drv_install(struct yaffs_dev *dev);
  8792. +struct mtd_info * yaffs_get_mtd_device(dev_t sdev);
  8793. +void yaffs_put_mtd_device(struct mtd_info *mtd);
  8794. +int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags);
  8795. +#endif
  8796. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_nameval.c linux-3.14.4/fs/yaffs2/yaffs_nameval.c
  8797. --- linux-3.14.4.orig/fs/yaffs2/yaffs_nameval.c 1970-01-01 01:00:00.000000000 +0100
  8798. +++ linux-3.14.4/fs/yaffs2/yaffs_nameval.c 2014-05-14 12:41:23.984792448 +0200
  8799. @@ -0,0 +1,208 @@
  8800. +/*
  8801. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  8802. + *
  8803. + * Copyright (C) 2002-2011 Aleph One Ltd.
  8804. + * for Toby Churchill Ltd and Brightstar Engineering
  8805. + *
  8806. + * Created by Charles Manning <charles@aleph1.co.uk>
  8807. + *
  8808. + * This program is free software; you can redistribute it and/or modify
  8809. + * it under the terms of the GNU General Public License version 2 as
  8810. + * published by the Free Software Foundation.
  8811. + */
  8812. +
  8813. +/*
  8814. + * This simple implementation of a name-value store assumes a small number of
  8815. +* values and fits into a small finite buffer.
  8816. + *
  8817. + * Each attribute is stored as a record:
  8818. + * sizeof(int) bytes record size.
  8819. + * strnlen+1 bytes name null terminated.
  8820. + * nbytes value.
  8821. + * ----------
  8822. + * total size stored in record size
  8823. + *
  8824. + * This code has not been tested with unicode yet.
  8825. + */
  8826. +
  8827. +#include "yaffs_nameval.h"
  8828. +
  8829. +#include "yportenv.h"
  8830. +
  8831. +static int nval_find(const char *xb, int xb_size, const YCHAR *name,
  8832. + int *exist_size)
  8833. +{
  8834. + int pos = 0;
  8835. + int size;
  8836. +
  8837. + memcpy(&size, xb, sizeof(int));
  8838. + while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
  8839. + if (!strncmp((YCHAR *) (xb + pos + sizeof(int)),
  8840. + name, size)) {
  8841. + if (exist_size)
  8842. + *exist_size = size;
  8843. + return pos;
  8844. + }
  8845. + pos += size;
  8846. + if (pos < xb_size - sizeof(int))
  8847. + memcpy(&size, xb + pos, sizeof(int));
  8848. + else
  8849. + size = 0;
  8850. + }
  8851. + if (exist_size)
  8852. + *exist_size = 0;
  8853. + return -ENODATA;
  8854. +}
  8855. +
  8856. +static int nval_used(const char *xb, int xb_size)
  8857. +{
  8858. + int pos = 0;
  8859. + int size;
  8860. +
  8861. + memcpy(&size, xb + pos, sizeof(int));
  8862. + while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
  8863. + pos += size;
  8864. + if (pos < xb_size - sizeof(int))
  8865. + memcpy(&size, xb + pos, sizeof(int));
  8866. + else
  8867. + size = 0;
  8868. + }
  8869. + return pos;
  8870. +}
  8871. +
  8872. +int nval_del(char *xb, int xb_size, const YCHAR *name)
  8873. +{
  8874. + int pos = nval_find(xb, xb_size, name, NULL);
  8875. + int size;
  8876. +
  8877. + if (pos < 0 || pos >= xb_size)
  8878. + return -ENODATA;
  8879. +
  8880. + /* Find size, shift rest over this record,
  8881. + * then zero out the rest of buffer */
  8882. + memcpy(&size, xb + pos, sizeof(int));
  8883. + memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
  8884. + memset(xb + (xb_size - size), 0, size);
  8885. + return 0;
  8886. +}
  8887. +
  8888. +int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf,
  8889. + int bsize, int flags)
  8890. +{
  8891. + int pos;
  8892. + int namelen = strnlen(name, xb_size);
  8893. + int reclen;
  8894. + int size_exist = 0;
  8895. + int space;
  8896. + int start;
  8897. +
  8898. + pos = nval_find(xb, xb_size, name, &size_exist);
  8899. +
  8900. + if (flags & XATTR_CREATE && pos >= 0)
  8901. + return -EEXIST;
  8902. + if (flags & XATTR_REPLACE && pos < 0)
  8903. + return -ENODATA;
  8904. +
  8905. + start = nval_used(xb, xb_size);
  8906. + space = xb_size - start + size_exist;
  8907. +
  8908. + reclen = (sizeof(int) + namelen + 1 + bsize);
  8909. +
  8910. + if (reclen > space)
  8911. + return -ENOSPC;
  8912. +
  8913. + if (pos >= 0) {
  8914. + nval_del(xb, xb_size, name);
  8915. + start = nval_used(xb, xb_size);
  8916. + }
  8917. +
  8918. + pos = start;
  8919. +
  8920. + memcpy(xb + pos, &reclen, sizeof(int));
  8921. + pos += sizeof(int);
  8922. + strncpy((YCHAR *) (xb + pos), name, reclen);
  8923. + pos += (namelen + 1);
  8924. + memcpy(xb + pos, buf, bsize);
  8925. + return 0;
  8926. +}
  8927. +
  8928. +int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
  8929. + int bsize)
  8930. +{
  8931. + int pos = nval_find(xb, xb_size, name, NULL);
  8932. + int size;
  8933. +
  8934. + if (pos >= 0 && pos < xb_size) {
  8935. +
  8936. + memcpy(&size, xb + pos, sizeof(int));
  8937. + pos += sizeof(int); /* advance past record length */
  8938. + size -= sizeof(int);
  8939. +
  8940. + /* Advance over name string */
  8941. + while (xb[pos] && size > 0 && pos < xb_size) {
  8942. + pos++;
  8943. + size--;
  8944. + }
  8945. + /*Advance over NUL */
  8946. + pos++;
  8947. + size--;
  8948. +
  8949. + /* If bsize is zero then this is a size query.
  8950. + * Return the size, but don't copy.
  8951. + */
  8952. + if (!bsize)
  8953. + return size;
  8954. +
  8955. + if (size <= bsize) {
  8956. + memcpy(buf, xb + pos, size);
  8957. + return size;
  8958. + }
  8959. + }
  8960. + if (pos >= 0)
  8961. + return -ERANGE;
  8962. +
  8963. + return -ENODATA;
  8964. +}
  8965. +
  8966. +int nval_list(const char *xb, int xb_size, char *buf, int bsize)
  8967. +{
  8968. + int pos = 0;
  8969. + int size;
  8970. + int name_len;
  8971. + int ncopied = 0;
  8972. + int filled = 0;
  8973. +
  8974. + memcpy(&size, xb + pos, sizeof(int));
  8975. + while (size > sizeof(int) &&
  8976. + size <= xb_size &&
  8977. + (pos + size) < xb_size &&
  8978. + !filled) {
  8979. + pos += sizeof(int);
  8980. + size -= sizeof(int);
  8981. + name_len = strnlen((YCHAR *) (xb + pos), size);
  8982. + if (ncopied + name_len + 1 < bsize) {
  8983. + memcpy(buf, xb + pos, name_len * sizeof(YCHAR));
  8984. + buf += name_len;
  8985. + *buf = '\0';
  8986. + buf++;
  8987. + if (sizeof(YCHAR) > 1) {
  8988. + *buf = '\0';
  8989. + buf++;
  8990. + }
  8991. + ncopied += (name_len + 1);
  8992. + } else {
  8993. + filled = 1;
  8994. + }
  8995. + pos += size;
  8996. + if (pos < xb_size - sizeof(int))
  8997. + memcpy(&size, xb + pos, sizeof(int));
  8998. + else
  8999. + size = 0;
  9000. + }
  9001. + return ncopied;
  9002. +}
  9003. +
  9004. +int nval_hasvalues(const char *xb, int xb_size)
  9005. +{
  9006. + return nval_used(xb, xb_size) > 0;
  9007. +}
  9008. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_nameval.h linux-3.14.4/fs/yaffs2/yaffs_nameval.h
  9009. --- linux-3.14.4.orig/fs/yaffs2/yaffs_nameval.h 1970-01-01 01:00:00.000000000 +0100
  9010. +++ linux-3.14.4/fs/yaffs2/yaffs_nameval.h 2014-05-14 12:41:23.984792448 +0200
  9011. @@ -0,0 +1,28 @@
  9012. +/*
  9013. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9014. + *
  9015. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9016. + * for Toby Churchill Ltd and Brightstar Engineering
  9017. + *
  9018. + * Created by Charles Manning <charles@aleph1.co.uk>
  9019. + *
  9020. + * This program is free software; you can redistribute it and/or modify
  9021. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9022. + * published by the Free Software Foundation.
  9023. + *
  9024. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9025. + */
  9026. +
  9027. +#ifndef __NAMEVAL_H__
  9028. +#define __NAMEVAL_H__
  9029. +
  9030. +#include "yportenv.h"
  9031. +
  9032. +int nval_del(char *xb, int xb_size, const YCHAR * name);
  9033. +int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf,
  9034. + int bsize, int flags);
  9035. +int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf,
  9036. + int bsize);
  9037. +int nval_list(const char *xb, int xb_size, char *buf, int bsize);
  9038. +int nval_hasvalues(const char *xb, int xb_size);
  9039. +#endif
  9040. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_nand.c linux-3.14.4/fs/yaffs2/yaffs_nand.c
  9041. --- linux-3.14.4.orig/fs/yaffs2/yaffs_nand.c 1970-01-01 01:00:00.000000000 +0100
  9042. +++ linux-3.14.4/fs/yaffs2/yaffs_nand.c 2014-05-14 12:41:23.984792448 +0200
  9043. @@ -0,0 +1,122 @@
  9044. +/*
  9045. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9046. + *
  9047. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9048. + * for Toby Churchill Ltd and Brightstar Engineering
  9049. + *
  9050. + * Created by Charles Manning <charles@aleph1.co.uk>
  9051. + *
  9052. + * This program is free software; you can redistribute it and/or modify
  9053. + * it under the terms of the GNU General Public License version 2 as
  9054. + * published by the Free Software Foundation.
  9055. + */
  9056. +
  9057. +#include "yaffs_nand.h"
  9058. +#include "yaffs_tagscompat.h"
  9059. +
  9060. +#include "yaffs_getblockinfo.h"
  9061. +#include "yaffs_summary.h"
  9062. +
  9063. +static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
  9064. +{
  9065. + return chunk - dev->chunk_offset;
  9066. +}
  9067. +
  9068. +int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
  9069. + u8 *buffer, struct yaffs_ext_tags *tags)
  9070. +{
  9071. + int result;
  9072. + struct yaffs_ext_tags local_tags;
  9073. + int flash_chunk = apply_chunk_offset(dev, nand_chunk);
  9074. +
  9075. + dev->n_page_reads++;
  9076. +
  9077. + /* If there are no tags provided use local tags. */
  9078. + if (!tags)
  9079. + tags = &local_tags;
  9080. +
  9081. + result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags);
  9082. + if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {
  9083. +
  9084. + struct yaffs_block_info *bi;
  9085. + bi = yaffs_get_block_info(dev,
  9086. + nand_chunk /
  9087. + dev->param.chunks_per_block);
  9088. + yaffs_handle_chunk_error(dev, bi);
  9089. + }
  9090. + return result;
  9091. +}
  9092. +
  9093. +int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
  9094. + int nand_chunk,
  9095. + const u8 *buffer, struct yaffs_ext_tags *tags)
  9096. +{
  9097. + int result;
  9098. + int flash_chunk = apply_chunk_offset(dev, nand_chunk);
  9099. +
  9100. + dev->n_page_writes++;
  9101. +
  9102. + if (!tags) {
  9103. + yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags");
  9104. + BUG();
  9105. + return YAFFS_FAIL;
  9106. + }
  9107. +
  9108. + tags->seq_number = dev->seq_number;
  9109. + tags->chunk_used = 1;
  9110. + yaffs_trace(YAFFS_TRACE_WRITE,
  9111. + "Writing chunk %d tags %d %d",
  9112. + nand_chunk, tags->obj_id, tags->chunk_id);
  9113. +
  9114. + result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk,
  9115. + buffer, tags);
  9116. +
  9117. + yaffs_summary_add(dev, tags, nand_chunk);
  9118. +
  9119. + return result;
  9120. +}
  9121. +
  9122. +int yaffs_mark_bad(struct yaffs_dev *dev, int block_no)
  9123. +{
  9124. + block_no -= dev->block_offset;
  9125. + dev->n_bad_markings++;
  9126. +
  9127. + if (dev->param.disable_bad_block_marking)
  9128. + return YAFFS_OK;
  9129. +
  9130. + return dev->tagger.mark_bad_fn(dev, block_no);
  9131. +}
  9132. +
  9133. +
  9134. +int yaffs_query_init_block_state(struct yaffs_dev *dev,
  9135. + int block_no,
  9136. + enum yaffs_block_state *state,
  9137. + u32 *seq_number)
  9138. +{
  9139. + block_no -= dev->block_offset;
  9140. + return dev->tagger.query_block_fn(dev, block_no, state, seq_number);
  9141. +}
  9142. +
  9143. +int yaffs_erase_block(struct yaffs_dev *dev, int block_no)
  9144. +{
  9145. + int result;
  9146. +
  9147. + block_no -= dev->block_offset;
  9148. + dev->n_erasures++;
  9149. + result = dev->drv.drv_erase_fn(dev, block_no);
  9150. + return result;
  9151. +}
  9152. +
  9153. +int yaffs_init_nand(struct yaffs_dev *dev)
  9154. +{
  9155. + if (dev->drv.drv_initialise_fn)
  9156. + return dev->drv.drv_initialise_fn(dev);
  9157. + return YAFFS_OK;
  9158. +}
  9159. +
  9160. +int yaffs_deinit_nand(struct yaffs_dev *dev)
  9161. +{
  9162. + if (dev->drv.drv_deinitialise_fn)
  9163. + return dev->drv.drv_deinitialise_fn(dev);
  9164. + return YAFFS_OK;
  9165. +}
  9166. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_nand.h linux-3.14.4/fs/yaffs2/yaffs_nand.h
  9167. --- linux-3.14.4.orig/fs/yaffs2/yaffs_nand.h 1970-01-01 01:00:00.000000000 +0100
  9168. +++ linux-3.14.4/fs/yaffs2/yaffs_nand.h 2014-05-14 12:41:23.984792448 +0200
  9169. @@ -0,0 +1,39 @@
  9170. +/*
  9171. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9172. + *
  9173. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9174. + * for Toby Churchill Ltd and Brightstar Engineering
  9175. + *
  9176. + * Created by Charles Manning <charles@aleph1.co.uk>
  9177. + *
  9178. + * This program is free software; you can redistribute it and/or modify
  9179. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9180. + * published by the Free Software Foundation.
  9181. + *
  9182. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9183. + */
  9184. +
  9185. +#ifndef __YAFFS_NAND_H__
  9186. +#define __YAFFS_NAND_H__
  9187. +#include "yaffs_guts.h"
  9188. +
  9189. +int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
  9190. + u8 *buffer, struct yaffs_ext_tags *tags);
  9191. +
  9192. +int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
  9193. + int nand_chunk,
  9194. + const u8 *buffer, struct yaffs_ext_tags *tags);
  9195. +
  9196. +int yaffs_mark_bad(struct yaffs_dev *dev, int block_no);
  9197. +
  9198. +int yaffs_query_init_block_state(struct yaffs_dev *dev,
  9199. + int block_no,
  9200. + enum yaffs_block_state *state,
  9201. + unsigned *seq_number);
  9202. +
  9203. +int yaffs_erase_block(struct yaffs_dev *dev, int flash_block);
  9204. +
  9205. +int yaffs_init_nand(struct yaffs_dev *dev);
  9206. +int yaffs_deinit_nand(struct yaffs_dev *dev);
  9207. +
  9208. +#endif
  9209. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags1.c linux-3.14.4/fs/yaffs2/yaffs_packedtags1.c
  9210. --- linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags1.c 1970-01-01 01:00:00.000000000 +0100
  9211. +++ linux-3.14.4/fs/yaffs2/yaffs_packedtags1.c 2014-05-14 12:41:23.984792448 +0200
  9212. @@ -0,0 +1,56 @@
  9213. +/*
  9214. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9215. + *
  9216. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9217. + * for Toby Churchill Ltd and Brightstar Engineering
  9218. + *
  9219. + * Created by Charles Manning <charles@aleph1.co.uk>
  9220. + *
  9221. + * This program is free software; you can redistribute it and/or modify
  9222. + * it under the terms of the GNU General Public License version 2 as
  9223. + * published by the Free Software Foundation.
  9224. + */
  9225. +
  9226. +#include "yaffs_packedtags1.h"
  9227. +#include "yportenv.h"
  9228. +
  9229. +static const u8 all_ff[20] = {
  9230. + 0xff, 0xff, 0xff, 0xff,
  9231. + 0xff, 0xff, 0xff, 0xff,
  9232. + 0xff, 0xff, 0xff, 0xff,
  9233. + 0xff, 0xff, 0xff, 0xff,
  9234. + 0xff, 0xff, 0xff, 0xff
  9235. +};
  9236. +
  9237. +void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
  9238. + const struct yaffs_ext_tags *t)
  9239. +{
  9240. + pt->chunk_id = t->chunk_id;
  9241. + pt->serial_number = t->serial_number;
  9242. + pt->n_bytes = t->n_bytes;
  9243. + pt->obj_id = t->obj_id;
  9244. + pt->ecc = 0;
  9245. + pt->deleted = (t->is_deleted) ? 0 : 1;
  9246. + pt->unused_stuff = 0;
  9247. + pt->should_be_ff = 0xffffffff;
  9248. +}
  9249. +
  9250. +void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
  9251. + const struct yaffs_packed_tags1 *pt)
  9252. +{
  9253. +
  9254. + if (memcmp(all_ff, pt, sizeof(struct yaffs_packed_tags1))) {
  9255. + t->block_bad = 0;
  9256. + if (pt->should_be_ff != 0xffffffff)
  9257. + t->block_bad = 1;
  9258. + t->chunk_used = 1;
  9259. + t->obj_id = pt->obj_id;
  9260. + t->chunk_id = pt->chunk_id;
  9261. + t->n_bytes = pt->n_bytes;
  9262. + t->ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  9263. + t->is_deleted = (pt->deleted) ? 0 : 1;
  9264. + t->serial_number = pt->serial_number;
  9265. + } else {
  9266. + memset(t, 0, sizeof(struct yaffs_ext_tags));
  9267. + }
  9268. +}
  9269. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags1.h linux-3.14.4/fs/yaffs2/yaffs_packedtags1.h
  9270. --- linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags1.h 1970-01-01 01:00:00.000000000 +0100
  9271. +++ linux-3.14.4/fs/yaffs2/yaffs_packedtags1.h 2014-05-14 12:41:23.984792448 +0200
  9272. @@ -0,0 +1,39 @@
  9273. +/*
  9274. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9275. + *
  9276. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9277. + * for Toby Churchill Ltd and Brightstar Engineering
  9278. + *
  9279. + * Created by Charles Manning <charles@aleph1.co.uk>
  9280. + *
  9281. + * This program is free software; you can redistribute it and/or modify
  9282. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9283. + * published by the Free Software Foundation.
  9284. + *
  9285. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9286. + */
  9287. +
  9288. +/* This is used to pack YAFFS1 tags, not YAFFS2 tags. */
  9289. +
  9290. +#ifndef __YAFFS_PACKEDTAGS1_H__
  9291. +#define __YAFFS_PACKEDTAGS1_H__
  9292. +
  9293. +#include "yaffs_guts.h"
  9294. +
  9295. +struct yaffs_packed_tags1 {
  9296. + u32 chunk_id:20;
  9297. + u32 serial_number:2;
  9298. + u32 n_bytes:10;
  9299. + u32 obj_id:18;
  9300. + u32 ecc:12;
  9301. + u32 deleted:1;
  9302. + u32 unused_stuff:1;
  9303. + unsigned should_be_ff;
  9304. +
  9305. +};
  9306. +
  9307. +void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
  9308. + const struct yaffs_ext_tags *t);
  9309. +void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
  9310. + const struct yaffs_packed_tags1 *pt);
  9311. +#endif
  9312. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags2.c linux-3.14.4/fs/yaffs2/yaffs_packedtags2.c
  9313. --- linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags2.c 1970-01-01 01:00:00.000000000 +0100
  9314. +++ linux-3.14.4/fs/yaffs2/yaffs_packedtags2.c 2014-05-14 12:41:23.984792448 +0200
  9315. @@ -0,0 +1,197 @@
  9316. +/*
  9317. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9318. + *
  9319. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9320. + * for Toby Churchill Ltd and Brightstar Engineering
  9321. + *
  9322. + * Created by Charles Manning <charles@aleph1.co.uk>
  9323. + *
  9324. + * This program is free software; you can redistribute it and/or modify
  9325. + * it under the terms of the GNU General Public License version 2 as
  9326. + * published by the Free Software Foundation.
  9327. + */
  9328. +
  9329. +#include "yaffs_packedtags2.h"
  9330. +#include "yportenv.h"
  9331. +#include "yaffs_trace.h"
  9332. +
  9333. +/* This code packs a set of extended tags into a binary structure for
  9334. + * NAND storage
  9335. + */
  9336. +
  9337. +/* Some of the information is "extra" struff which can be packed in to
  9338. + * speed scanning
  9339. + * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
  9340. + */
  9341. +
  9342. +/* Extra flags applied to chunk_id */
  9343. +
  9344. +#define EXTRA_HEADER_INFO_FLAG 0x80000000
  9345. +#define EXTRA_SHRINK_FLAG 0x40000000
  9346. +#define EXTRA_SHADOWS_FLAG 0x20000000
  9347. +#define EXTRA_SPARE_FLAGS 0x10000000
  9348. +
  9349. +#define ALL_EXTRA_FLAGS 0xf0000000
  9350. +
  9351. +/* Also, the top 4 bits of the object Id are set to the object type. */
  9352. +#define EXTRA_OBJECT_TYPE_SHIFT (28)
  9353. +#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT)
  9354. +
  9355. +static void yaffs_dump_packed_tags2_tags_only(
  9356. + const struct yaffs_packed_tags2_tags_only *ptt)
  9357. +{
  9358. + yaffs_trace(YAFFS_TRACE_MTD,
  9359. + "packed tags obj %d chunk %d byte %d seq %d",
  9360. + ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number);
  9361. +}
  9362. +
  9363. +static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt)
  9364. +{
  9365. + yaffs_dump_packed_tags2_tags_only(&pt->t);
  9366. +}
  9367. +
  9368. +static void yaffs_dump_tags2(const struct yaffs_ext_tags *t)
  9369. +{
  9370. + yaffs_trace(YAFFS_TRACE_MTD,
  9371. + "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d",
  9372. + t->ecc_result, t->block_bad, t->chunk_used, t->obj_id,
  9373. + t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number,
  9374. + t->seq_number);
  9375. +
  9376. +}
  9377. +
  9378. +static int yaffs_check_tags_extra_packable(const struct yaffs_ext_tags *t)
  9379. +{
  9380. + if (t->chunk_id != 0 || !t->extra_available)
  9381. + return 0;
  9382. +
  9383. + /* Check if the file size is too long to store */
  9384. + if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE &&
  9385. + (t->extra_file_size >> 31) != 0)
  9386. + return 0;
  9387. + return 1;
  9388. +}
  9389. +
  9390. +void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *ptt,
  9391. + const struct yaffs_ext_tags *t)
  9392. +{
  9393. + ptt->chunk_id = t->chunk_id;
  9394. + ptt->seq_number = t->seq_number;
  9395. + ptt->n_bytes = t->n_bytes;
  9396. + ptt->obj_id = t->obj_id;
  9397. +
  9398. + /* Only store extra tags for object headers.
  9399. + * If it is a file then only store if the file size is short\
  9400. + * enough to fit.
  9401. + */
  9402. + if (yaffs_check_tags_extra_packable(t)) {
  9403. + /* Store the extra header info instead */
  9404. + /* We save the parent object in the chunk_id */
  9405. + ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id;
  9406. + if (t->extra_is_shrink)
  9407. + ptt->chunk_id |= EXTRA_SHRINK_FLAG;
  9408. + if (t->extra_shadows)
  9409. + ptt->chunk_id |= EXTRA_SHADOWS_FLAG;
  9410. +
  9411. + ptt->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
  9412. + ptt->obj_id |= (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT);
  9413. +
  9414. + if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
  9415. + ptt->n_bytes = t->extra_equiv_id;
  9416. + else if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
  9417. + ptt->n_bytes = (unsigned) t->extra_file_size;
  9418. + else
  9419. + ptt->n_bytes = 0;
  9420. + }
  9421. +
  9422. + yaffs_dump_packed_tags2_tags_only(ptt);
  9423. + yaffs_dump_tags2(t);
  9424. +}
  9425. +
  9426. +void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt,
  9427. + const struct yaffs_ext_tags *t, int tags_ecc)
  9428. +{
  9429. + yaffs_pack_tags2_tags_only(&pt->t, t);
  9430. +
  9431. + if (tags_ecc)
  9432. + yaffs_ecc_calc_other((unsigned char *)&pt->t,
  9433. + sizeof(struct yaffs_packed_tags2_tags_only),
  9434. + &pt->ecc);
  9435. +}
  9436. +
  9437. +void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
  9438. + struct yaffs_packed_tags2_tags_only *ptt)
  9439. +{
  9440. + memset(t, 0, sizeof(struct yaffs_ext_tags));
  9441. +
  9442. + if (ptt->seq_number == 0xffffffff)
  9443. + return;
  9444. +
  9445. + t->block_bad = 0;
  9446. + t->chunk_used = 1;
  9447. + t->obj_id = ptt->obj_id;
  9448. + t->chunk_id = ptt->chunk_id;
  9449. + t->n_bytes = ptt->n_bytes;
  9450. + t->is_deleted = 0;
  9451. + t->serial_number = 0;
  9452. + t->seq_number = ptt->seq_number;
  9453. +
  9454. + /* Do extra header info stuff */
  9455. + if (ptt->chunk_id & EXTRA_HEADER_INFO_FLAG) {
  9456. + t->chunk_id = 0;
  9457. + t->n_bytes = 0;
  9458. +
  9459. + t->extra_available = 1;
  9460. + t->extra_parent_id = ptt->chunk_id & (~(ALL_EXTRA_FLAGS));
  9461. + t->extra_is_shrink = ptt->chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0;
  9462. + t->extra_shadows = ptt->chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0;
  9463. + t->extra_obj_type = ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT;
  9464. + t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
  9465. +
  9466. + if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
  9467. + t->extra_equiv_id = ptt->n_bytes;
  9468. + else
  9469. + t->extra_file_size = ptt->n_bytes;
  9470. + }
  9471. + yaffs_dump_packed_tags2_tags_only(ptt);
  9472. + yaffs_dump_tags2(t);
  9473. +}
  9474. +
  9475. +void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
  9476. + int tags_ecc)
  9477. +{
  9478. + enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  9479. +
  9480. + if (pt->t.seq_number != 0xffffffff && tags_ecc) {
  9481. + /* Chunk is in use and we need to do ECC */
  9482. +
  9483. + struct yaffs_ecc_other ecc;
  9484. + int result;
  9485. + yaffs_ecc_calc_other((unsigned char *)&pt->t,
  9486. + sizeof(struct yaffs_packed_tags2_tags_only),
  9487. + &ecc);
  9488. + result =
  9489. + yaffs_ecc_correct_other((unsigned char *)&pt->t,
  9490. + sizeof(struct yaffs_packed_tags2_tags_only),
  9491. + &pt->ecc, &ecc);
  9492. + switch (result) {
  9493. + case 0:
  9494. + ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  9495. + break;
  9496. + case 1:
  9497. + ecc_result = YAFFS_ECC_RESULT_FIXED;
  9498. + break;
  9499. + case -1:
  9500. + ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  9501. + break;
  9502. + default:
  9503. + ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
  9504. + }
  9505. + }
  9506. + yaffs_unpack_tags2_tags_only(t, &pt->t);
  9507. +
  9508. + t->ecc_result = ecc_result;
  9509. +
  9510. + yaffs_dump_packed_tags2(pt);
  9511. + yaffs_dump_tags2(t);
  9512. +}
  9513. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags2.h linux-3.14.4/fs/yaffs2/yaffs_packedtags2.h
  9514. --- linux-3.14.4.orig/fs/yaffs2/yaffs_packedtags2.h 1970-01-01 01:00:00.000000000 +0100
  9515. +++ linux-3.14.4/fs/yaffs2/yaffs_packedtags2.h 2014-05-14 12:41:23.984792448 +0200
  9516. @@ -0,0 +1,47 @@
  9517. +/*
  9518. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9519. + *
  9520. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9521. + * for Toby Churchill Ltd and Brightstar Engineering
  9522. + *
  9523. + * Created by Charles Manning <charles@aleph1.co.uk>
  9524. + *
  9525. + * This program is free software; you can redistribute it and/or modify
  9526. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9527. + * published by the Free Software Foundation.
  9528. + *
  9529. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9530. + */
  9531. +
  9532. +/* This is used to pack YAFFS2 tags, not YAFFS1tags. */
  9533. +
  9534. +#ifndef __YAFFS_PACKEDTAGS2_H__
  9535. +#define __YAFFS_PACKEDTAGS2_H__
  9536. +
  9537. +#include "yaffs_guts.h"
  9538. +#include "yaffs_ecc.h"
  9539. +
  9540. +struct yaffs_packed_tags2_tags_only {
  9541. + unsigned seq_number;
  9542. + unsigned obj_id;
  9543. + unsigned chunk_id;
  9544. + unsigned n_bytes;
  9545. +};
  9546. +
  9547. +struct yaffs_packed_tags2 {
  9548. + struct yaffs_packed_tags2_tags_only t;
  9549. + struct yaffs_ecc_other ecc;
  9550. +};
  9551. +
  9552. +/* Full packed tags with ECC, used for oob tags */
  9553. +void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt,
  9554. + const struct yaffs_ext_tags *t, int tags_ecc);
  9555. +void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
  9556. + int tags_ecc);
  9557. +
  9558. +/* Only the tags part (no ECC for use with inband tags */
  9559. +void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *pt,
  9560. + const struct yaffs_ext_tags *t);
  9561. +void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
  9562. + struct yaffs_packed_tags2_tags_only *pt);
  9563. +#endif
  9564. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_summary.c linux-3.14.4/fs/yaffs2/yaffs_summary.c
  9565. --- linux-3.14.4.orig/fs/yaffs2/yaffs_summary.c 1970-01-01 01:00:00.000000000 +0100
  9566. +++ linux-3.14.4/fs/yaffs2/yaffs_summary.c 2014-05-14 12:41:23.984792448 +0200
  9567. @@ -0,0 +1,312 @@
  9568. +/*
  9569. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9570. + *
  9571. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9572. + * for Toby Churchill Ltd and Brightstar Engineering
  9573. + *
  9574. + * Created by Charles Manning <charles@aleph1.co.uk>
  9575. + *
  9576. + * This program is free software; you can redistribute it and/or modify
  9577. + * it under the terms of the GNU General Public License version 2 as
  9578. + * published by the Free Software Foundation.
  9579. + */
  9580. +
  9581. +/* Summaries write the useful part of the tags for the chunks in a block into an
  9582. + * an array which is written to the last n chunks of the block.
  9583. + * Reading the summaries gives all the tags for the block in one read. Much
  9584. + * faster.
  9585. + *
  9586. + * Chunks holding summaries are marked with tags making it look like
  9587. + * they are part of a fake file.
  9588. + *
  9589. + * The summary could also be used during gc.
  9590. + *
  9591. + */
  9592. +
  9593. +#include "yaffs_summary.h"
  9594. +#include "yaffs_packedtags2.h"
  9595. +#include "yaffs_nand.h"
  9596. +#include "yaffs_getblockinfo.h"
  9597. +#include "yaffs_bitmap.h"
  9598. +
  9599. +/*
  9600. + * The summary is built up in an array of summary tags.
  9601. + * This gets written to the last one or two (maybe more) chunks in a block.
  9602. + * A summary header is written as the first part of each chunk of summary data.
  9603. + * The summary header must match or the summary is rejected.
  9604. + */
  9605. +
  9606. +/* Summary tags don't need the sequence number because that is redundant. */
  9607. +struct yaffs_summary_tags {
  9608. + unsigned obj_id;
  9609. + unsigned chunk_id;
  9610. + unsigned n_bytes;
  9611. +};
  9612. +
  9613. +/* Summary header */
  9614. +struct yaffs_summary_header {
  9615. + unsigned version; /* Must match current version */
  9616. + unsigned block; /* Must be this block */
  9617. + unsigned seq; /* Must be this sequence number */
  9618. + unsigned sum; /* Just add up all the bytes in the tags */
  9619. +};
  9620. +
  9621. +
  9622. +static void yaffs_summary_clear(struct yaffs_dev *dev)
  9623. +{
  9624. + if (!dev->sum_tags)
  9625. + return;
  9626. + memset(dev->sum_tags, 0, dev->chunks_per_summary *
  9627. + sizeof(struct yaffs_summary_tags));
  9628. +}
  9629. +
  9630. +
  9631. +void yaffs_summary_deinit(struct yaffs_dev *dev)
  9632. +{
  9633. + kfree(dev->sum_tags);
  9634. + dev->sum_tags = NULL;
  9635. + kfree(dev->gc_sum_tags);
  9636. + dev->gc_sum_tags = NULL;
  9637. + dev->chunks_per_summary = 0;
  9638. +}
  9639. +
  9640. +int yaffs_summary_init(struct yaffs_dev *dev)
  9641. +{
  9642. + int sum_bytes;
  9643. + int chunks_used; /* Number of chunks used by summary */
  9644. + int sum_tags_bytes;
  9645. +
  9646. + sum_bytes = dev->param.chunks_per_block *
  9647. + sizeof(struct yaffs_summary_tags);
  9648. +
  9649. + chunks_used = (sum_bytes + dev->data_bytes_per_chunk - 1)/
  9650. + (dev->data_bytes_per_chunk -
  9651. + sizeof(struct yaffs_summary_header));
  9652. +
  9653. + dev->chunks_per_summary = dev->param.chunks_per_block - chunks_used;
  9654. + sum_tags_bytes = sizeof(struct yaffs_summary_tags) *
  9655. + dev->chunks_per_summary;
  9656. + dev->sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS);
  9657. + dev->gc_sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS);
  9658. + if (!dev->sum_tags || !dev->gc_sum_tags) {
  9659. + yaffs_summary_deinit(dev);
  9660. + return YAFFS_FAIL;
  9661. + }
  9662. +
  9663. + yaffs_summary_clear(dev);
  9664. +
  9665. + return YAFFS_OK;
  9666. +}
  9667. +
  9668. +static unsigned yaffs_summary_sum(struct yaffs_dev *dev)
  9669. +{
  9670. + u8 *sum_buffer = (u8 *)dev->sum_tags;
  9671. + int i;
  9672. + unsigned sum = 0;
  9673. +
  9674. + i = sizeof(struct yaffs_summary_tags) *
  9675. + dev->chunks_per_summary;
  9676. + while (i > 0) {
  9677. + sum += *sum_buffer;
  9678. + sum_buffer++;
  9679. + i--;
  9680. + }
  9681. +
  9682. + return sum;
  9683. +}
  9684. +
  9685. +static int yaffs_summary_write(struct yaffs_dev *dev, int blk)
  9686. +{
  9687. + struct yaffs_ext_tags tags;
  9688. + u8 *buffer;
  9689. + u8 *sum_buffer = (u8 *)dev->sum_tags;
  9690. + int n_bytes;
  9691. + int chunk_in_nand;
  9692. + int chunk_in_block;
  9693. + int result;
  9694. + int this_tx;
  9695. + struct yaffs_summary_header hdr;
  9696. + int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr);
  9697. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
  9698. +
  9699. + buffer = yaffs_get_temp_buffer(dev);
  9700. + n_bytes = sizeof(struct yaffs_summary_tags) *
  9701. + dev->chunks_per_summary;
  9702. + memset(&tags, 0, sizeof(struct yaffs_ext_tags));
  9703. + tags.obj_id = YAFFS_OBJECTID_SUMMARY;
  9704. + tags.chunk_id = 1;
  9705. + chunk_in_block = dev->chunks_per_summary;
  9706. + chunk_in_nand = dev->alloc_block * dev->param.chunks_per_block +
  9707. + dev->chunks_per_summary;
  9708. + hdr.version = YAFFS_SUMMARY_VERSION;
  9709. + hdr.block = blk;
  9710. + hdr.seq = bi->seq_number;
  9711. + hdr.sum = yaffs_summary_sum(dev);
  9712. +
  9713. + do {
  9714. + this_tx = n_bytes;
  9715. + if (this_tx > sum_bytes_per_chunk)
  9716. + this_tx = sum_bytes_per_chunk;
  9717. + memcpy(buffer, &hdr, sizeof(hdr));
  9718. + memcpy(buffer + sizeof(hdr), sum_buffer, this_tx);
  9719. + tags.n_bytes = this_tx + sizeof(hdr);
  9720. + result = yaffs_wr_chunk_tags_nand(dev, chunk_in_nand,
  9721. + buffer, &tags);
  9722. +
  9723. + if (result != YAFFS_OK)
  9724. + break;
  9725. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  9726. + bi->pages_in_use++;
  9727. + dev->n_free_chunks--;
  9728. +
  9729. + n_bytes -= this_tx;
  9730. + sum_buffer += this_tx;
  9731. + chunk_in_nand++;
  9732. + chunk_in_block++;
  9733. + tags.chunk_id++;
  9734. + } while (result == YAFFS_OK && n_bytes > 0);
  9735. + yaffs_release_temp_buffer(dev, buffer);
  9736. +
  9737. +
  9738. + if (result == YAFFS_OK)
  9739. + bi->has_summary = 1;
  9740. +
  9741. +
  9742. + return result;
  9743. +}
  9744. +
  9745. +int yaffs_summary_read(struct yaffs_dev *dev,
  9746. + struct yaffs_summary_tags *st,
  9747. + int blk)
  9748. +{
  9749. + struct yaffs_ext_tags tags;
  9750. + u8 *buffer;
  9751. + u8 *sum_buffer = (u8 *)st;
  9752. + int n_bytes;
  9753. + int chunk_id;
  9754. + int chunk_in_nand;
  9755. + int chunk_in_block;
  9756. + int result;
  9757. + int this_tx;
  9758. + struct yaffs_summary_header hdr;
  9759. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
  9760. + int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr);
  9761. + int sum_tags_bytes;
  9762. +
  9763. + sum_tags_bytes = sizeof(struct yaffs_summary_tags) *
  9764. + dev->chunks_per_summary;
  9765. + buffer = yaffs_get_temp_buffer(dev);
  9766. + n_bytes = sizeof(struct yaffs_summary_tags) * dev->chunks_per_summary;
  9767. + chunk_in_block = dev->chunks_per_summary;
  9768. + chunk_in_nand = blk * dev->param.chunks_per_block +
  9769. + dev->chunks_per_summary;
  9770. + chunk_id = 1;
  9771. + do {
  9772. + this_tx = n_bytes;
  9773. + if (this_tx > sum_bytes_per_chunk)
  9774. + this_tx = sum_bytes_per_chunk;
  9775. + result = yaffs_rd_chunk_tags_nand(dev, chunk_in_nand,
  9776. + buffer, &tags);
  9777. +
  9778. + if (tags.chunk_id != chunk_id ||
  9779. + tags.obj_id != YAFFS_OBJECTID_SUMMARY ||
  9780. + tags.chunk_used == 0 ||
  9781. + tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
  9782. + tags.n_bytes != (this_tx + sizeof(hdr)))
  9783. + result = YAFFS_FAIL;
  9784. + if (result != YAFFS_OK)
  9785. + break;
  9786. +
  9787. + if (st == dev->sum_tags) {
  9788. + /* If we're scanning then update the block info */
  9789. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  9790. + bi->pages_in_use++;
  9791. + }
  9792. + memcpy(&hdr, buffer, sizeof(hdr));
  9793. + memcpy(sum_buffer, buffer + sizeof(hdr), this_tx);
  9794. + n_bytes -= this_tx;
  9795. + sum_buffer += this_tx;
  9796. + chunk_in_nand++;
  9797. + chunk_in_block++;
  9798. + chunk_id++;
  9799. + } while (result == YAFFS_OK && n_bytes > 0);
  9800. + yaffs_release_temp_buffer(dev, buffer);
  9801. +
  9802. + if (result == YAFFS_OK) {
  9803. + /* Verify header */
  9804. + if (hdr.version != YAFFS_SUMMARY_VERSION ||
  9805. + hdr.seq != bi->seq_number ||
  9806. + hdr.sum != yaffs_summary_sum(dev))
  9807. + result = YAFFS_FAIL;
  9808. + }
  9809. +
  9810. + if (st == dev->sum_tags && result == YAFFS_OK)
  9811. + bi->has_summary = 1;
  9812. +
  9813. + return result;
  9814. +}
  9815. +
  9816. +int yaffs_summary_add(struct yaffs_dev *dev,
  9817. + struct yaffs_ext_tags *tags,
  9818. + int chunk_in_nand)
  9819. +{
  9820. + struct yaffs_packed_tags2_tags_only tags_only;
  9821. + struct yaffs_summary_tags *sum_tags;
  9822. + int block_in_nand = chunk_in_nand / dev->param.chunks_per_block;
  9823. + int chunk_in_block = chunk_in_nand % dev->param.chunks_per_block;
  9824. +
  9825. + if (!dev->sum_tags)
  9826. + return YAFFS_OK;
  9827. +
  9828. + if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) {
  9829. + yaffs_pack_tags2_tags_only(&tags_only, tags);
  9830. + sum_tags = &dev->sum_tags[chunk_in_block];
  9831. + sum_tags->chunk_id = tags_only.chunk_id;
  9832. + sum_tags->n_bytes = tags_only.n_bytes;
  9833. + sum_tags->obj_id = tags_only.obj_id;
  9834. +
  9835. + if (chunk_in_block == dev->chunks_per_summary - 1) {
  9836. + /* Time to write out the summary */
  9837. + yaffs_summary_write(dev, block_in_nand);
  9838. + yaffs_summary_clear(dev);
  9839. + yaffs_skip_rest_of_block(dev);
  9840. + }
  9841. + }
  9842. + return YAFFS_OK;
  9843. +}
  9844. +
  9845. +int yaffs_summary_fetch(struct yaffs_dev *dev,
  9846. + struct yaffs_ext_tags *tags,
  9847. + int chunk_in_block)
  9848. +{
  9849. + struct yaffs_packed_tags2_tags_only tags_only;
  9850. + struct yaffs_summary_tags *sum_tags;
  9851. + if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) {
  9852. + sum_tags = &dev->sum_tags[chunk_in_block];
  9853. + tags_only.chunk_id = sum_tags->chunk_id;
  9854. + tags_only.n_bytes = sum_tags->n_bytes;
  9855. + tags_only.obj_id = sum_tags->obj_id;
  9856. + yaffs_unpack_tags2_tags_only(tags, &tags_only);
  9857. + return YAFFS_OK;
  9858. + }
  9859. + return YAFFS_FAIL;
  9860. +}
  9861. +
  9862. +void yaffs_summary_gc(struct yaffs_dev *dev, int blk)
  9863. +{
  9864. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
  9865. + int i;
  9866. +
  9867. + if (!bi->has_summary)
  9868. + return;
  9869. +
  9870. + for (i = dev->chunks_per_summary;
  9871. + i < dev->param.chunks_per_block;
  9872. + i++) {
  9873. + if (yaffs_check_chunk_bit(dev, blk, i)) {
  9874. + yaffs_clear_chunk_bit(dev, blk, i);
  9875. + bi->pages_in_use--;
  9876. + dev->n_free_chunks++;
  9877. + }
  9878. + }
  9879. +}
  9880. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_summary.h linux-3.14.4/fs/yaffs2/yaffs_summary.h
  9881. --- linux-3.14.4.orig/fs/yaffs2/yaffs_summary.h 1970-01-01 01:00:00.000000000 +0100
  9882. +++ linux-3.14.4/fs/yaffs2/yaffs_summary.h 2014-05-14 12:41:23.984792448 +0200
  9883. @@ -0,0 +1,37 @@
  9884. +/*
  9885. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  9886. + *
  9887. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9888. + * for Toby Churchill Ltd and Brightstar Engineering
  9889. + *
  9890. + * Created by Charles Manning <charles@aleph1.co.uk>
  9891. + *
  9892. + * This program is free software; you can redistribute it and/or modify
  9893. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  9894. + * published by the Free Software Foundation.
  9895. + *
  9896. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  9897. + */
  9898. +
  9899. +#ifndef __YAFFS_SUMMARY_H__
  9900. +#define __YAFFS_SUMMARY_H__
  9901. +
  9902. +#include "yaffs_packedtags2.h"
  9903. +
  9904. +
  9905. +int yaffs_summary_init(struct yaffs_dev *dev);
  9906. +void yaffs_summary_deinit(struct yaffs_dev *dev);
  9907. +
  9908. +int yaffs_summary_add(struct yaffs_dev *dev,
  9909. + struct yaffs_ext_tags *tags,
  9910. + int chunk_in_block);
  9911. +int yaffs_summary_fetch(struct yaffs_dev *dev,
  9912. + struct yaffs_ext_tags *tags,
  9913. + int chunk_in_block);
  9914. +int yaffs_summary_read(struct yaffs_dev *dev,
  9915. + struct yaffs_summary_tags *st,
  9916. + int blk);
  9917. +void yaffs_summary_gc(struct yaffs_dev *dev, int blk);
  9918. +
  9919. +
  9920. +#endif
  9921. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_tagscompat.c linux-3.14.4/fs/yaffs2/yaffs_tagscompat.c
  9922. --- linux-3.14.4.orig/fs/yaffs2/yaffs_tagscompat.c 1970-01-01 01:00:00.000000000 +0100
  9923. +++ linux-3.14.4/fs/yaffs2/yaffs_tagscompat.c 2014-05-14 12:41:23.988792461 +0200
  9924. @@ -0,0 +1,381 @@
  9925. +/*
  9926. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  9927. + *
  9928. + * Copyright (C) 2002-2011 Aleph One Ltd.
  9929. + * for Toby Churchill Ltd and Brightstar Engineering
  9930. + *
  9931. + * Created by Charles Manning <charles@aleph1.co.uk>
  9932. + *
  9933. + * This program is free software; you can redistribute it and/or modify
  9934. + * it under the terms of the GNU General Public License version 2 as
  9935. + * published by the Free Software Foundation.
  9936. + */
  9937. +
  9938. +#include "yaffs_guts.h"
  9939. +#include "yaffs_tagscompat.h"
  9940. +#include "yaffs_ecc.h"
  9941. +#include "yaffs_getblockinfo.h"
  9942. +#include "yaffs_trace.h"
  9943. +
  9944. +static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
  9945. +
  9946. +
  9947. +/********** Tags ECC calculations *********/
  9948. +
  9949. +
  9950. +void yaffs_calc_tags_ecc(struct yaffs_tags *tags)
  9951. +{
  9952. + /* Calculate an ecc */
  9953. + unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes;
  9954. + unsigned i, j;
  9955. + unsigned ecc = 0;
  9956. + unsigned bit = 0;
  9957. +
  9958. + tags->ecc = 0;
  9959. +
  9960. + for (i = 0; i < 8; i++) {
  9961. + for (j = 1; j & 0xff; j <<= 1) {
  9962. + bit++;
  9963. + if (b[i] & j)
  9964. + ecc ^= bit;
  9965. + }
  9966. + }
  9967. + tags->ecc = ecc;
  9968. +}
  9969. +
  9970. +int yaffs_check_tags_ecc(struct yaffs_tags *tags)
  9971. +{
  9972. + unsigned ecc = tags->ecc;
  9973. +
  9974. + yaffs_calc_tags_ecc(tags);
  9975. +
  9976. + ecc ^= tags->ecc;
  9977. +
  9978. + if (ecc && ecc <= 64) {
  9979. + /* TODO: Handle the failure better. Retire? */
  9980. + unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes;
  9981. +
  9982. + ecc--;
  9983. +
  9984. + b[ecc / 8] ^= (1 << (ecc & 7));
  9985. +
  9986. + /* Now recvalc the ecc */
  9987. + yaffs_calc_tags_ecc(tags);
  9988. +
  9989. + return 1; /* recovered error */
  9990. + } else if (ecc) {
  9991. + /* Wierd ecc failure value */
  9992. + /* TODO Need to do somethiong here */
  9993. + return -1; /* unrecovered error */
  9994. + }
  9995. + return 0;
  9996. +}
  9997. +
  9998. +/********** Tags **********/
  9999. +
  10000. +static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
  10001. + struct yaffs_tags *tags_ptr)
  10002. +{
  10003. + union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
  10004. +
  10005. + yaffs_calc_tags_ecc(tags_ptr);
  10006. +
  10007. + spare_ptr->tb0 = tu->as_bytes[0];
  10008. + spare_ptr->tb1 = tu->as_bytes[1];
  10009. + spare_ptr->tb2 = tu->as_bytes[2];
  10010. + spare_ptr->tb3 = tu->as_bytes[3];
  10011. + spare_ptr->tb4 = tu->as_bytes[4];
  10012. + spare_ptr->tb5 = tu->as_bytes[5];
  10013. + spare_ptr->tb6 = tu->as_bytes[6];
  10014. + spare_ptr->tb7 = tu->as_bytes[7];
  10015. +}
  10016. +
  10017. +static void yaffs_get_tags_from_spare(struct yaffs_dev *dev,
  10018. + struct yaffs_spare *spare_ptr,
  10019. + struct yaffs_tags *tags_ptr)
  10020. +{
  10021. + union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
  10022. + int result;
  10023. +
  10024. + tu->as_bytes[0] = spare_ptr->tb0;
  10025. + tu->as_bytes[1] = spare_ptr->tb1;
  10026. + tu->as_bytes[2] = spare_ptr->tb2;
  10027. + tu->as_bytes[3] = spare_ptr->tb3;
  10028. + tu->as_bytes[4] = spare_ptr->tb4;
  10029. + tu->as_bytes[5] = spare_ptr->tb5;
  10030. + tu->as_bytes[6] = spare_ptr->tb6;
  10031. + tu->as_bytes[7] = spare_ptr->tb7;
  10032. +
  10033. + result = yaffs_check_tags_ecc(tags_ptr);
  10034. + if (result > 0)
  10035. + dev->n_tags_ecc_fixed++;
  10036. + else if (result < 0)
  10037. + dev->n_tags_ecc_unfixed++;
  10038. +}
  10039. +
  10040. +static void yaffs_spare_init(struct yaffs_spare *spare)
  10041. +{
  10042. + memset(spare, 0xff, sizeof(struct yaffs_spare));
  10043. +}
  10044. +
  10045. +static int yaffs_wr_nand(struct yaffs_dev *dev,
  10046. + int nand_chunk, const u8 *data,
  10047. + struct yaffs_spare *spare)
  10048. +{
  10049. + int data_size = dev->data_bytes_per_chunk;
  10050. +
  10051. + return dev->drv.drv_write_chunk_fn(dev, nand_chunk,
  10052. + data, data_size,
  10053. + (u8 *) spare, sizeof(*spare));
  10054. +}
  10055. +
  10056. +static int yaffs_rd_chunk_nand(struct yaffs_dev *dev,
  10057. + int nand_chunk,
  10058. + u8 *data,
  10059. + struct yaffs_spare *spare,
  10060. + enum yaffs_ecc_result *ecc_result,
  10061. + int correct_errors)
  10062. +{
  10063. + int ret_val;
  10064. + struct yaffs_spare local_spare;
  10065. + int data_size;
  10066. + int spare_size;
  10067. + int ecc_result1, ecc_result2;
  10068. + u8 calc_ecc[3];
  10069. +
  10070. + if (!spare) {
  10071. + /* If we don't have a real spare, then we use a local one. */
  10072. + /* Need this for the calculation of the ecc */
  10073. + spare = &local_spare;
  10074. + }
  10075. + data_size = dev->data_bytes_per_chunk;
  10076. + spare_size = sizeof(struct yaffs_spare);
  10077. +
  10078. + if (dev->param.use_nand_ecc)
  10079. + return dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  10080. + data, data_size,
  10081. + (u8 *) spare, spare_size,
  10082. + ecc_result);
  10083. +
  10084. +
  10085. + /* Handle the ECC at this level. */
  10086. +
  10087. + ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  10088. + data, data_size,
  10089. + (u8 *)spare, spare_size,
  10090. + NULL);
  10091. + if (!data || !correct_errors)
  10092. + return ret_val;
  10093. +
  10094. + /* Do ECC correction if needed. */
  10095. + yaffs_ecc_calc(data, calc_ecc);
  10096. + ecc_result1 = yaffs_ecc_correct(data, spare->ecc1, calc_ecc);
  10097. + yaffs_ecc_calc(&data[256], calc_ecc);
  10098. + ecc_result2 = yaffs_ecc_correct(&data[256], spare->ecc2, calc_ecc);
  10099. +
  10100. + if (ecc_result1 > 0) {
  10101. + yaffs_trace(YAFFS_TRACE_ERROR,
  10102. + "**>>yaffs ecc error fix performed on chunk %d:0",
  10103. + nand_chunk);
  10104. + dev->n_ecc_fixed++;
  10105. + } else if (ecc_result1 < 0) {
  10106. + yaffs_trace(YAFFS_TRACE_ERROR,
  10107. + "**>>yaffs ecc error unfixed on chunk %d:0",
  10108. + nand_chunk);
  10109. + dev->n_ecc_unfixed++;
  10110. + }
  10111. +
  10112. + if (ecc_result2 > 0) {
  10113. + yaffs_trace(YAFFS_TRACE_ERROR,
  10114. + "**>>yaffs ecc error fix performed on chunk %d:1",
  10115. + nand_chunk);
  10116. + dev->n_ecc_fixed++;
  10117. + } else if (ecc_result2 < 0) {
  10118. + yaffs_trace(YAFFS_TRACE_ERROR,
  10119. + "**>>yaffs ecc error unfixed on chunk %d:1",
  10120. + nand_chunk);
  10121. + dev->n_ecc_unfixed++;
  10122. + }
  10123. +
  10124. + if (ecc_result1 || ecc_result2) {
  10125. + /* We had a data problem on this page */
  10126. + yaffs_handle_rd_data_error(dev, nand_chunk);
  10127. + }
  10128. +
  10129. + if (ecc_result1 < 0 || ecc_result2 < 0)
  10130. + *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  10131. + else if (ecc_result1 > 0 || ecc_result2 > 0)
  10132. + *ecc_result = YAFFS_ECC_RESULT_FIXED;
  10133. + else
  10134. + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
  10135. +
  10136. + return ret_val;
  10137. +}
  10138. +
  10139. +/*
  10140. + * Functions for robustisizing
  10141. + */
  10142. +
  10143. +static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk)
  10144. +{
  10145. + int flash_block = nand_chunk / dev->param.chunks_per_block;
  10146. +
  10147. + /* Mark the block for retirement */
  10148. + yaffs_get_block_info(dev, flash_block + dev->block_offset)->
  10149. + needs_retiring = 1;
  10150. + yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
  10151. + "**>>Block %d marked for retirement",
  10152. + flash_block);
  10153. +
  10154. + /* TODO:
  10155. + * Just do a garbage collection on the affected block
  10156. + * then retire the block
  10157. + * NB recursion
  10158. + */
  10159. +}
  10160. +
  10161. +static int yaffs_tags_compat_wr(struct yaffs_dev *dev,
  10162. + int nand_chunk,
  10163. + const u8 *data, const struct yaffs_ext_tags *ext_tags)
  10164. +{
  10165. + struct yaffs_spare spare;
  10166. + struct yaffs_tags tags;
  10167. +
  10168. + yaffs_spare_init(&spare);
  10169. +
  10170. + if (ext_tags->is_deleted)
  10171. + spare.page_status = 0;
  10172. + else {
  10173. + tags.obj_id = ext_tags->obj_id;
  10174. + tags.chunk_id = ext_tags->chunk_id;
  10175. +
  10176. + tags.n_bytes_lsb = ext_tags->n_bytes & (1024 - 1);
  10177. +
  10178. + if (dev->data_bytes_per_chunk >= 1024)
  10179. + tags.n_bytes_msb = (ext_tags->n_bytes >> 10) & 3;
  10180. + else
  10181. + tags.n_bytes_msb = 3;
  10182. +
  10183. + tags.serial_number = ext_tags->serial_number;
  10184. +
  10185. + if (!dev->param.use_nand_ecc && data) {
  10186. + yaffs_ecc_calc(data, spare.ecc1);
  10187. + yaffs_ecc_calc(&data[256], spare.ecc2);
  10188. + }
  10189. +
  10190. + yaffs_load_tags_to_spare(&spare, &tags);
  10191. + }
  10192. + return yaffs_wr_nand(dev, nand_chunk, data, &spare);
  10193. +}
  10194. +
  10195. +static int yaffs_tags_compat_rd(struct yaffs_dev *dev,
  10196. + int nand_chunk,
  10197. + u8 *data, struct yaffs_ext_tags *ext_tags)
  10198. +{
  10199. + struct yaffs_spare spare;
  10200. + struct yaffs_tags tags;
  10201. + enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
  10202. + static struct yaffs_spare spare_ff;
  10203. + static int init;
  10204. + int deleted;
  10205. +
  10206. + if (!init) {
  10207. + memset(&spare_ff, 0xff, sizeof(spare_ff));
  10208. + init = 1;
  10209. + }
  10210. +
  10211. + if (!yaffs_rd_chunk_nand(dev, nand_chunk,
  10212. + data, &spare, &ecc_result, 1))
  10213. + return YAFFS_FAIL;
  10214. +
  10215. + /* ext_tags may be NULL */
  10216. + if (!ext_tags)
  10217. + return YAFFS_OK;
  10218. +
  10219. + deleted = (hweight8(spare.page_status) < 7) ? 1 : 0;
  10220. +
  10221. + ext_tags->is_deleted = deleted;
  10222. + ext_tags->ecc_result = ecc_result;
  10223. + ext_tags->block_bad = 0; /* We're reading it */
  10224. + /* therefore it is not a bad block */
  10225. + ext_tags->chunk_used =
  10226. + memcmp(&spare_ff, &spare, sizeof(spare_ff)) ? 1 : 0;
  10227. +
  10228. + if (ext_tags->chunk_used) {
  10229. + yaffs_get_tags_from_spare(dev, &spare, &tags);
  10230. + ext_tags->obj_id = tags.obj_id;
  10231. + ext_tags->chunk_id = tags.chunk_id;
  10232. + ext_tags->n_bytes = tags.n_bytes_lsb;
  10233. +
  10234. + if (dev->data_bytes_per_chunk >= 1024)
  10235. + ext_tags->n_bytes |=
  10236. + (((unsigned)tags.n_bytes_msb) << 10);
  10237. +
  10238. + ext_tags->serial_number = tags.serial_number;
  10239. + }
  10240. +
  10241. + return YAFFS_OK;
  10242. +}
  10243. +
  10244. +static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block)
  10245. +{
  10246. + struct yaffs_spare spare;
  10247. +
  10248. + memset(&spare, 0xff, sizeof(struct yaffs_spare));
  10249. +
  10250. + spare.block_status = 'Y';
  10251. +
  10252. + yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block, NULL,
  10253. + &spare);
  10254. + yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block + 1,
  10255. + NULL, &spare);
  10256. +
  10257. + return YAFFS_OK;
  10258. +}
  10259. +
  10260. +static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
  10261. + int block_no,
  10262. + enum yaffs_block_state *state,
  10263. + u32 *seq_number)
  10264. +{
  10265. + struct yaffs_spare spare0, spare1;
  10266. + static struct yaffs_spare spare_ff;
  10267. + static int init;
  10268. + enum yaffs_ecc_result dummy;
  10269. +
  10270. + if (!init) {
  10271. + memset(&spare_ff, 0xff, sizeof(spare_ff));
  10272. + init = 1;
  10273. + }
  10274. +
  10275. + *seq_number = 0;
  10276. +
  10277. + /* Look for bad block markers in the first two chunks */
  10278. + yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block,
  10279. + NULL, &spare0, &dummy, 0);
  10280. + yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1,
  10281. + NULL, &spare1, &dummy, 0);
  10282. +
  10283. + if (hweight8(spare0.block_status & spare1.block_status) < 7)
  10284. + *state = YAFFS_BLOCK_STATE_DEAD;
  10285. + else if (memcmp(&spare_ff, &spare0, sizeof(spare_ff)) == 0)
  10286. + *state = YAFFS_BLOCK_STATE_EMPTY;
  10287. + else
  10288. + *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
  10289. +
  10290. + return YAFFS_OK;
  10291. +}
  10292. +
  10293. +void yaffs_tags_compat_install(struct yaffs_dev *dev)
  10294. +{
  10295. + if(dev->param.is_yaffs2)
  10296. + return;
  10297. + if(!dev->tagger.write_chunk_tags_fn)
  10298. + dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr;
  10299. + if(!dev->tagger.read_chunk_tags_fn)
  10300. + dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd;
  10301. + if(!dev->tagger.query_block_fn)
  10302. + dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
  10303. + if(!dev->tagger.mark_bad_fn)
  10304. + dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
  10305. +}
  10306. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_tagscompat.h linux-3.14.4/fs/yaffs2/yaffs_tagscompat.h
  10307. --- linux-3.14.4.orig/fs/yaffs2/yaffs_tagscompat.h 1970-01-01 01:00:00.000000000 +0100
  10308. +++ linux-3.14.4/fs/yaffs2/yaffs_tagscompat.h 2014-05-14 12:41:23.988792461 +0200
  10309. @@ -0,0 +1,44 @@
  10310. +/*
  10311. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  10312. + *
  10313. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10314. + * for Toby Churchill Ltd and Brightstar Engineering
  10315. + *
  10316. + * Created by Charles Manning <charles@aleph1.co.uk>
  10317. + *
  10318. + * This program is free software; you can redistribute it and/or modify
  10319. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  10320. + * published by the Free Software Foundation.
  10321. + *
  10322. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  10323. + */
  10324. +
  10325. +#ifndef __YAFFS_TAGSCOMPAT_H__
  10326. +#define __YAFFS_TAGSCOMPAT_H__
  10327. +
  10328. +
  10329. +#include "yaffs_guts.h"
  10330. +
  10331. +#if 0
  10332. +
  10333. +
  10334. +int yaffs_tags_compat_wr(struct yaffs_dev *dev,
  10335. + int nand_chunk,
  10336. + const u8 *data, const struct yaffs_ext_tags *tags);
  10337. +int yaffs_tags_compat_rd(struct yaffs_dev *dev,
  10338. + int nand_chunk,
  10339. + u8 *data, struct yaffs_ext_tags *tags);
  10340. +int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no);
  10341. +int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
  10342. + int block_no,
  10343. + enum yaffs_block_state *state,
  10344. + u32 *seq_number);
  10345. +
  10346. +#endif
  10347. +
  10348. +
  10349. +void yaffs_tags_compat_install(struct yaffs_dev *dev);
  10350. +void yaffs_calc_tags_ecc(struct yaffs_tags *tags);
  10351. +int yaffs_check_tags_ecc(struct yaffs_tags *tags);
  10352. +
  10353. +#endif
  10354. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_tagsmarshall.c linux-3.14.4/fs/yaffs2/yaffs_tagsmarshall.c
  10355. --- linux-3.14.4.orig/fs/yaffs2/yaffs_tagsmarshall.c 1970-01-01 01:00:00.000000000 +0100
  10356. +++ linux-3.14.4/fs/yaffs2/yaffs_tagsmarshall.c 2014-05-14 12:41:23.988792461 +0200
  10357. @@ -0,0 +1,199 @@
  10358. +/*
  10359. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  10360. + *
  10361. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10362. + * for Toby Churchill Ltd and Brightstar Engineering
  10363. + *
  10364. + * Created by Charles Manning <charles@aleph1.co.uk>
  10365. + *
  10366. + * This program is free software; you can redistribute it and/or modify
  10367. + * it under the terms of the GNU General Public License version 2 as
  10368. + * published by the Free Software Foundation.
  10369. + */
  10370. +
  10371. +#include "yaffs_guts.h"
  10372. +#include "yaffs_trace.h"
  10373. +#include "yaffs_packedtags2.h"
  10374. +
  10375. +static int yaffs_tags_marshall_write(struct yaffs_dev *dev,
  10376. + int nand_chunk, const u8 *data,
  10377. + const struct yaffs_ext_tags *tags)
  10378. +{
  10379. + struct yaffs_packed_tags2 pt;
  10380. + int retval;
  10381. +
  10382. + int packed_tags_size =
  10383. + dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
  10384. + void *packed_tags_ptr =
  10385. + dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
  10386. +
  10387. + yaffs_trace(YAFFS_TRACE_MTD,
  10388. + "yaffs_tags_marshall_write chunk %d data %p tags %p",
  10389. + nand_chunk, data, tags);
  10390. +
  10391. + /* For yaffs2 writing there must be both data and tags.
  10392. + * If we're using inband tags, then the tags are stuffed into
  10393. + * the end of the data buffer.
  10394. + */
  10395. + if (!data || !tags)
  10396. + BUG();
  10397. + else if (dev->param.inband_tags) {
  10398. + struct yaffs_packed_tags2_tags_only *pt2tp;
  10399. + pt2tp =
  10400. + (struct yaffs_packed_tags2_tags_only *)(data +
  10401. + dev->
  10402. + data_bytes_per_chunk);
  10403. + yaffs_pack_tags2_tags_only(pt2tp, tags);
  10404. + } else {
  10405. + yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
  10406. + }
  10407. +
  10408. + retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
  10409. + data, dev->param.total_bytes_per_chunk,
  10410. + (dev->param.inband_tags) ? NULL : packed_tags_ptr,
  10411. + (dev->param.inband_tags) ? 0 : packed_tags_size);
  10412. +
  10413. + return retval;
  10414. +}
  10415. +
  10416. +static int yaffs_tags_marshall_read(struct yaffs_dev *dev,
  10417. + int nand_chunk, u8 *data,
  10418. + struct yaffs_ext_tags *tags)
  10419. +{
  10420. + int retval = 0;
  10421. + int local_data = 0;
  10422. + u8 spare_buffer[100];
  10423. + enum yaffs_ecc_result ecc_result;
  10424. +
  10425. + struct yaffs_packed_tags2 pt;
  10426. +
  10427. + int packed_tags_size =
  10428. + dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
  10429. + void *packed_tags_ptr =
  10430. + dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
  10431. +
  10432. + yaffs_trace(YAFFS_TRACE_MTD,
  10433. + "yaffs_tags_marshall_read chunk %d data %p tags %p",
  10434. + nand_chunk, data, tags);
  10435. +
  10436. + if (dev->param.inband_tags) {
  10437. + if (!data) {
  10438. + local_data = 1;
  10439. + data = yaffs_get_temp_buffer(dev);
  10440. + }
  10441. + }
  10442. +
  10443. + if (dev->param.inband_tags || (data && !tags))
  10444. + retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  10445. + data, dev->param.total_bytes_per_chunk,
  10446. + NULL, 0,
  10447. + &ecc_result);
  10448. + else if (tags)
  10449. + retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
  10450. + data, dev->param.total_bytes_per_chunk,
  10451. + spare_buffer, packed_tags_size,
  10452. + &ecc_result);
  10453. + else
  10454. + BUG();
  10455. +
  10456. +
  10457. + if (dev->param.inband_tags) {
  10458. + if (tags) {
  10459. + struct yaffs_packed_tags2_tags_only *pt2tp;
  10460. + pt2tp =
  10461. + (struct yaffs_packed_tags2_tags_only *)
  10462. + &data[dev->data_bytes_per_chunk];
  10463. + yaffs_unpack_tags2_tags_only(tags, pt2tp);
  10464. + }
  10465. + } else if (tags) {
  10466. + memcpy(packed_tags_ptr, spare_buffer, packed_tags_size);
  10467. + yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
  10468. + }
  10469. +
  10470. + if (local_data)
  10471. + yaffs_release_temp_buffer(dev, data);
  10472. +
  10473. + if (tags && ecc_result == YAFFS_ECC_RESULT_UNFIXED) {
  10474. + tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
  10475. + dev->n_ecc_unfixed++;
  10476. + }
  10477. +
  10478. + if (tags && ecc_result == -YAFFS_ECC_RESULT_FIXED) {
  10479. + if (tags->ecc_result <= YAFFS_ECC_RESULT_NO_ERROR)
  10480. + tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
  10481. + dev->n_ecc_fixed++;
  10482. + }
  10483. +
  10484. + if (ecc_result < YAFFS_ECC_RESULT_UNFIXED)
  10485. + return YAFFS_OK;
  10486. + else
  10487. + return YAFFS_FAIL;
  10488. +}
  10489. +
  10490. +static int yaffs_tags_marshall_query_block(struct yaffs_dev *dev, int block_no,
  10491. + enum yaffs_block_state *state,
  10492. + u32 *seq_number)
  10493. +{
  10494. + int retval;
  10495. +
  10496. + yaffs_trace(YAFFS_TRACE_MTD, "yaffs_tags_marshall_query_block %d",
  10497. + block_no);
  10498. +
  10499. + retval = dev->drv.drv_check_bad_fn(dev, block_no);
  10500. +
  10501. + if (retval== YAFFS_FAIL) {
  10502. + yaffs_trace(YAFFS_TRACE_MTD, "block is bad");
  10503. +
  10504. + *state = YAFFS_BLOCK_STATE_DEAD;
  10505. + *seq_number = 0;
  10506. + } else {
  10507. + struct yaffs_ext_tags t;
  10508. +
  10509. + yaffs_tags_marshall_read(dev,
  10510. + block_no * dev->param.chunks_per_block,
  10511. + NULL, &t);
  10512. +
  10513. + if (t.chunk_used) {
  10514. + *seq_number = t.seq_number;
  10515. + *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
  10516. + } else {
  10517. + *seq_number = 0;
  10518. + *state = YAFFS_BLOCK_STATE_EMPTY;
  10519. + }
  10520. + }
  10521. +
  10522. + yaffs_trace(YAFFS_TRACE_MTD,
  10523. + "block query returns seq %d state %d",
  10524. + *seq_number, *state);
  10525. +
  10526. + if (retval == 0)
  10527. + return YAFFS_OK;
  10528. + else
  10529. + return YAFFS_FAIL;
  10530. +}
  10531. +
  10532. +static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no)
  10533. +{
  10534. + return dev->drv.drv_mark_bad_fn(dev, block_no);
  10535. +
  10536. +}
  10537. +
  10538. +
  10539. +void yaffs_tags_marshall_install(struct yaffs_dev *dev)
  10540. +{
  10541. + if (!dev->param.is_yaffs2)
  10542. + return;
  10543. +
  10544. + if (!dev->tagger.write_chunk_tags_fn)
  10545. + dev->tagger.write_chunk_tags_fn = yaffs_tags_marshall_write;
  10546. +
  10547. + if (!dev->tagger.read_chunk_tags_fn)
  10548. + dev->tagger.read_chunk_tags_fn = yaffs_tags_marshall_read;
  10549. +
  10550. + if (!dev->tagger.query_block_fn)
  10551. + dev->tagger.query_block_fn = yaffs_tags_marshall_query_block;
  10552. +
  10553. + if (!dev->tagger.mark_bad_fn)
  10554. + dev->tagger.mark_bad_fn = yaffs_tags_marshall_mark_bad;
  10555. +
  10556. +}
  10557. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_tagsmarshall.h linux-3.14.4/fs/yaffs2/yaffs_tagsmarshall.h
  10558. --- linux-3.14.4.orig/fs/yaffs2/yaffs_tagsmarshall.h 1970-01-01 01:00:00.000000000 +0100
  10559. +++ linux-3.14.4/fs/yaffs2/yaffs_tagsmarshall.h 2014-05-14 12:41:23.988792461 +0200
  10560. @@ -0,0 +1,22 @@
  10561. +/*
  10562. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  10563. + *
  10564. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10565. + * for Toby Churchill Ltd and Brightstar Engineering
  10566. + *
  10567. + * Created by Charles Manning <charles@aleph1.co.uk>
  10568. + *
  10569. + * This program is free software; you can redistribute it and/or modify
  10570. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  10571. + * published by the Free Software Foundation.
  10572. + *
  10573. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  10574. + */
  10575. +
  10576. +#ifndef __YAFFS_TAGSMARSHALL_H__
  10577. +#define __YAFFS_TAGSMARSHALL_H__
  10578. +
  10579. +#include "yaffs_guts.h"
  10580. +void yaffs_tags_marshall_install(struct yaffs_dev *dev);
  10581. +
  10582. +#endif
  10583. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_trace.h linux-3.14.4/fs/yaffs2/yaffs_trace.h
  10584. --- linux-3.14.4.orig/fs/yaffs2/yaffs_trace.h 1970-01-01 01:00:00.000000000 +0100
  10585. +++ linux-3.14.4/fs/yaffs2/yaffs_trace.h 2014-05-14 12:41:23.988792461 +0200
  10586. @@ -0,0 +1,57 @@
  10587. +/*
  10588. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  10589. + *
  10590. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10591. + * for Toby Churchill Ltd and Brightstar Engineering
  10592. + *
  10593. + * Created by Charles Manning <charles@aleph1.co.uk>
  10594. + *
  10595. + * This program is free software; you can redistribute it and/or modify
  10596. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  10597. + * published by the Free Software Foundation.
  10598. + *
  10599. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  10600. + */
  10601. +
  10602. +#ifndef __YTRACE_H__
  10603. +#define __YTRACE_H__
  10604. +
  10605. +extern unsigned int yaffs_trace_mask;
  10606. +extern unsigned int yaffs_wr_attempts;
  10607. +
  10608. +/*
  10609. + * Tracing flags.
  10610. + * The flags masked in YAFFS_TRACE_ALWAYS are always traced.
  10611. + */
  10612. +
  10613. +#define YAFFS_TRACE_OS 0x00000002
  10614. +#define YAFFS_TRACE_ALLOCATE 0x00000004
  10615. +#define YAFFS_TRACE_SCAN 0x00000008
  10616. +#define YAFFS_TRACE_BAD_BLOCKS 0x00000010
  10617. +#define YAFFS_TRACE_ERASE 0x00000020
  10618. +#define YAFFS_TRACE_GC 0x00000040
  10619. +#define YAFFS_TRACE_WRITE 0x00000080
  10620. +#define YAFFS_TRACE_TRACING 0x00000100
  10621. +#define YAFFS_TRACE_DELETION 0x00000200
  10622. +#define YAFFS_TRACE_BUFFERS 0x00000400
  10623. +#define YAFFS_TRACE_NANDACCESS 0x00000800
  10624. +#define YAFFS_TRACE_GC_DETAIL 0x00001000
  10625. +#define YAFFS_TRACE_SCAN_DEBUG 0x00002000
  10626. +#define YAFFS_TRACE_MTD 0x00004000
  10627. +#define YAFFS_TRACE_CHECKPOINT 0x00008000
  10628. +
  10629. +#define YAFFS_TRACE_VERIFY 0x00010000
  10630. +#define YAFFS_TRACE_VERIFY_NAND 0x00020000
  10631. +#define YAFFS_TRACE_VERIFY_FULL 0x00040000
  10632. +#define YAFFS_TRACE_VERIFY_ALL 0x000f0000
  10633. +
  10634. +#define YAFFS_TRACE_SYNC 0x00100000
  10635. +#define YAFFS_TRACE_BACKGROUND 0x00200000
  10636. +#define YAFFS_TRACE_LOCK 0x00400000
  10637. +#define YAFFS_TRACE_MOUNT 0x00800000
  10638. +
  10639. +#define YAFFS_TRACE_ERROR 0x40000000
  10640. +#define YAFFS_TRACE_BUG 0x80000000
  10641. +#define YAFFS_TRACE_ALWAYS 0xf0000000
  10642. +
  10643. +#endif
  10644. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_verify.c linux-3.14.4/fs/yaffs2/yaffs_verify.c
  10645. --- linux-3.14.4.orig/fs/yaffs2/yaffs_verify.c 1970-01-01 01:00:00.000000000 +0100
  10646. +++ linux-3.14.4/fs/yaffs2/yaffs_verify.c 2014-05-14 12:41:23.988792461 +0200
  10647. @@ -0,0 +1,529 @@
  10648. +/*
  10649. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  10650. + *
  10651. + * Copyright (C) 2002-2011 Aleph One Ltd.
  10652. + * for Toby Churchill Ltd and Brightstar Engineering
  10653. + *
  10654. + * Created by Charles Manning <charles@aleph1.co.uk>
  10655. + *
  10656. + * This program is free software; you can redistribute it and/or modify
  10657. + * it under the terms of the GNU General Public License version 2 as
  10658. + * published by the Free Software Foundation.
  10659. + */
  10660. +
  10661. +#include "yaffs_verify.h"
  10662. +#include "yaffs_trace.h"
  10663. +#include "yaffs_bitmap.h"
  10664. +#include "yaffs_getblockinfo.h"
  10665. +#include "yaffs_nand.h"
  10666. +
  10667. +int yaffs_skip_verification(struct yaffs_dev *dev)
  10668. +{
  10669. + (void) dev;
  10670. + return !(yaffs_trace_mask &
  10671. + (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
  10672. +}
  10673. +
  10674. +static int yaffs_skip_full_verification(struct yaffs_dev *dev)
  10675. +{
  10676. + (void) dev;
  10677. + return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_FULL));
  10678. +}
  10679. +
  10680. +static int yaffs_skip_nand_verification(struct yaffs_dev *dev)
  10681. +{
  10682. + (void) dev;
  10683. + return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND));
  10684. +}
  10685. +
  10686. +static const char * const block_state_name[] = {
  10687. + "Unknown",
  10688. + "Needs scan",
  10689. + "Scanning",
  10690. + "Empty",
  10691. + "Allocating",
  10692. + "Full",
  10693. + "Dirty",
  10694. + "Checkpoint",
  10695. + "Collecting",
  10696. + "Dead"
  10697. +};
  10698. +
  10699. +void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n)
  10700. +{
  10701. + int actually_used;
  10702. + int in_use;
  10703. +
  10704. + if (yaffs_skip_verification(dev))
  10705. + return;
  10706. +
  10707. + /* Report illegal runtime states */
  10708. + if (bi->block_state >= YAFFS_NUMBER_OF_BLOCK_STATES)
  10709. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10710. + "Block %d has undefined state %d",
  10711. + n, bi->block_state);
  10712. +
  10713. + switch (bi->block_state) {
  10714. + case YAFFS_BLOCK_STATE_UNKNOWN:
  10715. + case YAFFS_BLOCK_STATE_SCANNING:
  10716. + case YAFFS_BLOCK_STATE_NEEDS_SCAN:
  10717. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10718. + "Block %d has bad run-state %s",
  10719. + n, block_state_name[bi->block_state]);
  10720. + }
  10721. +
  10722. + /* Check pages in use and soft deletions are legal */
  10723. +
  10724. + actually_used = bi->pages_in_use - bi->soft_del_pages;
  10725. +
  10726. + if (bi->pages_in_use < 0 ||
  10727. + bi->pages_in_use > dev->param.chunks_per_block ||
  10728. + bi->soft_del_pages < 0 ||
  10729. + bi->soft_del_pages > dev->param.chunks_per_block ||
  10730. + actually_used < 0 || actually_used > dev->param.chunks_per_block)
  10731. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10732. + "Block %d has illegal values pages_in_used %d soft_del_pages %d",
  10733. + n, bi->pages_in_use, bi->soft_del_pages);
  10734. +
  10735. + /* Check chunk bitmap legal */
  10736. + in_use = yaffs_count_chunk_bits(dev, n);
  10737. + if (in_use != bi->pages_in_use)
  10738. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10739. + "Block %d has inconsistent values pages_in_use %d counted chunk bits %d",
  10740. + n, bi->pages_in_use, in_use);
  10741. +}
  10742. +
  10743. +void yaffs_verify_collected_blk(struct yaffs_dev *dev,
  10744. + struct yaffs_block_info *bi, int n)
  10745. +{
  10746. + yaffs_verify_blk(dev, bi, n);
  10747. +
  10748. + /* After collection the block should be in the erased state */
  10749. +
  10750. + if (bi->block_state != YAFFS_BLOCK_STATE_COLLECTING &&
  10751. + bi->block_state != YAFFS_BLOCK_STATE_EMPTY) {
  10752. + yaffs_trace(YAFFS_TRACE_ERROR,
  10753. + "Block %d is in state %d after gc, should be erased",
  10754. + n, bi->block_state);
  10755. + }
  10756. +}
  10757. +
  10758. +void yaffs_verify_blocks(struct yaffs_dev *dev)
  10759. +{
  10760. + int i;
  10761. + int state_count[YAFFS_NUMBER_OF_BLOCK_STATES];
  10762. + int illegal_states = 0;
  10763. +
  10764. + if (yaffs_skip_verification(dev))
  10765. + return;
  10766. +
  10767. + memset(state_count, 0, sizeof(state_count));
  10768. +
  10769. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  10770. + struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
  10771. + yaffs_verify_blk(dev, bi, i);
  10772. +
  10773. + if (bi->block_state < YAFFS_NUMBER_OF_BLOCK_STATES)
  10774. + state_count[bi->block_state]++;
  10775. + else
  10776. + illegal_states++;
  10777. + }
  10778. +
  10779. + yaffs_trace(YAFFS_TRACE_VERIFY, "Block summary");
  10780. +
  10781. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10782. + "%d blocks have illegal states",
  10783. + illegal_states);
  10784. + if (state_count[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
  10785. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10786. + "Too many allocating blocks");
  10787. +
  10788. + for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++)
  10789. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10790. + "%s %d blocks",
  10791. + block_state_name[i], state_count[i]);
  10792. +
  10793. + if (dev->blocks_in_checkpt != state_count[YAFFS_BLOCK_STATE_CHECKPOINT])
  10794. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10795. + "Checkpoint block count wrong dev %d count %d",
  10796. + dev->blocks_in_checkpt,
  10797. + state_count[YAFFS_BLOCK_STATE_CHECKPOINT]);
  10798. +
  10799. + if (dev->n_erased_blocks != state_count[YAFFS_BLOCK_STATE_EMPTY])
  10800. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10801. + "Erased block count wrong dev %d count %d",
  10802. + dev->n_erased_blocks,
  10803. + state_count[YAFFS_BLOCK_STATE_EMPTY]);
  10804. +
  10805. + if (state_count[YAFFS_BLOCK_STATE_COLLECTING] > 1)
  10806. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10807. + "Too many collecting blocks %d (max is 1)",
  10808. + state_count[YAFFS_BLOCK_STATE_COLLECTING]);
  10809. +}
  10810. +
  10811. +/*
  10812. + * Verify the object header. oh must be valid, but obj and tags may be NULL in
  10813. + * which case those tests will not be performed.
  10814. + */
  10815. +void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
  10816. + struct yaffs_ext_tags *tags, int parent_check)
  10817. +{
  10818. + if (obj && yaffs_skip_verification(obj->my_dev))
  10819. + return;
  10820. +
  10821. + if (!(tags && obj && oh)) {
  10822. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10823. + "Verifying object header tags %p obj %p oh %p",
  10824. + tags, obj, oh);
  10825. + return;
  10826. + }
  10827. +
  10828. + if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
  10829. + oh->type > YAFFS_OBJECT_TYPE_MAX)
  10830. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10831. + "Obj %d header type is illegal value 0x%x",
  10832. + tags->obj_id, oh->type);
  10833. +
  10834. + if (tags->obj_id != obj->obj_id)
  10835. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10836. + "Obj %d header mismatch obj_id %d",
  10837. + tags->obj_id, obj->obj_id);
  10838. +
  10839. + /*
  10840. + * Check that the object's parent ids match if parent_check requested.
  10841. + *
  10842. + * Tests do not apply to the root object.
  10843. + */
  10844. +
  10845. + if (parent_check && tags->obj_id > 1 && !obj->parent)
  10846. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10847. + "Obj %d header mismatch parent_id %d obj->parent is NULL",
  10848. + tags->obj_id, oh->parent_obj_id);
  10849. +
  10850. + if (parent_check && obj->parent &&
  10851. + oh->parent_obj_id != obj->parent->obj_id &&
  10852. + (oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED ||
  10853. + obj->parent->obj_id != YAFFS_OBJECTID_DELETED))
  10854. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10855. + "Obj %d header mismatch parent_id %d parent_obj_id %d",
  10856. + tags->obj_id, oh->parent_obj_id,
  10857. + obj->parent->obj_id);
  10858. +
  10859. + if (tags->obj_id > 1 && oh->name[0] == 0) /* Null name */
  10860. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10861. + "Obj %d header name is NULL",
  10862. + obj->obj_id);
  10863. +
  10864. + if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff) /* Junk name */
  10865. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10866. + "Obj %d header name is 0xff",
  10867. + obj->obj_id);
  10868. +}
  10869. +
  10870. +void yaffs_verify_file(struct yaffs_obj *obj)
  10871. +{
  10872. + u32 x;
  10873. + int required_depth;
  10874. + int actual_depth;
  10875. + int last_chunk;
  10876. + u32 offset_in_chunk;
  10877. + u32 the_chunk;
  10878. +
  10879. + u32 i;
  10880. + struct yaffs_dev *dev;
  10881. + struct yaffs_ext_tags tags;
  10882. + struct yaffs_tnode *tn;
  10883. + u32 obj_id;
  10884. +
  10885. + if (!obj)
  10886. + return;
  10887. +
  10888. + if (yaffs_skip_verification(obj->my_dev))
  10889. + return;
  10890. +
  10891. + dev = obj->my_dev;
  10892. + obj_id = obj->obj_id;
  10893. +
  10894. +
  10895. + /* Check file size is consistent with tnode depth */
  10896. + yaffs_addr_to_chunk(dev, obj->variant.file_variant.file_size,
  10897. + &last_chunk, &offset_in_chunk);
  10898. + last_chunk++;
  10899. + x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS;
  10900. + required_depth = 0;
  10901. + while (x > 0) {
  10902. + x >>= YAFFS_TNODES_INTERNAL_BITS;
  10903. + required_depth++;
  10904. + }
  10905. +
  10906. + actual_depth = obj->variant.file_variant.top_level;
  10907. +
  10908. + /* Check that the chunks in the tnode tree are all correct.
  10909. + * We do this by scanning through the tnode tree and
  10910. + * checking the tags for every chunk match.
  10911. + */
  10912. +
  10913. + if (yaffs_skip_nand_verification(dev))
  10914. + return;
  10915. +
  10916. + for (i = 1; i <= last_chunk; i++) {
  10917. + tn = yaffs_find_tnode_0(dev, &obj->variant.file_variant, i);
  10918. +
  10919. + if (!tn)
  10920. + continue;
  10921. +
  10922. + the_chunk = yaffs_get_group_base(dev, tn, i);
  10923. + if (the_chunk > 0) {
  10924. + yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
  10925. + &tags);
  10926. + if (tags.obj_id != obj_id || tags.chunk_id != i)
  10927. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10928. + "Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)",
  10929. + obj_id, i, the_chunk,
  10930. + tags.obj_id, tags.chunk_id);
  10931. + }
  10932. + }
  10933. +}
  10934. +
  10935. +void yaffs_verify_link(struct yaffs_obj *obj)
  10936. +{
  10937. + if (obj && yaffs_skip_verification(obj->my_dev))
  10938. + return;
  10939. +
  10940. + /* Verify sane equivalent object */
  10941. +}
  10942. +
  10943. +void yaffs_verify_symlink(struct yaffs_obj *obj)
  10944. +{
  10945. + if (obj && yaffs_skip_verification(obj->my_dev))
  10946. + return;
  10947. +
  10948. + /* Verify symlink string */
  10949. +}
  10950. +
  10951. +void yaffs_verify_special(struct yaffs_obj *obj)
  10952. +{
  10953. + if (obj && yaffs_skip_verification(obj->my_dev))
  10954. + return;
  10955. +}
  10956. +
  10957. +void yaffs_verify_obj(struct yaffs_obj *obj)
  10958. +{
  10959. + struct yaffs_dev *dev;
  10960. + u32 chunk_min;
  10961. + u32 chunk_max;
  10962. + u32 chunk_id_ok;
  10963. + u32 chunk_in_range;
  10964. + u32 chunk_wrongly_deleted;
  10965. + u32 chunk_valid;
  10966. +
  10967. + if (!obj)
  10968. + return;
  10969. +
  10970. + if (obj->being_created)
  10971. + return;
  10972. +
  10973. + dev = obj->my_dev;
  10974. +
  10975. + if (yaffs_skip_verification(dev))
  10976. + return;
  10977. +
  10978. + /* Check sane object header chunk */
  10979. +
  10980. + chunk_min = dev->internal_start_block * dev->param.chunks_per_block;
  10981. + chunk_max =
  10982. + (dev->internal_end_block + 1) * dev->param.chunks_per_block - 1;
  10983. +
  10984. + chunk_in_range = (((unsigned)(obj->hdr_chunk)) >= chunk_min &&
  10985. + ((unsigned)(obj->hdr_chunk)) <= chunk_max);
  10986. + chunk_id_ok = chunk_in_range || (obj->hdr_chunk == 0);
  10987. + chunk_valid = chunk_in_range &&
  10988. + yaffs_check_chunk_bit(dev,
  10989. + obj->hdr_chunk / dev->param.chunks_per_block,
  10990. + obj->hdr_chunk % dev->param.chunks_per_block);
  10991. + chunk_wrongly_deleted = chunk_in_range && !chunk_valid;
  10992. +
  10993. + if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted))
  10994. + yaffs_trace(YAFFS_TRACE_VERIFY,
  10995. + "Obj %d has chunk_id %d %s %s",
  10996. + obj->obj_id, obj->hdr_chunk,
  10997. + chunk_id_ok ? "" : ",out of range",
  10998. + chunk_wrongly_deleted ? ",marked as deleted" : "");
  10999. +
  11000. + if (chunk_valid && !yaffs_skip_nand_verification(dev)) {
  11001. + struct yaffs_ext_tags tags;
  11002. + struct yaffs_obj_hdr *oh;
  11003. + u8 *buffer = yaffs_get_temp_buffer(dev);
  11004. +
  11005. + oh = (struct yaffs_obj_hdr *)buffer;
  11006. +
  11007. + yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, buffer, &tags);
  11008. +
  11009. + yaffs_verify_oh(obj, oh, &tags, 1);
  11010. +
  11011. + yaffs_release_temp_buffer(dev, buffer);
  11012. + }
  11013. +
  11014. + /* Verify it has a parent */
  11015. + if (obj && !obj->fake && (!obj->parent || obj->parent->my_dev != dev)) {
  11016. + yaffs_trace(YAFFS_TRACE_VERIFY,
  11017. + "Obj %d has parent pointer %p which does not look like an object",
  11018. + obj->obj_id, obj->parent);
  11019. + }
  11020. +
  11021. + /* Verify parent is a directory */
  11022. + if (obj->parent &&
  11023. + obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  11024. + yaffs_trace(YAFFS_TRACE_VERIFY,
  11025. + "Obj %d's parent is not a directory (type %d)",
  11026. + obj->obj_id, obj->parent->variant_type);
  11027. + }
  11028. +
  11029. + switch (obj->variant_type) {
  11030. + case YAFFS_OBJECT_TYPE_FILE:
  11031. + yaffs_verify_file(obj);
  11032. + break;
  11033. + case YAFFS_OBJECT_TYPE_SYMLINK:
  11034. + yaffs_verify_symlink(obj);
  11035. + break;
  11036. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  11037. + yaffs_verify_dir(obj);
  11038. + break;
  11039. + case YAFFS_OBJECT_TYPE_HARDLINK:
  11040. + yaffs_verify_link(obj);
  11041. + break;
  11042. + case YAFFS_OBJECT_TYPE_SPECIAL:
  11043. + yaffs_verify_special(obj);
  11044. + break;
  11045. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  11046. + default:
  11047. + yaffs_trace(YAFFS_TRACE_VERIFY,
  11048. + "Obj %d has illegaltype %d",
  11049. + obj->obj_id, obj->variant_type);
  11050. + break;
  11051. + }
  11052. +}
  11053. +
  11054. +void yaffs_verify_objects(struct yaffs_dev *dev)
  11055. +{
  11056. + struct yaffs_obj *obj;
  11057. + int i;
  11058. + struct list_head *lh;
  11059. +
  11060. + if (yaffs_skip_verification(dev))
  11061. + return;
  11062. +
  11063. + /* Iterate through the objects in each hash entry */
  11064. +
  11065. + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
  11066. + list_for_each(lh, &dev->obj_bucket[i].list) {
  11067. + obj = list_entry(lh, struct yaffs_obj, hash_link);
  11068. + yaffs_verify_obj(obj);
  11069. + }
  11070. + }
  11071. +}
  11072. +
  11073. +void yaffs_verify_obj_in_dir(struct yaffs_obj *obj)
  11074. +{
  11075. + struct list_head *lh;
  11076. + struct yaffs_obj *list_obj;
  11077. + int count = 0;
  11078. +
  11079. + if (!obj) {
  11080. + yaffs_trace(YAFFS_TRACE_ALWAYS, "No object to verify");
  11081. + BUG();
  11082. + return;
  11083. + }
  11084. +
  11085. + if (yaffs_skip_verification(obj->my_dev))
  11086. + return;
  11087. +
  11088. + if (!obj->parent) {
  11089. + yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent");
  11090. + BUG();
  11091. + return;
  11092. + }
  11093. +
  11094. + if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  11095. + yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory");
  11096. + BUG();
  11097. + }
  11098. +
  11099. + /* Iterate through the objects in each hash entry */
  11100. +
  11101. + list_for_each(lh, &obj->parent->variant.dir_variant.children) {
  11102. + list_obj = list_entry(lh, struct yaffs_obj, siblings);
  11103. + yaffs_verify_obj(list_obj);
  11104. + if (obj == list_obj)
  11105. + count++;
  11106. + }
  11107. +
  11108. + if (count != 1) {
  11109. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  11110. + "Object in directory %d times",
  11111. + count);
  11112. + BUG();
  11113. + }
  11114. +}
  11115. +
  11116. +void yaffs_verify_dir(struct yaffs_obj *directory)
  11117. +{
  11118. + struct list_head *lh;
  11119. + struct yaffs_obj *list_obj;
  11120. +
  11121. + if (!directory) {
  11122. + BUG();
  11123. + return;
  11124. + }
  11125. +
  11126. + if (yaffs_skip_full_verification(directory->my_dev))
  11127. + return;
  11128. +
  11129. + if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  11130. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  11131. + "Directory has wrong type: %d",
  11132. + directory->variant_type);
  11133. + BUG();
  11134. + }
  11135. +
  11136. + /* Iterate through the objects in each hash entry */
  11137. +
  11138. + list_for_each(lh, &directory->variant.dir_variant.children) {
  11139. + list_obj = list_entry(lh, struct yaffs_obj, siblings);
  11140. + if (list_obj->parent != directory) {
  11141. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  11142. + "Object in directory list has wrong parent %p",
  11143. + list_obj->parent);
  11144. + BUG();
  11145. + }
  11146. + yaffs_verify_obj_in_dir(list_obj);
  11147. + }
  11148. +}
  11149. +
  11150. +static int yaffs_free_verification_failures;
  11151. +
  11152. +void yaffs_verify_free_chunks(struct yaffs_dev *dev)
  11153. +{
  11154. + int counted;
  11155. + int difference;
  11156. +
  11157. + if (yaffs_skip_verification(dev))
  11158. + return;
  11159. +
  11160. + counted = yaffs_count_free_chunks(dev);
  11161. +
  11162. + difference = dev->n_free_chunks - counted;
  11163. +
  11164. + if (difference) {
  11165. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  11166. + "Freechunks verification failure %d %d %d",
  11167. + dev->n_free_chunks, counted, difference);
  11168. + yaffs_free_verification_failures++;
  11169. + }
  11170. +}
  11171. +
  11172. +int yaffs_verify_file_sane(struct yaffs_obj *in)
  11173. +{
  11174. + (void) in;
  11175. + return YAFFS_OK;
  11176. +}
  11177. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_verify.h linux-3.14.4/fs/yaffs2/yaffs_verify.h
  11178. --- linux-3.14.4.orig/fs/yaffs2/yaffs_verify.h 1970-01-01 01:00:00.000000000 +0100
  11179. +++ linux-3.14.4/fs/yaffs2/yaffs_verify.h 2014-05-14 12:41:23.988792461 +0200
  11180. @@ -0,0 +1,43 @@
  11181. +/*
  11182. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  11183. + *
  11184. + * Copyright (C) 2002-2011 Aleph One Ltd.
  11185. + * for Toby Churchill Ltd and Brightstar Engineering
  11186. + *
  11187. + * Created by Charles Manning <charles@aleph1.co.uk>
  11188. + *
  11189. + * This program is free software; you can redistribute it and/or modify
  11190. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  11191. + * published by the Free Software Foundation.
  11192. + *
  11193. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  11194. + */
  11195. +
  11196. +#ifndef __YAFFS_VERIFY_H__
  11197. +#define __YAFFS_VERIFY_H__
  11198. +
  11199. +#include "yaffs_guts.h"
  11200. +
  11201. +void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi,
  11202. + int n);
  11203. +void yaffs_verify_collected_blk(struct yaffs_dev *dev,
  11204. + struct yaffs_block_info *bi, int n);
  11205. +void yaffs_verify_blocks(struct yaffs_dev *dev);
  11206. +
  11207. +void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
  11208. + struct yaffs_ext_tags *tags, int parent_check);
  11209. +void yaffs_verify_file(struct yaffs_obj *obj);
  11210. +void yaffs_verify_link(struct yaffs_obj *obj);
  11211. +void yaffs_verify_symlink(struct yaffs_obj *obj);
  11212. +void yaffs_verify_special(struct yaffs_obj *obj);
  11213. +void yaffs_verify_obj(struct yaffs_obj *obj);
  11214. +void yaffs_verify_objects(struct yaffs_dev *dev);
  11215. +void yaffs_verify_obj_in_dir(struct yaffs_obj *obj);
  11216. +void yaffs_verify_dir(struct yaffs_obj *directory);
  11217. +void yaffs_verify_free_chunks(struct yaffs_dev *dev);
  11218. +
  11219. +int yaffs_verify_file_sane(struct yaffs_obj *obj);
  11220. +
  11221. +int yaffs_skip_verification(struct yaffs_dev *dev);
  11222. +
  11223. +#endif
  11224. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_vfs.c linux-3.14.4/fs/yaffs2/yaffs_vfs.c
  11225. --- linux-3.14.4.orig/fs/yaffs2/yaffs_vfs.c 1970-01-01 01:00:00.000000000 +0100
  11226. +++ linux-3.14.4/fs/yaffs2/yaffs_vfs.c 2014-05-14 12:41:23.992792475 +0200
  11227. @@ -0,0 +1,3600 @@
  11228. +/*
  11229. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  11230. + *
  11231. + * Copyright (C) 2002-2011 Aleph One Ltd.
  11232. + * for Toby Churchill Ltd and Brightstar Engineering
  11233. + *
  11234. + * Created by Charles Manning <charles@aleph1.co.uk>
  11235. + * Acknowledgements:
  11236. + * Luc van OostenRyck for numerous patches.
  11237. + * Nick Bane for numerous patches.
  11238. + * Nick Bane for 2.5/2.6 integration.
  11239. + * Andras Toth for mknod rdev issue.
  11240. + * Michael Fischer for finding the problem with inode inconsistency.
  11241. + * Some code bodily lifted from JFFS
  11242. + *
  11243. + * This program is free software; you can redistribute it and/or modify
  11244. + * it under the terms of the GNU General Public License version 2 as
  11245. + * published by the Free Software Foundation.
  11246. + */
  11247. +
  11248. +/*
  11249. + *
  11250. + * This is the file system front-end to YAFFS that hooks it up to
  11251. + * the VFS.
  11252. + *
  11253. + * Special notes:
  11254. + * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with
  11255. + * this superblock
  11256. + * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this
  11257. + * superblock
  11258. + * >> inode->u.generic_ip points to the associated struct yaffs_obj.
  11259. + */
  11260. +
  11261. +/*
  11262. + * There are two variants of the VFS glue code. This variant should compile
  11263. + * for any version of Linux.
  11264. + */
  11265. +#include <linux/version.h>
  11266. +
  11267. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
  11268. +#define YAFFS_COMPILE_BACKGROUND
  11269. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23))
  11270. +#define YAFFS_COMPILE_FREEZER
  11271. +#endif
  11272. +#endif
  11273. +
  11274. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
  11275. +#define YAFFS_COMPILE_EXPORTFS
  11276. +#endif
  11277. +
  11278. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
  11279. +#define YAFFS_USE_SETATTR_COPY
  11280. +#define YAFFS_USE_TRUNCATE_SETSIZE
  11281. +#endif
  11282. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
  11283. +#define YAFFS_HAS_EVICT_INODE
  11284. +#endif
  11285. +
  11286. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
  11287. +#define YAFFS_NEW_FOLLOW_LINK 1
  11288. +#else
  11289. +#define YAFFS_NEW_FOLLOW_LINK 0
  11290. +#endif
  11291. +
  11292. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
  11293. +#define YAFFS_HAS_WRITE_SUPER
  11294. +#endif
  11295. +
  11296. +
  11297. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  11298. +#include <linux/config.h>
  11299. +#endif
  11300. +
  11301. +#include <linux/kernel.h>
  11302. +#include <linux/module.h>
  11303. +#include <linux/slab.h>
  11304. +#include <linux/init.h>
  11305. +#include <linux/fs.h>
  11306. +#include <linux/proc_fs.h>
  11307. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
  11308. +#include <linux/smp_lock.h>
  11309. +#endif
  11310. +#include <linux/pagemap.h>
  11311. +#include <linux/mtd/mtd.h>
  11312. +#include <linux/interrupt.h>
  11313. +#include <linux/string.h>
  11314. +#include <linux/ctype.h>
  11315. +
  11316. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  11317. +#include <linux/namei.h>
  11318. +#endif
  11319. +
  11320. +#ifdef YAFFS_COMPILE_EXPORTFS
  11321. +#include <linux/exportfs.h>
  11322. +#endif
  11323. +
  11324. +#ifdef YAFFS_COMPILE_BACKGROUND
  11325. +#include <linux/kthread.h>
  11326. +#include <linux/delay.h>
  11327. +#endif
  11328. +#ifdef YAFFS_COMPILE_FREEZER
  11329. +#include <linux/freezer.h>
  11330. +#endif
  11331. +
  11332. +#include <asm/div64.h>
  11333. +
  11334. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11335. +
  11336. +#include <linux/statfs.h>
  11337. +
  11338. +#define UnlockPage(p) unlock_page(p)
  11339. +#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
  11340. +
  11341. +/* FIXME: use sb->s_id instead ? */
  11342. +#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
  11343. +
  11344. +#else
  11345. +
  11346. +#include <linux/locks.h>
  11347. +#define BDEVNAME_SIZE 0
  11348. +#define yaffs_devname(sb, buf) kdevname(sb->s_dev)
  11349. +
  11350. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
  11351. +/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
  11352. +#define __user
  11353. +#endif
  11354. +
  11355. +#endif
  11356. +
  11357. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
  11358. +#define YPROC_ROOT (&proc_root)
  11359. +#else
  11360. +#define YPROC_ROOT NULL
  11361. +#endif
  11362. +
  11363. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
  11364. +#define Y_INIT_TIMER(a) init_timer(a)
  11365. +#else
  11366. +#define Y_INIT_TIMER(a) init_timer_on_stack(a)
  11367. +#endif
  11368. +
  11369. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
  11370. +#define YAFFS_USE_WRITE_BEGIN_END 1
  11371. +#else
  11372. +#define YAFFS_USE_WRITE_BEGIN_END 0
  11373. +#endif
  11374. +
  11375. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
  11376. +#define YAFFS_SUPER_HAS_DIRTY
  11377. +#endif
  11378. +
  11379. +
  11380. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
  11381. +#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0)
  11382. +#endif
  11383. +
  11384. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
  11385. +static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
  11386. +{
  11387. + uint64_t result = partition_size;
  11388. + do_div(result, block_size);
  11389. + return (uint32_t) result;
  11390. +}
  11391. +#else
  11392. +#define YCALCBLOCKS(s, b) ((s)/(b))
  11393. +#endif
  11394. +
  11395. +#include <linux/uaccess.h>
  11396. +#include <linux/mtd/mtd.h>
  11397. +
  11398. +#include "yportenv.h"
  11399. +#include "yaffs_trace.h"
  11400. +#include "yaffs_guts.h"
  11401. +#include "yaffs_attribs.h"
  11402. +
  11403. +#include "yaffs_linux.h"
  11404. +
  11405. +#include "yaffs_mtdif.h"
  11406. +#include "yaffs_packedtags2.h"
  11407. +#include "yaffs_getblockinfo.h"
  11408. +
  11409. +unsigned int yaffs_trace_mask =
  11410. + YAFFS_TRACE_BAD_BLOCKS |
  11411. + YAFFS_TRACE_ALWAYS |
  11412. + 0;
  11413. +
  11414. +unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
  11415. +unsigned int yaffs_auto_checkpoint = 1;
  11416. +unsigned int yaffs_gc_control = 1;
  11417. +unsigned int yaffs_bg_enable = 1;
  11418. +unsigned int yaffs_auto_select = 1;
  11419. +/* Module Parameters */
  11420. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11421. +module_param(yaffs_trace_mask, uint, 0644);
  11422. +module_param(yaffs_wr_attempts, uint, 0644);
  11423. +module_param(yaffs_auto_checkpoint, uint, 0644);
  11424. +module_param(yaffs_gc_control, uint, 0644);
  11425. +module_param(yaffs_bg_enable, uint, 0644);
  11426. +#else
  11427. +MODULE_PARM(yaffs_trace_mask, "i");
  11428. +MODULE_PARM(yaffs_wr_attempts, "i");
  11429. +MODULE_PARM(yaffs_auto_checkpoint, "i");
  11430. +MODULE_PARM(yaffs_gc_control, "i");
  11431. +#endif
  11432. +
  11433. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
  11434. +/* use iget and read_inode */
  11435. +#define Y_IGET(sb, inum) iget((sb), (inum))
  11436. +
  11437. +#else
  11438. +/* Call local equivalent */
  11439. +#define YAFFS_USE_OWN_IGET
  11440. +#define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
  11441. +
  11442. +#endif
  11443. +
  11444. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
  11445. +#define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private)
  11446. +#else
  11447. +#define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
  11448. +#endif
  11449. +
  11450. +#define yaffs_inode_to_obj(iptr) \
  11451. + ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
  11452. +#define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode)
  11453. +
  11454. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11455. +#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info)
  11456. +#else
  11457. +#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp)
  11458. +#endif
  11459. +
  11460. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  11461. +#define Y_CLEAR_INODE(i) clear_inode(i)
  11462. +#else
  11463. +#define Y_CLEAR_INODE(i) end_writeback(i)
  11464. +#endif
  11465. +
  11466. +
  11467. +#define update_dir_time(dir) do {\
  11468. + (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
  11469. + } while (0)
  11470. +
  11471. +static void yaffs_fill_inode_from_obj(struct inode *inode,
  11472. + struct yaffs_obj *obj);
  11473. +
  11474. +
  11475. +static void yaffs_gross_lock(struct yaffs_dev *dev)
  11476. +{
  11477. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locking %p", current);
  11478. + mutex_lock(&(yaffs_dev_to_lc(dev)->gross_lock));
  11479. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locked %p", current);
  11480. +}
  11481. +
  11482. +static void yaffs_gross_unlock(struct yaffs_dev *dev)
  11483. +{
  11484. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current);
  11485. + mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock));
  11486. +}
  11487. +
  11488. +
  11489. +static int yaffs_readpage_nolock(struct file *f, struct page *pg)
  11490. +{
  11491. + /* Lifted from jffs2 */
  11492. +
  11493. + struct yaffs_obj *obj;
  11494. + unsigned char *pg_buf;
  11495. + int ret;
  11496. + loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
  11497. + struct yaffs_dev *dev;
  11498. +
  11499. + yaffs_trace(YAFFS_TRACE_OS,
  11500. + "yaffs_readpage_nolock at %lld, size %08x",
  11501. + (long long)pos,
  11502. + (unsigned)PAGE_CACHE_SIZE);
  11503. +
  11504. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11505. +
  11506. + dev = obj->my_dev;
  11507. +
  11508. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11509. + BUG_ON(!PageLocked(pg));
  11510. +#else
  11511. + if (!PageLocked(pg))
  11512. + PAGE_BUG(pg);
  11513. +#endif
  11514. +
  11515. + pg_buf = kmap(pg);
  11516. + /* FIXME: Can kmap fail? */
  11517. +
  11518. + yaffs_gross_lock(dev);
  11519. +
  11520. + ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE);
  11521. +
  11522. + yaffs_gross_unlock(dev);
  11523. +
  11524. + if (ret >= 0)
  11525. + ret = 0;
  11526. +
  11527. + if (ret) {
  11528. + ClearPageUptodate(pg);
  11529. + SetPageError(pg);
  11530. + } else {
  11531. + SetPageUptodate(pg);
  11532. + ClearPageError(pg);
  11533. + }
  11534. +
  11535. + flush_dcache_page(pg);
  11536. + kunmap(pg);
  11537. +
  11538. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done");
  11539. + return ret;
  11540. +}
  11541. +
  11542. +static int yaffs_readpage_unlock(struct file *f, struct page *pg)
  11543. +{
  11544. + int ret = yaffs_readpage_nolock(f, pg);
  11545. + UnlockPage(pg);
  11546. + return ret;
  11547. +}
  11548. +
  11549. +static int yaffs_readpage(struct file *f, struct page *pg)
  11550. +{
  11551. + int ret;
  11552. +
  11553. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage");
  11554. + ret = yaffs_readpage_unlock(f, pg);
  11555. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done");
  11556. + return ret;
  11557. +}
  11558. +
  11559. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  11560. +#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
  11561. +#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
  11562. +#else
  11563. +#define YCRED_FSUID() YCRED(current)->fsuid
  11564. +#define YCRED_FSGID() YCRED(current)->fsgid
  11565. +
  11566. +static inline uid_t i_uid_read(const struct inode *inode)
  11567. +{
  11568. + return inode->i_uid;
  11569. +}
  11570. +
  11571. +static inline gid_t i_gid_read(const struct inode *inode)
  11572. +{
  11573. + return inode->i_gid;
  11574. +}
  11575. +
  11576. +static inline void i_uid_write(struct inode *inode, uid_t uid)
  11577. +{
  11578. + inode->i_uid = uid;
  11579. +}
  11580. +
  11581. +static inline void i_gid_write(struct inode *inode, gid_t gid)
  11582. +{
  11583. + inode->i_gid = gid;
  11584. +}
  11585. +#endif
  11586. +
  11587. +static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
  11588. +{
  11589. + struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
  11590. +
  11591. + if (lc)
  11592. + lc->dirty = val;
  11593. +
  11594. +# ifdef YAFFS_SUPER_HAS_DIRTY
  11595. + {
  11596. + struct super_block *sb = lc->super;
  11597. +
  11598. + if (sb)
  11599. + sb->s_dirt = val;
  11600. + }
  11601. +#endif
  11602. +
  11603. +}
  11604. +
  11605. +static void yaffs_set_super_dirty(struct yaffs_dev *dev)
  11606. +{
  11607. + yaffs_set_super_dirty_val(dev, 1);
  11608. +}
  11609. +
  11610. +static void yaffs_clear_super_dirty(struct yaffs_dev *dev)
  11611. +{
  11612. + yaffs_set_super_dirty_val(dev, 0);
  11613. +}
  11614. +
  11615. +static int yaffs_check_super_dirty(struct yaffs_dev *dev)
  11616. +{
  11617. + struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
  11618. +
  11619. + if (lc && lc->dirty)
  11620. + return 1;
  11621. +
  11622. +# ifdef YAFFS_SUPER_HAS_DIRTY
  11623. + {
  11624. + struct super_block *sb = lc->super;
  11625. +
  11626. + if (sb && sb->s_dirt)
  11627. + return 1;
  11628. + }
  11629. +#endif
  11630. + return 0;
  11631. +
  11632. +}
  11633. +
  11634. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  11635. +static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
  11636. +#else
  11637. +static int yaffs_writepage(struct page *page)
  11638. +#endif
  11639. +{
  11640. + struct yaffs_dev *dev;
  11641. + struct address_space *mapping = page->mapping;
  11642. + struct inode *inode;
  11643. + unsigned long end_index;
  11644. + char *buffer;
  11645. + struct yaffs_obj *obj;
  11646. + int n_written = 0;
  11647. + unsigned n_bytes;
  11648. + loff_t i_size;
  11649. +
  11650. + if (!mapping)
  11651. + BUG();
  11652. + inode = mapping->host;
  11653. + if (!inode)
  11654. + BUG();
  11655. + i_size = i_size_read(inode);
  11656. +
  11657. + end_index = i_size >> PAGE_CACHE_SHIFT;
  11658. +
  11659. + if (page->index < end_index)
  11660. + n_bytes = PAGE_CACHE_SIZE;
  11661. + else {
  11662. + n_bytes = i_size & (PAGE_CACHE_SIZE - 1);
  11663. +
  11664. + if (page->index > end_index || !n_bytes) {
  11665. + yaffs_trace(YAFFS_TRACE_OS,
  11666. + "yaffs_writepage at %lld, inode size = %lld!!",
  11667. + ((loff_t)page->index) << PAGE_CACHE_SHIFT,
  11668. + inode->i_size);
  11669. + yaffs_trace(YAFFS_TRACE_OS,
  11670. + " -> don't care!!");
  11671. +
  11672. + zero_user_segment(page, 0, PAGE_CACHE_SIZE);
  11673. + set_page_writeback(page);
  11674. + unlock_page(page);
  11675. + end_page_writeback(page);
  11676. + return 0;
  11677. + }
  11678. + }
  11679. +
  11680. + if (n_bytes != PAGE_CACHE_SIZE)
  11681. + zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE);
  11682. +
  11683. + get_page(page);
  11684. +
  11685. + buffer = kmap(page);
  11686. +
  11687. + obj = yaffs_inode_to_obj(inode);
  11688. + dev = obj->my_dev;
  11689. + yaffs_gross_lock(dev);
  11690. +
  11691. + yaffs_trace(YAFFS_TRACE_OS,
  11692. + "yaffs_writepage at %lld, size %08x",
  11693. + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes);
  11694. + yaffs_trace(YAFFS_TRACE_OS,
  11695. + "writepag0: obj = %lld, ino = %lld",
  11696. + obj->variant.file_variant.file_size, inode->i_size);
  11697. +
  11698. + n_written = yaffs_wr_file(obj, buffer,
  11699. + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0);
  11700. +
  11701. + yaffs_set_super_dirty(dev);
  11702. +
  11703. + yaffs_trace(YAFFS_TRACE_OS,
  11704. + "writepag1: obj = %lld, ino = %lld",
  11705. + obj->variant.file_variant.file_size, inode->i_size);
  11706. +
  11707. + yaffs_gross_unlock(dev);
  11708. +
  11709. + kunmap(page);
  11710. + set_page_writeback(page);
  11711. + unlock_page(page);
  11712. + end_page_writeback(page);
  11713. + put_page(page);
  11714. +
  11715. + return (n_written == n_bytes) ? 0 : -ENOSPC;
  11716. +}
  11717. +
  11718. +/* Space holding and freeing is done to ensure we have space available for write_begin/end */
  11719. +/* For now we just assume few parallel writes and check against a small number. */
  11720. +/* Todo: need to do this with a counter to handle parallel reads better */
  11721. +
  11722. +static ssize_t yaffs_hold_space(struct file *f)
  11723. +{
  11724. + struct yaffs_obj *obj;
  11725. + struct yaffs_dev *dev;
  11726. +
  11727. + int n_free_chunks;
  11728. +
  11729. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11730. +
  11731. + dev = obj->my_dev;
  11732. +
  11733. + yaffs_gross_lock(dev);
  11734. +
  11735. + n_free_chunks = yaffs_get_n_free_chunks(dev);
  11736. +
  11737. + yaffs_gross_unlock(dev);
  11738. +
  11739. + return (n_free_chunks > 20) ? 1 : 0;
  11740. +}
  11741. +
  11742. +static void yaffs_release_space(struct file *f)
  11743. +{
  11744. + struct yaffs_obj *obj;
  11745. + struct yaffs_dev *dev;
  11746. +
  11747. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11748. +
  11749. + dev = obj->my_dev;
  11750. +
  11751. + yaffs_gross_lock(dev);
  11752. +
  11753. + yaffs_gross_unlock(dev);
  11754. +}
  11755. +
  11756. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  11757. +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
  11758. + loff_t pos, unsigned len, unsigned flags,
  11759. + struct page **pagep, void **fsdata)
  11760. +{
  11761. + struct page *pg = NULL;
  11762. + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  11763. +
  11764. + int ret = 0;
  11765. + int space_held = 0;
  11766. +
  11767. + /* Get a page */
  11768. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
  11769. + pg = grab_cache_page_write_begin(mapping, index, flags);
  11770. +#else
  11771. + pg = __grab_cache_page(mapping, index);
  11772. +#endif
  11773. +
  11774. + *pagep = pg;
  11775. + if (!pg) {
  11776. + ret = -ENOMEM;
  11777. + goto out;
  11778. + }
  11779. + yaffs_trace(YAFFS_TRACE_OS,
  11780. + "start yaffs_write_begin index %d(%x) uptodate %d",
  11781. + (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0);
  11782. +
  11783. + /* Get fs space */
  11784. + space_held = yaffs_hold_space(filp);
  11785. +
  11786. + if (!space_held) {
  11787. + ret = -ENOSPC;
  11788. + goto out;
  11789. + }
  11790. +
  11791. + /* Update page if required */
  11792. +
  11793. + if (!Page_Uptodate(pg))
  11794. + ret = yaffs_readpage_nolock(filp, pg);
  11795. +
  11796. + if (ret)
  11797. + goto out;
  11798. +
  11799. + /* Happy path return */
  11800. + yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok");
  11801. +
  11802. + return 0;
  11803. +
  11804. +out:
  11805. + yaffs_trace(YAFFS_TRACE_OS,
  11806. + "end yaffs_write_begin fail returning %d", ret);
  11807. + if (space_held)
  11808. + yaffs_release_space(filp);
  11809. + if (pg) {
  11810. + unlock_page(pg);
  11811. + page_cache_release(pg);
  11812. + }
  11813. + return ret;
  11814. +}
  11815. +
  11816. +#else
  11817. +
  11818. +static int yaffs_prepare_write(struct file *f, struct page *pg,
  11819. + unsigned offset, unsigned to)
  11820. +{
  11821. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write");
  11822. +
  11823. + if (!Page_Uptodate(pg))
  11824. + return yaffs_readpage_nolock(f, pg);
  11825. + return 0;
  11826. +}
  11827. +#endif
  11828. +
  11829. +
  11830. +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
  11831. + loff_t * pos)
  11832. +{
  11833. + struct yaffs_obj *obj;
  11834. + int n_written;
  11835. + loff_t ipos;
  11836. + struct inode *inode;
  11837. + struct yaffs_dev *dev;
  11838. +
  11839. + obj = yaffs_dentry_to_obj(f->f_dentry);
  11840. +
  11841. + if (!obj) {
  11842. + yaffs_trace(YAFFS_TRACE_OS,
  11843. + "yaffs_file_write: hey obj is null!");
  11844. + return -EINVAL;
  11845. + }
  11846. +
  11847. + dev = obj->my_dev;
  11848. +
  11849. + yaffs_gross_lock(dev);
  11850. +
  11851. + inode = f->f_dentry->d_inode;
  11852. +
  11853. + if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
  11854. + ipos = inode->i_size;
  11855. + else
  11856. + ipos = *pos;
  11857. +
  11858. + yaffs_trace(YAFFS_TRACE_OS,
  11859. + "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
  11860. + (unsigned)n, (unsigned)n, obj->obj_id, ipos);
  11861. +
  11862. + n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
  11863. +
  11864. + yaffs_set_super_dirty(dev);
  11865. +
  11866. + yaffs_trace(YAFFS_TRACE_OS,
  11867. + "yaffs_file_write: %d(%x) bytes written",
  11868. + (unsigned)n, (unsigned)n);
  11869. +
  11870. + if (n_written > 0) {
  11871. + ipos += n_written;
  11872. + *pos = ipos;
  11873. + if (ipos > inode->i_size) {
  11874. + inode->i_size = ipos;
  11875. + inode->i_blocks = (ipos + 511) >> 9;
  11876. +
  11877. + yaffs_trace(YAFFS_TRACE_OS,
  11878. + "yaffs_file_write size updated to %lld bytes, %d blocks",
  11879. + ipos, (int)(inode->i_blocks));
  11880. + }
  11881. +
  11882. + }
  11883. + yaffs_gross_unlock(dev);
  11884. + return (n_written == 0) && (n > 0) ? -ENOSPC : n_written;
  11885. +}
  11886. +
  11887. +
  11888. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  11889. +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
  11890. + loff_t pos, unsigned len, unsigned copied,
  11891. + struct page *pg, void *fsdadata)
  11892. +{
  11893. + int ret = 0;
  11894. + void *addr, *kva;
  11895. + uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
  11896. +
  11897. + kva = kmap(pg);
  11898. + addr = kva + offset_into_page;
  11899. +
  11900. + yaffs_trace(YAFFS_TRACE_OS,
  11901. + "yaffs_write_end addr %p pos %lld n_bytes %d",
  11902. + addr, pos, copied);
  11903. +
  11904. + ret = yaffs_file_write(filp, addr, copied, &pos);
  11905. +
  11906. + if (ret != copied) {
  11907. + yaffs_trace(YAFFS_TRACE_OS,
  11908. + "yaffs_write_end not same size ret %d copied %d",
  11909. + ret, copied);
  11910. + SetPageError(pg);
  11911. + }
  11912. +
  11913. + kunmap(pg);
  11914. +
  11915. + yaffs_release_space(filp);
  11916. + unlock_page(pg);
  11917. + page_cache_release(pg);
  11918. + return ret;
  11919. +}
  11920. +#else
  11921. +
  11922. +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
  11923. + unsigned to)
  11924. +{
  11925. + void *addr, *kva;
  11926. +
  11927. + loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
  11928. + int n_bytes = to - offset;
  11929. + int n_written;
  11930. +
  11931. + kva = kmap(pg);
  11932. + addr = kva + offset;
  11933. +
  11934. + yaffs_trace(YAFFS_TRACE_OS,
  11935. + "yaffs_commit_write addr %p pos %lld n_bytes %d",
  11936. + addr, pos, n_bytes);
  11937. +
  11938. + n_written = yaffs_file_write(f, addr, n_bytes, &pos);
  11939. +
  11940. + if (n_written != n_bytes) {
  11941. + yaffs_trace(YAFFS_TRACE_OS,
  11942. + "yaffs_commit_write not same size n_written %d n_bytes %d",
  11943. + n_written, n_bytes);
  11944. + SetPageError(pg);
  11945. + }
  11946. + kunmap(pg);
  11947. +
  11948. + yaffs_trace(YAFFS_TRACE_OS,
  11949. + "yaffs_commit_write returning %d",
  11950. + n_written == n_bytes ? 0 : n_written);
  11951. +
  11952. + return n_written == n_bytes ? 0 : n_written;
  11953. +}
  11954. +#endif
  11955. +
  11956. +static struct address_space_operations yaffs_file_address_operations = {
  11957. + .readpage = yaffs_readpage,
  11958. + .writepage = yaffs_writepage,
  11959. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  11960. + .write_begin = yaffs_write_begin,
  11961. + .write_end = yaffs_write_end,
  11962. +#else
  11963. + .prepare_write = yaffs_prepare_write,
  11964. + .commit_write = yaffs_commit_write,
  11965. +#endif
  11966. +};
  11967. +
  11968. +
  11969. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  11970. +static int yaffs_file_flush(struct file *file, fl_owner_t id)
  11971. +#else
  11972. +static int yaffs_file_flush(struct file *file)
  11973. +#endif
  11974. +{
  11975. + struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
  11976. +
  11977. + struct yaffs_dev *dev = obj->my_dev;
  11978. +
  11979. + yaffs_trace(YAFFS_TRACE_OS,
  11980. + "yaffs_file_flush object %d (%s)",
  11981. + obj->obj_id,
  11982. + obj->dirty ? "dirty" : "clean");
  11983. +
  11984. + yaffs_gross_lock(dev);
  11985. +
  11986. + yaffs_flush_file(obj, 1, 0);
  11987. +
  11988. + yaffs_gross_unlock(dev);
  11989. +
  11990. + return 0;
  11991. +}
  11992. +
  11993. +
  11994. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  11995. +static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync)
  11996. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
  11997. +static int yaffs_sync_object(struct file *file, int datasync)
  11998. +#else
  11999. +static int yaffs_sync_object(struct file *file, struct dentry *dentry,
  12000. + int datasync)
  12001. +#endif
  12002. +{
  12003. + struct yaffs_obj *obj;
  12004. + struct yaffs_dev *dev;
  12005. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
  12006. + struct dentry *dentry = file->f_path.dentry;
  12007. +#endif
  12008. +
  12009. + obj = yaffs_dentry_to_obj(dentry);
  12010. +
  12011. + dev = obj->my_dev;
  12012. +
  12013. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
  12014. + "yaffs_sync_object");
  12015. + yaffs_gross_lock(dev);
  12016. + yaffs_flush_file(obj, 1, datasync);
  12017. + yaffs_gross_unlock(dev);
  12018. + return 0;
  12019. +}
  12020. +
  12021. +
  12022. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
  12023. +static const struct file_operations yaffs_file_operations = {
  12024. + .read = do_sync_read,
  12025. + .write = do_sync_write,
  12026. + .aio_read = generic_file_aio_read,
  12027. + .aio_write = generic_file_aio_write,
  12028. + .mmap = generic_file_mmap,
  12029. + .flush = yaffs_file_flush,
  12030. + .fsync = yaffs_sync_object,
  12031. + .splice_read = generic_file_splice_read,
  12032. + .splice_write = generic_file_splice_write,
  12033. + .llseek = generic_file_llseek,
  12034. +};
  12035. +
  12036. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
  12037. +
  12038. +static const struct file_operations yaffs_file_operations = {
  12039. + .read = do_sync_read,
  12040. + .write = do_sync_write,
  12041. + .aio_read = generic_file_aio_read,
  12042. + .aio_write = generic_file_aio_write,
  12043. + .mmap = generic_file_mmap,
  12044. + .flush = yaffs_file_flush,
  12045. + .fsync = yaffs_sync_object,
  12046. + .sendfile = generic_file_sendfile,
  12047. +};
  12048. +
  12049. +#else
  12050. +
  12051. +static const struct file_operations yaffs_file_operations = {
  12052. + .read = generic_file_read,
  12053. + .write = generic_file_write,
  12054. + .mmap = generic_file_mmap,
  12055. + .flush = yaffs_file_flush,
  12056. + .fsync = yaffs_sync_object,
  12057. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12058. + .sendfile = generic_file_sendfile,
  12059. +#endif
  12060. +};
  12061. +#endif
  12062. +
  12063. +
  12064. +
  12065. +
  12066. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
  12067. +static void zero_user_segment(struct page *page, unsigned start, unsigned end)
  12068. +{
  12069. + void *kaddr = kmap_atomic(page, KM_USER0);
  12070. + memset(kaddr + start, 0, end - start);
  12071. + kunmap_atomic(kaddr, KM_USER0);
  12072. + flush_dcache_page(page);
  12073. +}
  12074. +#endif
  12075. +
  12076. +
  12077. +static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
  12078. +{
  12079. +#ifdef YAFFS_USE_TRUNCATE_SETSIZE
  12080. + truncate_setsize(inode, newsize);
  12081. + return 0;
  12082. +#else
  12083. + truncate_inode_pages(&inode->i_data, newsize);
  12084. + return 0;
  12085. +#endif
  12086. +
  12087. +}
  12088. +
  12089. +
  12090. +static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
  12091. +{
  12092. +#ifdef YAFFS_USE_SETATTR_COPY
  12093. + setattr_copy(inode, attr);
  12094. + return 0;
  12095. +#else
  12096. + return inode_setattr(inode, attr);
  12097. +#endif
  12098. +
  12099. +}
  12100. +
  12101. +static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
  12102. +{
  12103. + struct inode *inode = dentry->d_inode;
  12104. + int error = 0;
  12105. + struct yaffs_dev *dev;
  12106. +
  12107. + yaffs_trace(YAFFS_TRACE_OS,
  12108. + "yaffs_setattr of object %d",
  12109. + yaffs_inode_to_obj(inode)->obj_id);
  12110. +#if 0
  12111. + /* Fail if a requested resize >= 2GB */
  12112. + if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
  12113. + error = -EINVAL;
  12114. +#endif
  12115. +
  12116. + if (error == 0)
  12117. + error = inode_change_ok(inode, attr);
  12118. + if (error == 0) {
  12119. + int result;
  12120. + if (!error) {
  12121. + error = yaffs_vfs_setattr(inode, attr);
  12122. + yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called");
  12123. + if (attr->ia_valid & ATTR_SIZE) {
  12124. + yaffs_vfs_setsize(inode, attr->ia_size);
  12125. + inode->i_blocks = (inode->i_size + 511) >> 9;
  12126. + }
  12127. + }
  12128. + dev = yaffs_inode_to_obj(inode)->my_dev;
  12129. + if (attr->ia_valid & ATTR_SIZE) {
  12130. + yaffs_trace(YAFFS_TRACE_OS,
  12131. + "resize to %d(%x)",
  12132. + (int)(attr->ia_size),
  12133. + (int)(attr->ia_size));
  12134. + }
  12135. + yaffs_gross_lock(dev);
  12136. + result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr);
  12137. + if (result == YAFFS_OK) {
  12138. + error = 0;
  12139. + } else {
  12140. + error = -EPERM;
  12141. + }
  12142. + yaffs_gross_unlock(dev);
  12143. +
  12144. + }
  12145. +
  12146. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error);
  12147. +
  12148. + return error;
  12149. +}
  12150. +
  12151. +static int yaffs_setxattr(struct dentry *dentry, const char *name,
  12152. + const void *value, size_t size, int flags)
  12153. +{
  12154. + struct inode *inode = dentry->d_inode;
  12155. + int error = 0;
  12156. + struct yaffs_dev *dev;
  12157. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  12158. +
  12159. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id);
  12160. +
  12161. + if (error == 0) {
  12162. + int result;
  12163. + dev = obj->my_dev;
  12164. + yaffs_gross_lock(dev);
  12165. + result = yaffs_set_xattrib(obj, name, value, size, flags);
  12166. + if (result == YAFFS_OK)
  12167. + error = 0;
  12168. + else if (result < 0)
  12169. + error = result;
  12170. + yaffs_gross_unlock(dev);
  12171. +
  12172. + }
  12173. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error);
  12174. +
  12175. + return error;
  12176. +}
  12177. +
  12178. +static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name,
  12179. + void *buff, size_t size)
  12180. +{
  12181. + struct inode *inode = dentry->d_inode;
  12182. + int error = 0;
  12183. + struct yaffs_dev *dev;
  12184. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  12185. +
  12186. + yaffs_trace(YAFFS_TRACE_OS,
  12187. + "yaffs_getxattr \"%s\" from object %d",
  12188. + name, obj->obj_id);
  12189. +
  12190. + if (error == 0) {
  12191. + dev = obj->my_dev;
  12192. + yaffs_gross_lock(dev);
  12193. + error = yaffs_get_xattrib(obj, name, buff, size);
  12194. + yaffs_gross_unlock(dev);
  12195. +
  12196. + }
  12197. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error);
  12198. +
  12199. + return error;
  12200. +}
  12201. +
  12202. +static int yaffs_removexattr(struct dentry *dentry, const char *name)
  12203. +{
  12204. + struct inode *inode = dentry->d_inode;
  12205. + int error = 0;
  12206. + struct yaffs_dev *dev;
  12207. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  12208. +
  12209. + yaffs_trace(YAFFS_TRACE_OS,
  12210. + "yaffs_removexattr of object %d", obj->obj_id);
  12211. +
  12212. + if (error == 0) {
  12213. + int result;
  12214. + dev = obj->my_dev;
  12215. + yaffs_gross_lock(dev);
  12216. + result = yaffs_remove_xattrib(obj, name);
  12217. + if (result == YAFFS_OK)
  12218. + error = 0;
  12219. + else if (result < 0)
  12220. + error = result;
  12221. + yaffs_gross_unlock(dev);
  12222. +
  12223. + }
  12224. + yaffs_trace(YAFFS_TRACE_OS,
  12225. + "yaffs_removexattr done returning %d", error);
  12226. +
  12227. + return error;
  12228. +}
  12229. +
  12230. +static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size)
  12231. +{
  12232. + struct inode *inode = dentry->d_inode;
  12233. + int error = 0;
  12234. + struct yaffs_dev *dev;
  12235. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  12236. +
  12237. + yaffs_trace(YAFFS_TRACE_OS,
  12238. + "yaffs_listxattr of object %d", obj->obj_id);
  12239. +
  12240. + if (error == 0) {
  12241. + dev = obj->my_dev;
  12242. + yaffs_gross_lock(dev);
  12243. + error = yaffs_list_xattrib(obj, buff, size);
  12244. + yaffs_gross_unlock(dev);
  12245. +
  12246. + }
  12247. + yaffs_trace(YAFFS_TRACE_OS,
  12248. + "yaffs_listxattr done returning %d", error);
  12249. +
  12250. + return error;
  12251. +}
  12252. +
  12253. +
  12254. +static const struct inode_operations yaffs_file_inode_operations = {
  12255. + .setattr = yaffs_setattr,
  12256. + .setxattr = yaffs_setxattr,
  12257. + .getxattr = yaffs_getxattr,
  12258. + .listxattr = yaffs_listxattr,
  12259. + .removexattr = yaffs_removexattr,
  12260. +};
  12261. +
  12262. +
  12263. +static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
  12264. + int buflen)
  12265. +{
  12266. + unsigned char *alias;
  12267. + int ret;
  12268. +
  12269. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  12270. +
  12271. + yaffs_gross_lock(dev);
  12272. +
  12273. + alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
  12274. +
  12275. + yaffs_gross_unlock(dev);
  12276. +
  12277. + if (!alias)
  12278. + return -ENOMEM;
  12279. +
  12280. + ret = vfs_readlink(dentry, buffer, buflen, alias);
  12281. + kfree(alias);
  12282. + return ret;
  12283. +}
  12284. +
  12285. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  12286. +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
  12287. +{
  12288. + void *ret;
  12289. +#else
  12290. +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
  12291. +{
  12292. + int ret
  12293. +#endif
  12294. + unsigned char *alias;
  12295. + int ret_int = 0;
  12296. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  12297. +
  12298. + yaffs_gross_lock(dev);
  12299. +
  12300. + alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
  12301. + yaffs_gross_unlock(dev);
  12302. +
  12303. + if (!alias) {
  12304. + ret_int = -ENOMEM;
  12305. + goto out;
  12306. + }
  12307. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  12308. + nd_set_link(nd, alias);
  12309. + ret = alias;
  12310. +out:
  12311. + if (ret_int)
  12312. + ret = ERR_PTR(ret_int);
  12313. + return ret;
  12314. +#else
  12315. + ret = vfs_follow_link(nd, alias);
  12316. + kfree(alias);
  12317. +out:
  12318. + if (ret_int)
  12319. + ret = ret_int;
  12320. + return ret;
  12321. +#endif
  12322. +}
  12323. +
  12324. +
  12325. +#ifdef YAFFS_HAS_PUT_INODE
  12326. +
  12327. +/* For now put inode is just for debugging
  12328. + * Put inode is called when the inode **structure** is put.
  12329. + */
  12330. +static void yaffs_put_inode(struct inode *inode)
  12331. +{
  12332. + yaffs_trace(YAFFS_TRACE_OS,
  12333. + "yaffs_put_inode: ino %d, count %d"),
  12334. + (int)inode->i_ino, atomic_read(&inode->i_count);
  12335. +
  12336. +}
  12337. +#endif
  12338. +
  12339. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  12340. +void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias)
  12341. +{
  12342. + kfree(alias);
  12343. +}
  12344. +#endif
  12345. +
  12346. +static const struct inode_operations yaffs_symlink_inode_operations = {
  12347. + .readlink = yaffs_readlink,
  12348. + .follow_link = yaffs_follow_link,
  12349. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  12350. + .put_link = yaffs_put_link,
  12351. +#endif
  12352. + .setattr = yaffs_setattr,
  12353. + .setxattr = yaffs_setxattr,
  12354. + .getxattr = yaffs_getxattr,
  12355. + .listxattr = yaffs_listxattr,
  12356. + .removexattr = yaffs_removexattr,
  12357. +};
  12358. +
  12359. +#ifdef YAFFS_USE_OWN_IGET
  12360. +
  12361. +static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
  12362. +{
  12363. + struct inode *inode;
  12364. + struct yaffs_obj *obj;
  12365. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  12366. +
  12367. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino);
  12368. +
  12369. + inode = iget_locked(sb, ino);
  12370. + if (!inode)
  12371. + return ERR_PTR(-ENOMEM);
  12372. + if (!(inode->i_state & I_NEW))
  12373. + return inode;
  12374. +
  12375. + /* NB This is called as a side effect of other functions, but
  12376. + * we had to release the lock to prevent deadlocks, so
  12377. + * need to lock again.
  12378. + */
  12379. +
  12380. + yaffs_gross_lock(dev);
  12381. +
  12382. + obj = yaffs_find_by_number(dev, inode->i_ino);
  12383. +
  12384. + yaffs_fill_inode_from_obj(inode, obj);
  12385. +
  12386. + yaffs_gross_unlock(dev);
  12387. +
  12388. + unlock_new_inode(inode);
  12389. + return inode;
  12390. +}
  12391. +
  12392. +#else
  12393. +
  12394. +static void yaffs_read_inode(struct inode *inode)
  12395. +{
  12396. + /* NB This is called as a side effect of other functions, but
  12397. + * we had to release the lock to prevent deadlocks, so
  12398. + * need to lock again.
  12399. + */
  12400. +
  12401. + struct yaffs_obj *obj;
  12402. + struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb);
  12403. +
  12404. + yaffs_trace(YAFFS_TRACE_OS,
  12405. + "yaffs_read_inode for %d", (int)inode->i_ino);
  12406. +
  12407. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  12408. + yaffs_gross_lock(dev);
  12409. +
  12410. + obj = yaffs_find_by_number(dev, inode->i_ino);
  12411. +
  12412. + yaffs_fill_inode_from_obj(inode, obj);
  12413. +
  12414. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  12415. + yaffs_gross_unlock(dev);
  12416. +}
  12417. +
  12418. +#endif
  12419. +
  12420. +
  12421. +
  12422. +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
  12423. + struct yaffs_obj *obj)
  12424. +{
  12425. + struct inode *inode;
  12426. +
  12427. + if (!sb) {
  12428. + yaffs_trace(YAFFS_TRACE_OS,
  12429. + "yaffs_get_inode for NULL super_block!!");
  12430. + return NULL;
  12431. +
  12432. + }
  12433. +
  12434. + if (!obj) {
  12435. + yaffs_trace(YAFFS_TRACE_OS,
  12436. + "yaffs_get_inode for NULL object!!");
  12437. + return NULL;
  12438. +
  12439. + }
  12440. +
  12441. + yaffs_trace(YAFFS_TRACE_OS,
  12442. + "yaffs_get_inode for object %d", obj->obj_id);
  12443. +
  12444. + inode = Y_IGET(sb, obj->obj_id);
  12445. + if (IS_ERR(inode))
  12446. + return NULL;
  12447. +
  12448. + /* NB Side effect: iget calls back to yaffs_read_inode(). */
  12449. + /* iget also increments the inode's i_count */
  12450. + /* NB You can't be holding gross_lock or deadlock will happen! */
  12451. +
  12452. + return inode;
  12453. +}
  12454. +
  12455. +
  12456. +
  12457. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
  12458. +#define YCRED(x) x
  12459. +#else
  12460. +#define YCRED(x) (x->cred)
  12461. +#endif
  12462. +
  12463. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  12464. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
  12465. + dev_t rdev)
  12466. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12467. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
  12468. + dev_t rdev)
  12469. +#else
  12470. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
  12471. + int rdev)
  12472. +#endif
  12473. +{
  12474. + struct inode *inode;
  12475. +
  12476. + struct yaffs_obj *obj = NULL;
  12477. + struct yaffs_dev *dev;
  12478. +
  12479. + struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
  12480. +
  12481. + int error = -ENOSPC;
  12482. + uid_t uid = YCRED_FSUID();
  12483. + gid_t gid =
  12484. + (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
  12485. +
  12486. + if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
  12487. + mode |= S_ISGID;
  12488. +
  12489. + if (parent) {
  12490. + yaffs_trace(YAFFS_TRACE_OS,
  12491. + "yaffs_mknod: parent object %d type %d",
  12492. + parent->obj_id, parent->variant_type);
  12493. + } else {
  12494. + yaffs_trace(YAFFS_TRACE_OS,
  12495. + "yaffs_mknod: could not get parent object");
  12496. + return -EPERM;
  12497. + }
  12498. +
  12499. + yaffs_trace(YAFFS_TRACE_OS,
  12500. + "yaffs_mknod: making oject for %s, mode %x dev %x",
  12501. + dentry->d_name.name, mode, rdev);
  12502. +
  12503. + dev = parent->my_dev;
  12504. +
  12505. + yaffs_gross_lock(dev);
  12506. +
  12507. + switch (mode & S_IFMT) {
  12508. + default:
  12509. + /* Special (socket, fifo, device...) */
  12510. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making special");
  12511. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12512. + obj =
  12513. + yaffs_create_special(parent, dentry->d_name.name, mode, uid,
  12514. + gid, old_encode_dev(rdev));
  12515. +#else
  12516. + obj =
  12517. + yaffs_create_special(parent, dentry->d_name.name, mode, uid,
  12518. + gid, rdev);
  12519. +#endif
  12520. + break;
  12521. + case S_IFREG: /* file */
  12522. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making file");
  12523. + obj = yaffs_create_file(parent, dentry->d_name.name, mode, uid,
  12524. + gid);
  12525. + break;
  12526. + case S_IFDIR: /* directory */
  12527. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making directory");
  12528. + obj = yaffs_create_dir(parent, dentry->d_name.name, mode,
  12529. + uid, gid);
  12530. + break;
  12531. + case S_IFLNK: /* symlink */
  12532. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink");
  12533. + obj = NULL; /* Do we ever get here? */
  12534. + break;
  12535. + }
  12536. +
  12537. + /* Can not call yaffs_get_inode() with gross lock held */
  12538. + yaffs_gross_unlock(dev);
  12539. +
  12540. + if (obj) {
  12541. + inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
  12542. + d_instantiate(dentry, inode);
  12543. + update_dir_time(dir);
  12544. + yaffs_trace(YAFFS_TRACE_OS,
  12545. + "yaffs_mknod created object %d count = %d",
  12546. + obj->obj_id, atomic_read(&inode->i_count));
  12547. + error = 0;
  12548. + yaffs_fill_inode_from_obj(dir, parent);
  12549. + } else {
  12550. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object");
  12551. + error = -ENOMEM;
  12552. + }
  12553. +
  12554. + return error;
  12555. +}
  12556. +
  12557. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  12558. +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  12559. +#else
  12560. +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  12561. +#endif
  12562. +{
  12563. + int ret_val;
  12564. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir");
  12565. + ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
  12566. + return ret_val;
  12567. +}
  12568. +
  12569. +
  12570. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  12571. +static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  12572. + bool dummy)
  12573. +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  12574. +static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  12575. + struct nameidata *n)
  12576. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12577. +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
  12578. + struct nameidata *n)
  12579. +#else
  12580. +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
  12581. +#endif
  12582. +{
  12583. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_create");
  12584. + return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
  12585. +}
  12586. +
  12587. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  12588. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
  12589. + unsigned int dummy)
  12590. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  12591. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
  12592. + struct nameidata *n)
  12593. +#else
  12594. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
  12595. +#endif
  12596. +{
  12597. + struct yaffs_obj *obj;
  12598. + struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */
  12599. +
  12600. + struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev;
  12601. +
  12602. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  12603. + yaffs_gross_lock(dev);
  12604. +
  12605. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s",
  12606. + yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name);
  12607. +
  12608. + obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name);
  12609. +
  12610. + obj = yaffs_get_equivalent_obj(obj); /* in case it was a hardlink */
  12611. +
  12612. + /* Can't hold gross lock when calling yaffs_get_inode() */
  12613. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  12614. + yaffs_gross_unlock(dev);
  12615. +
  12616. + if (obj) {
  12617. + yaffs_trace(YAFFS_TRACE_OS,
  12618. + "yaffs_lookup found %d", obj->obj_id);
  12619. +
  12620. + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
  12621. + } else {
  12622. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found");
  12623. +
  12624. + }
  12625. +
  12626. +/* added NCB for 2.5/6 compatability - forces add even if inode is
  12627. + * NULL which creates dentry hash */
  12628. + d_add(dentry, inode);
  12629. +
  12630. + return NULL;
  12631. +}
  12632. +
  12633. +/*
  12634. + * Create a link...
  12635. + */
  12636. +static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
  12637. + struct dentry *dentry)
  12638. +{
  12639. + struct inode *inode = old_dentry->d_inode;
  12640. + struct yaffs_obj *obj = NULL;
  12641. + struct yaffs_obj *link = NULL;
  12642. + struct yaffs_dev *dev;
  12643. +
  12644. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_link");
  12645. +
  12646. + obj = yaffs_inode_to_obj(inode);
  12647. + dev = obj->my_dev;
  12648. +
  12649. + yaffs_gross_lock(dev);
  12650. +
  12651. + if (!S_ISDIR(inode->i_mode)) /* Don't link directories */
  12652. + link =
  12653. + yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name,
  12654. + obj);
  12655. +
  12656. + if (link) {
  12657. + set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj));
  12658. + d_instantiate(dentry, old_dentry->d_inode);
  12659. + atomic_inc(&old_dentry->d_inode->i_count);
  12660. + yaffs_trace(YAFFS_TRACE_OS,
  12661. + "yaffs_link link count %d i_count %d",
  12662. + old_dentry->d_inode->i_nlink,
  12663. + atomic_read(&old_dentry->d_inode->i_count));
  12664. + }
  12665. +
  12666. + yaffs_gross_unlock(dev);
  12667. +
  12668. + if (link) {
  12669. + update_dir_time(dir);
  12670. + return 0;
  12671. + }
  12672. +
  12673. + return -EPERM;
  12674. +}
  12675. +
  12676. +static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
  12677. + const char *symname)
  12678. +{
  12679. + struct yaffs_obj *obj;
  12680. + struct yaffs_dev *dev;
  12681. + uid_t uid = YCRED_FSUID();
  12682. + gid_t gid =
  12683. + (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
  12684. +
  12685. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
  12686. +
  12687. + if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) >
  12688. + YAFFS_MAX_NAME_LENGTH)
  12689. + return -ENAMETOOLONG;
  12690. +
  12691. + if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) >
  12692. + YAFFS_MAX_ALIAS_LENGTH)
  12693. + return -ENAMETOOLONG;
  12694. +
  12695. + dev = yaffs_inode_to_obj(dir)->my_dev;
  12696. + yaffs_gross_lock(dev);
  12697. + obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name,
  12698. + S_IFLNK | S_IRWXUGO, uid, gid, symname);
  12699. + yaffs_gross_unlock(dev);
  12700. +
  12701. + if (obj) {
  12702. + struct inode *inode;
  12703. +
  12704. + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
  12705. + d_instantiate(dentry, inode);
  12706. + update_dir_time(dir);
  12707. + yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
  12708. + return 0;
  12709. + } else {
  12710. + yaffs_trace(YAFFS_TRACE_OS, "symlink not created");
  12711. + }
  12712. +
  12713. + return -ENOMEM;
  12714. +}
  12715. +
  12716. +/*
  12717. + * The VFS layer already does all the dentry stuff for rename.
  12718. + *
  12719. + * NB: POSIX says you can rename an object over an old object of the same name
  12720. + */
  12721. +static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
  12722. + struct inode *new_dir, struct dentry *new_dentry)
  12723. +{
  12724. + struct yaffs_dev *dev;
  12725. + int ret_val = YAFFS_FAIL;
  12726. + struct yaffs_obj *target;
  12727. +
  12728. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename");
  12729. + dev = yaffs_inode_to_obj(old_dir)->my_dev;
  12730. +
  12731. + yaffs_gross_lock(dev);
  12732. +
  12733. + /* Check if the target is an existing directory that is not empty. */
  12734. + target = yaffs_find_by_name(yaffs_inode_to_obj(new_dir),
  12735. + new_dentry->d_name.name);
  12736. +
  12737. + if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
  12738. + !list_empty(&target->variant.dir_variant.children)) {
  12739. +
  12740. + yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir");
  12741. +
  12742. + ret_val = YAFFS_FAIL;
  12743. + } else {
  12744. + /* Now does unlinking internally using shadowing mechanism */
  12745. + yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj");
  12746. +
  12747. + ret_val = yaffs_rename_obj(yaffs_inode_to_obj(old_dir),
  12748. + old_dentry->d_name.name,
  12749. + yaffs_inode_to_obj(new_dir),
  12750. + new_dentry->d_name.name);
  12751. + }
  12752. + yaffs_gross_unlock(dev);
  12753. +
  12754. + if (ret_val == YAFFS_OK) {
  12755. + if (target)
  12756. + inode_dec_link_count(new_dentry->d_inode);
  12757. +
  12758. + update_dir_time(old_dir);
  12759. + if (old_dir != new_dir)
  12760. + update_dir_time(new_dir);
  12761. + return 0;
  12762. + } else {
  12763. + return -ENOTEMPTY;
  12764. + }
  12765. +}
  12766. +
  12767. +
  12768. +
  12769. +
  12770. +static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
  12771. +{
  12772. + int ret_val;
  12773. +
  12774. + struct yaffs_dev *dev;
  12775. + struct yaffs_obj *obj;
  12776. +
  12777. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_unlink %d:%s",
  12778. + (int)(dir->i_ino), dentry->d_name.name);
  12779. + obj = yaffs_inode_to_obj(dir);
  12780. + dev = obj->my_dev;
  12781. +
  12782. + yaffs_gross_lock(dev);
  12783. +
  12784. + ret_val = yaffs_unlinker(obj, dentry->d_name.name);
  12785. +
  12786. + if (ret_val == YAFFS_OK) {
  12787. + inode_dec_link_count(dentry->d_inode);
  12788. + dir->i_version++;
  12789. + yaffs_gross_unlock(dev);
  12790. + update_dir_time(dir);
  12791. + return 0;
  12792. + }
  12793. + yaffs_gross_unlock(dev);
  12794. + return -ENOTEMPTY;
  12795. +}
  12796. +
  12797. +
  12798. +
  12799. +static const struct inode_operations yaffs_dir_inode_operations = {
  12800. + .create = yaffs_create,
  12801. + .lookup = yaffs_lookup,
  12802. + .link = yaffs_link,
  12803. + .unlink = yaffs_unlink,
  12804. + .symlink = yaffs_symlink,
  12805. + .mkdir = yaffs_mkdir,
  12806. + .rmdir = yaffs_unlink,
  12807. + .mknod = yaffs_mknod,
  12808. + .rename = yaffs_rename,
  12809. + .setattr = yaffs_setattr,
  12810. + .setxattr = yaffs_setxattr,
  12811. + .getxattr = yaffs_getxattr,
  12812. + .listxattr = yaffs_listxattr,
  12813. + .removexattr = yaffs_removexattr,
  12814. +};
  12815. +
  12816. +/*-----------------------------------------------------------------*/
  12817. +/* Directory search context allows us to unlock access to yaffs during
  12818. + * filldir without causing problems with the directory being modified.
  12819. + * This is similar to the tried and tested mechanism used in yaffs direct.
  12820. + *
  12821. + * A search context iterates along a doubly linked list of siblings in the
  12822. + * directory. If the iterating object is deleted then this would corrupt
  12823. + * the list iteration, likely causing a crash. The search context avoids
  12824. + * this by using the remove_obj_fn to move the search context to the
  12825. + * next object before the object is deleted.
  12826. + *
  12827. + * Many readdirs (and thus seach conexts) may be alive simulateously so
  12828. + * each struct yaffs_dev has a list of these.
  12829. + *
  12830. + * A seach context lives for the duration of a readdir.
  12831. + *
  12832. + * All these functions must be called while yaffs is locked.
  12833. + */
  12834. +
  12835. +struct yaffs_search_context {
  12836. + struct yaffs_dev *dev;
  12837. + struct yaffs_obj *dir_obj;
  12838. + struct yaffs_obj *next_return;
  12839. + struct list_head others;
  12840. +};
  12841. +
  12842. +/*
  12843. + * yaffs_new_search() creates a new search context, initialises it and
  12844. + * adds it to the device's search context list.
  12845. + *
  12846. + * Called at start of readdir.
  12847. + */
  12848. +static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir)
  12849. +{
  12850. + struct yaffs_dev *dev = dir->my_dev;
  12851. + struct yaffs_search_context *sc =
  12852. + kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS);
  12853. + if (sc) {
  12854. + sc->dir_obj = dir;
  12855. + sc->dev = dev;
  12856. + if (list_empty(&sc->dir_obj->variant.dir_variant.children))
  12857. + sc->next_return = NULL;
  12858. + else
  12859. + sc->next_return =
  12860. + list_entry(dir->variant.dir_variant.children.next,
  12861. + struct yaffs_obj, siblings);
  12862. + INIT_LIST_HEAD(&sc->others);
  12863. + list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts));
  12864. + }
  12865. + return sc;
  12866. +}
  12867. +
  12868. +/*
  12869. + * yaffs_search_end() disposes of a search context and cleans up.
  12870. + */
  12871. +static void yaffs_search_end(struct yaffs_search_context *sc)
  12872. +{
  12873. + if (sc) {
  12874. + list_del(&sc->others);
  12875. + kfree(sc);
  12876. + }
  12877. +}
  12878. +
  12879. +/*
  12880. + * yaffs_search_advance() moves a search context to the next object.
  12881. + * Called when the search iterates or when an object removal causes
  12882. + * the search context to be moved to the next object.
  12883. + */
  12884. +static void yaffs_search_advance(struct yaffs_search_context *sc)
  12885. +{
  12886. + if (!sc)
  12887. + return;
  12888. +
  12889. + if (sc->next_return == NULL ||
  12890. + list_empty(&sc->dir_obj->variant.dir_variant.children))
  12891. + sc->next_return = NULL;
  12892. + else {
  12893. + struct list_head *next = sc->next_return->siblings.next;
  12894. +
  12895. + if (next == &sc->dir_obj->variant.dir_variant.children)
  12896. + sc->next_return = NULL; /* end of list */
  12897. + else
  12898. + sc->next_return =
  12899. + list_entry(next, struct yaffs_obj, siblings);
  12900. + }
  12901. +}
  12902. +
  12903. +/*
  12904. + * yaffs_remove_obj_callback() is called when an object is unlinked.
  12905. + * We check open search contexts and advance any which are currently
  12906. + * on the object being iterated.
  12907. + */
  12908. +static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
  12909. +{
  12910. +
  12911. + struct list_head *i;
  12912. + struct yaffs_search_context *sc;
  12913. + struct list_head *search_contexts =
  12914. + &(yaffs_dev_to_lc(obj->my_dev)->search_contexts);
  12915. +
  12916. + /* Iterate through the directory search contexts.
  12917. + * If any are currently on the object being removed, then advance
  12918. + * the search context to the next object to prevent a hanging pointer.
  12919. + */
  12920. + list_for_each(i, search_contexts) {
  12921. + sc = list_entry(i, struct yaffs_search_context, others);
  12922. + if (sc->next_return == obj)
  12923. + yaffs_search_advance(sc);
  12924. + }
  12925. +
  12926. +}
  12927. +
  12928. +
  12929. +/*-----------------------------------------------------------------*/
  12930. +
  12931. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  12932. +static int yaffs_readdir(struct file *file, struct dir_context *ctx)
  12933. +{
  12934. + struct yaffs_obj *obj;
  12935. + struct yaffs_dev *dev;
  12936. + struct yaffs_search_context *sc;
  12937. + struct inode *inode = file->f_dentry->d_inode;
  12938. + unsigned long offset, curoffs;
  12939. + struct yaffs_obj *l;
  12940. + int ret_val = 0;
  12941. +
  12942. + char name[YAFFS_MAX_NAME_LENGTH + 1];
  12943. +
  12944. + obj = yaffs_dentry_to_obj(file->f_dentry);
  12945. + dev = obj->my_dev;
  12946. +
  12947. + yaffs_gross_lock(dev);
  12948. +
  12949. + yaffs_dev_to_lc(dev)->readdir_process = current;
  12950. +
  12951. + offset = ctx->pos;
  12952. +
  12953. + sc = yaffs_new_search(obj);
  12954. + if (!sc) {
  12955. + ret_val = -ENOMEM;
  12956. + goto out;
  12957. + }
  12958. +
  12959. + yaffs_trace(YAFFS_TRACE_OS,
  12960. + "yaffs_readdir: starting at %d", (int)offset);
  12961. +
  12962. + if (offset == 0) {
  12963. + yaffs_trace(YAFFS_TRACE_OS,
  12964. + "yaffs_readdir: entry . ino %d",
  12965. + (int)inode->i_ino);
  12966. + yaffs_gross_unlock(dev);
  12967. + if (!dir_emit_dot(file, ctx)) {
  12968. + yaffs_gross_lock(dev);
  12969. + goto out;
  12970. + }
  12971. + yaffs_gross_lock(dev);
  12972. + offset++;
  12973. + ctx->pos++;
  12974. + }
  12975. + if (offset == 1) {
  12976. + yaffs_trace(YAFFS_TRACE_OS,
  12977. + "yaffs_readdir: entry .. ino %d",
  12978. + (int)file->f_dentry->d_parent->d_inode->i_ino);
  12979. + yaffs_gross_unlock(dev);
  12980. + if (!dir_emit_dotdot(file, ctx)) {
  12981. + yaffs_gross_lock(dev);
  12982. + goto out;
  12983. + }
  12984. + yaffs_gross_lock(dev);
  12985. + offset++;
  12986. + ctx->pos++;
  12987. + }
  12988. +
  12989. + curoffs = 1;
  12990. +
  12991. + /* If the directory has changed since the open or last call to
  12992. + readdir, rewind to after the 2 canned entries. */
  12993. + if (file->f_version != inode->i_version) {
  12994. + offset = 2;
  12995. + ctx->pos = offset;
  12996. + file->f_version = inode->i_version;
  12997. + }
  12998. +
  12999. + while (sc->next_return) {
  13000. + curoffs++;
  13001. + l = sc->next_return;
  13002. + if (curoffs >= offset) {
  13003. + int this_inode = yaffs_get_obj_inode(l);
  13004. + int this_type = yaffs_get_obj_type(l);
  13005. +
  13006. + yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
  13007. + yaffs_trace(YAFFS_TRACE_OS,
  13008. + "yaffs_readdir: %s inode %d",
  13009. + name, yaffs_get_obj_inode(l));
  13010. +
  13011. + yaffs_gross_unlock(dev);
  13012. +
  13013. + if (!dir_emit(ctx, name, strlen(name),
  13014. + this_inode, this_type) < 0) {
  13015. + yaffs_gross_lock(dev);
  13016. + goto out;
  13017. + }
  13018. +
  13019. + yaffs_gross_lock(dev);
  13020. +
  13021. + offset++;
  13022. + ctx->pos++;
  13023. + }
  13024. + yaffs_search_advance(sc);
  13025. + }
  13026. +
  13027. +out:
  13028. + yaffs_search_end(sc);
  13029. + yaffs_dev_to_lc(dev)->readdir_process = NULL;
  13030. + yaffs_gross_unlock(dev);
  13031. +
  13032. + return ret_val;
  13033. +}
  13034. +#else
  13035. +static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
  13036. +{
  13037. + struct yaffs_obj *obj;
  13038. + struct yaffs_dev *dev;
  13039. + struct yaffs_search_context *sc;
  13040. + struct inode *inode = f->f_dentry->d_inode;
  13041. + unsigned long offset, curoffs;
  13042. + struct yaffs_obj *l;
  13043. + int ret_val = 0;
  13044. +
  13045. + char name[YAFFS_MAX_NAME_LENGTH + 1];
  13046. +
  13047. + obj = yaffs_dentry_to_obj(f->f_dentry);
  13048. + dev = obj->my_dev;
  13049. +
  13050. + yaffs_gross_lock(dev);
  13051. +
  13052. + yaffs_dev_to_lc(dev)->readdir_process = current;
  13053. +
  13054. + offset = f->f_pos;
  13055. +
  13056. + sc = yaffs_new_search(obj);
  13057. + if (!sc) {
  13058. + ret_val = -ENOMEM;
  13059. + goto out;
  13060. + }
  13061. +
  13062. + yaffs_trace(YAFFS_TRACE_OS,
  13063. + "yaffs_readdir: starting at %d", (int)offset);
  13064. +
  13065. + if (offset == 0) {
  13066. + yaffs_trace(YAFFS_TRACE_OS,
  13067. + "yaffs_readdir: entry . ino %d",
  13068. + (int)inode->i_ino);
  13069. + yaffs_gross_unlock(dev);
  13070. + if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) {
  13071. + yaffs_gross_lock(dev);
  13072. + goto out;
  13073. + }
  13074. + yaffs_gross_lock(dev);
  13075. + offset++;
  13076. + f->f_pos++;
  13077. + }
  13078. + if (offset == 1) {
  13079. + yaffs_trace(YAFFS_TRACE_OS,
  13080. + "yaffs_readdir: entry .. ino %d",
  13081. + (int)f->f_dentry->d_parent->d_inode->i_ino);
  13082. + yaffs_gross_unlock(dev);
  13083. + if (filldir(dirent, "..", 2, offset,
  13084. + f->f_dentry->d_parent->d_inode->i_ino,
  13085. + DT_DIR) < 0) {
  13086. + yaffs_gross_lock(dev);
  13087. + goto out;
  13088. + }
  13089. + yaffs_gross_lock(dev);
  13090. + offset++;
  13091. + f->f_pos++;
  13092. + }
  13093. +
  13094. + curoffs = 1;
  13095. +
  13096. + /* If the directory has changed since the open or last call to
  13097. + readdir, rewind to after the 2 canned entries. */
  13098. + if (f->f_version != inode->i_version) {
  13099. + offset = 2;
  13100. + f->f_pos = offset;
  13101. + f->f_version = inode->i_version;
  13102. + }
  13103. +
  13104. + while (sc->next_return) {
  13105. + curoffs++;
  13106. + l = sc->next_return;
  13107. + if (curoffs >= offset) {
  13108. + int this_inode = yaffs_get_obj_inode(l);
  13109. + int this_type = yaffs_get_obj_type(l);
  13110. +
  13111. + yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
  13112. + yaffs_trace(YAFFS_TRACE_OS,
  13113. + "yaffs_readdir: %s inode %d",
  13114. + name, yaffs_get_obj_inode(l));
  13115. +
  13116. + yaffs_gross_unlock(dev);
  13117. +
  13118. + if (filldir(dirent,
  13119. + name,
  13120. + strlen(name),
  13121. + offset, this_inode, this_type) < 0) {
  13122. + yaffs_gross_lock(dev);
  13123. + goto out;
  13124. + }
  13125. +
  13126. + yaffs_gross_lock(dev);
  13127. +
  13128. + offset++;
  13129. + f->f_pos++;
  13130. + }
  13131. + yaffs_search_advance(sc);
  13132. + }
  13133. +
  13134. +out:
  13135. + yaffs_search_end(sc);
  13136. + yaffs_dev_to_lc(dev)->readdir_process = NULL;
  13137. + yaffs_gross_unlock(dev);
  13138. +
  13139. + return ret_val;
  13140. +}
  13141. +#endif
  13142. +
  13143. +static const struct file_operations yaffs_dir_operations = {
  13144. + .read = generic_read_dir,
  13145. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  13146. + .iterate = yaffs_readdir,
  13147. +#else
  13148. + .readdir = yaffs_readdir,
  13149. +#endif
  13150. + .fsync = yaffs_sync_object,
  13151. + .llseek = generic_file_llseek,
  13152. +};
  13153. +
  13154. +static void yaffs_fill_inode_from_obj(struct inode *inode,
  13155. + struct yaffs_obj *obj)
  13156. +{
  13157. + if (inode && obj) {
  13158. +
  13159. + /* Check mode against the variant type and attempt to repair if broken. */
  13160. + u32 mode = obj->yst_mode;
  13161. + switch (obj->variant_type) {
  13162. + case YAFFS_OBJECT_TYPE_FILE:
  13163. + if (!S_ISREG(mode)) {
  13164. + obj->yst_mode &= ~S_IFMT;
  13165. + obj->yst_mode |= S_IFREG;
  13166. + }
  13167. +
  13168. + break;
  13169. + case YAFFS_OBJECT_TYPE_SYMLINK:
  13170. + if (!S_ISLNK(mode)) {
  13171. + obj->yst_mode &= ~S_IFMT;
  13172. + obj->yst_mode |= S_IFLNK;
  13173. + }
  13174. +
  13175. + break;
  13176. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  13177. + if (!S_ISDIR(mode)) {
  13178. + obj->yst_mode &= ~S_IFMT;
  13179. + obj->yst_mode |= S_IFDIR;
  13180. + }
  13181. +
  13182. + break;
  13183. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  13184. + case YAFFS_OBJECT_TYPE_HARDLINK:
  13185. + case YAFFS_OBJECT_TYPE_SPECIAL:
  13186. + default:
  13187. + /* TODO? */
  13188. + break;
  13189. + }
  13190. +
  13191. + inode->i_flags |= S_NOATIME;
  13192. +
  13193. + inode->i_ino = obj->obj_id;
  13194. + inode->i_mode = obj->yst_mode;
  13195. + i_uid_write(inode, obj->yst_uid);
  13196. + i_gid_write(inode, obj->yst_gid);
  13197. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  13198. + inode->i_blksize = inode->i_sb->s_blocksize;
  13199. +#endif
  13200. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  13201. +
  13202. + inode->i_rdev = old_decode_dev(obj->yst_rdev);
  13203. + inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
  13204. + inode->i_atime.tv_nsec = 0;
  13205. + inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
  13206. + inode->i_mtime.tv_nsec = 0;
  13207. + inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
  13208. + inode->i_ctime.tv_nsec = 0;
  13209. +#else
  13210. + inode->i_rdev = obj->yst_rdev;
  13211. + inode->i_atime = obj->yst_atime;
  13212. + inode->i_mtime = obj->yst_mtime;
  13213. + inode->i_ctime = obj->yst_ctime;
  13214. +#endif
  13215. + inode->i_size = yaffs_get_obj_length(obj);
  13216. + inode->i_blocks = (inode->i_size + 511) >> 9;
  13217. +
  13218. + set_nlink(inode, yaffs_get_obj_link_count(obj));
  13219. +
  13220. + yaffs_trace(YAFFS_TRACE_OS,
  13221. + "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
  13222. + inode->i_mode, i_uid_read(inode), i_gid_read(inode),
  13223. + inode->i_size, atomic_read(&inode->i_count));
  13224. +
  13225. + switch (obj->yst_mode & S_IFMT) {
  13226. + default: /* fifo, device or socket */
  13227. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  13228. + init_special_inode(inode, obj->yst_mode,
  13229. + old_decode_dev(obj->yst_rdev));
  13230. +#else
  13231. + init_special_inode(inode, obj->yst_mode,
  13232. + (dev_t) (obj->yst_rdev));
  13233. +#endif
  13234. + break;
  13235. + case S_IFREG: /* file */
  13236. + inode->i_op = &yaffs_file_inode_operations;
  13237. + inode->i_fop = &yaffs_file_operations;
  13238. + inode->i_mapping->a_ops =
  13239. + &yaffs_file_address_operations;
  13240. + break;
  13241. + case S_IFDIR: /* directory */
  13242. + inode->i_op = &yaffs_dir_inode_operations;
  13243. + inode->i_fop = &yaffs_dir_operations;
  13244. + break;
  13245. + case S_IFLNK: /* symlink */
  13246. + inode->i_op = &yaffs_symlink_inode_operations;
  13247. + break;
  13248. + }
  13249. +
  13250. + yaffs_inode_to_obj_lv(inode) = obj;
  13251. +
  13252. + obj->my_inode = inode;
  13253. +
  13254. + } else {
  13255. + yaffs_trace(YAFFS_TRACE_OS,
  13256. + "yaffs_fill_inode invalid parameters");
  13257. + }
  13258. +
  13259. +}
  13260. +
  13261. +
  13262. +
  13263. +/*
  13264. + * yaffs background thread functions .
  13265. + * yaffs_bg_thread_fn() the thread function
  13266. + * yaffs_bg_start() launches the background thread.
  13267. + * yaffs_bg_stop() cleans up the background thread.
  13268. + *
  13269. + * NB:
  13270. + * The thread should only run after the yaffs is initialised
  13271. + * The thread should be stopped before yaffs is unmounted.
  13272. + * The thread should not do any writing while the fs is in read only.
  13273. + */
  13274. +
  13275. +static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
  13276. +{
  13277. + unsigned erased_chunks =
  13278. + dev->n_erased_blocks * dev->param.chunks_per_block;
  13279. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  13280. + unsigned scattered = 0; /* Free chunks not in an erased block */
  13281. +
  13282. + if (erased_chunks < dev->n_free_chunks)
  13283. + scattered = (dev->n_free_chunks - erased_chunks);
  13284. +
  13285. + if (!context->bg_running)
  13286. + return 0;
  13287. + else if (scattered < (dev->param.chunks_per_block * 2))
  13288. + return 0;
  13289. + else if (erased_chunks > dev->n_free_chunks / 2)
  13290. + return 0;
  13291. + else if (erased_chunks > dev->n_free_chunks / 4)
  13292. + return 1;
  13293. + else
  13294. + return 2;
  13295. +}
  13296. +
  13297. +#ifdef YAFFS_COMPILE_BACKGROUND
  13298. +
  13299. +void yaffs_background_waker(unsigned long data)
  13300. +{
  13301. + wake_up_process((struct task_struct *)data);
  13302. +}
  13303. +
  13304. +static int yaffs_bg_thread_fn(void *data)
  13305. +{
  13306. + struct yaffs_dev *dev = (struct yaffs_dev *)data;
  13307. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  13308. + unsigned long now = jiffies;
  13309. + unsigned long next_dir_update = now;
  13310. + unsigned long next_gc = now;
  13311. + unsigned long expires;
  13312. + unsigned int urgency;
  13313. +
  13314. + int gc_result;
  13315. + struct timer_list timer;
  13316. +
  13317. + yaffs_trace(YAFFS_TRACE_BACKGROUND,
  13318. + "yaffs_background starting for dev %p", (void *)dev);
  13319. +
  13320. +#ifdef YAFFS_COMPILE_FREEZER
  13321. + set_freezable();
  13322. +#endif
  13323. + while (context->bg_running) {
  13324. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background");
  13325. +
  13326. + if (kthread_should_stop())
  13327. + break;
  13328. +
  13329. +#ifdef YAFFS_COMPILE_FREEZER
  13330. + if (try_to_freeze())
  13331. + continue;
  13332. +#endif
  13333. + yaffs_gross_lock(dev);
  13334. +
  13335. + now = jiffies;
  13336. +
  13337. + if (time_after(now, next_dir_update) && yaffs_bg_enable) {
  13338. + yaffs_update_dirty_dirs(dev);
  13339. + next_dir_update = now + HZ;
  13340. + }
  13341. +
  13342. + if (time_after(now, next_gc) && yaffs_bg_enable) {
  13343. + if (!dev->is_checkpointed) {
  13344. + urgency = yaffs_bg_gc_urgency(dev);
  13345. + gc_result = yaffs_bg_gc(dev, urgency);
  13346. + if (urgency > 1)
  13347. + next_gc = now + HZ / 20 + 1;
  13348. + else if (urgency > 0)
  13349. + next_gc = now + HZ / 10 + 1;
  13350. + else
  13351. + next_gc = now + HZ * 2;
  13352. + } else {
  13353. + /*
  13354. + * gc not running so set to next_dir_update
  13355. + * to cut down on wake ups
  13356. + */
  13357. + next_gc = next_dir_update;
  13358. + }
  13359. + }
  13360. + yaffs_gross_unlock(dev);
  13361. +#if 1
  13362. + expires = next_dir_update;
  13363. + if (time_before(next_gc, expires))
  13364. + expires = next_gc;
  13365. + if (time_before(expires, now))
  13366. + expires = now + HZ;
  13367. +
  13368. + Y_INIT_TIMER(&timer);
  13369. + timer.expires = expires + 1;
  13370. + timer.data = (unsigned long)current;
  13371. + timer.function = yaffs_background_waker;
  13372. +
  13373. + set_current_state(TASK_INTERRUPTIBLE);
  13374. + add_timer(&timer);
  13375. + schedule();
  13376. + del_timer_sync(&timer);
  13377. +#else
  13378. + msleep(10);
  13379. +#endif
  13380. + }
  13381. +
  13382. + return 0;
  13383. +}
  13384. +
  13385. +static int yaffs_bg_start(struct yaffs_dev *dev)
  13386. +{
  13387. + int retval = 0;
  13388. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  13389. +
  13390. + if (dev->read_only)
  13391. + return -1;
  13392. +
  13393. + context->bg_running = 1;
  13394. +
  13395. + context->bg_thread = kthread_run(yaffs_bg_thread_fn,
  13396. + (void *)dev, "yaffs-bg-%d",
  13397. + context->mount_id);
  13398. +
  13399. + if (IS_ERR(context->bg_thread)) {
  13400. + retval = PTR_ERR(context->bg_thread);
  13401. + context->bg_thread = NULL;
  13402. + context->bg_running = 0;
  13403. + }
  13404. + return retval;
  13405. +}
  13406. +
  13407. +static void yaffs_bg_stop(struct yaffs_dev *dev)
  13408. +{
  13409. + struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev);
  13410. +
  13411. + ctxt->bg_running = 0;
  13412. +
  13413. + if (ctxt->bg_thread) {
  13414. + kthread_stop(ctxt->bg_thread);
  13415. + ctxt->bg_thread = NULL;
  13416. + }
  13417. +}
  13418. +#else
  13419. +static int yaffs_bg_thread_fn(void *data)
  13420. +{
  13421. + return 0;
  13422. +}
  13423. +
  13424. +static int yaffs_bg_start(struct yaffs_dev *dev)
  13425. +{
  13426. + return 0;
  13427. +}
  13428. +
  13429. +static void yaffs_bg_stop(struct yaffs_dev *dev)
  13430. +{
  13431. +}
  13432. +#endif
  13433. +
  13434. +
  13435. +static void yaffs_flush_inodes(struct super_block *sb)
  13436. +{
  13437. + struct inode *iptr;
  13438. + struct yaffs_obj *obj;
  13439. +
  13440. + list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
  13441. + obj = yaffs_inode_to_obj(iptr);
  13442. + if (obj) {
  13443. + yaffs_trace(YAFFS_TRACE_OS,
  13444. + "flushing obj %d",
  13445. + obj->obj_id);
  13446. + yaffs_flush_file(obj, 1, 0);
  13447. + }
  13448. + }
  13449. +}
  13450. +
  13451. +static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
  13452. +{
  13453. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13454. + if (!dev)
  13455. + return;
  13456. +
  13457. + yaffs_flush_inodes(sb);
  13458. + yaffs_update_dirty_dirs(dev);
  13459. + yaffs_flush_whole_cache(dev);
  13460. + if (do_checkpoint)
  13461. + yaffs_checkpoint_save(dev);
  13462. +}
  13463. +
  13464. +static LIST_HEAD(yaffs_context_list);
  13465. +struct mutex yaffs_context_lock;
  13466. +
  13467. +static void yaffs_put_super(struct super_block *sb)
  13468. +{
  13469. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13470. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  13471. +
  13472. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
  13473. + "yaffs_put_super");
  13474. +
  13475. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
  13476. + "Shutting down yaffs background thread");
  13477. + yaffs_bg_stop(dev);
  13478. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
  13479. + "yaffs background thread shut down");
  13480. +
  13481. + yaffs_gross_lock(dev);
  13482. +
  13483. + yaffs_flush_super(sb, 1);
  13484. +
  13485. + yaffs_deinitialise(dev);
  13486. +
  13487. + yaffs_gross_unlock(dev);
  13488. +
  13489. + mutex_lock(&yaffs_context_lock);
  13490. + list_del_init(&(yaffs_dev_to_lc(dev)->context_list));
  13491. + mutex_unlock(&yaffs_context_lock);
  13492. +
  13493. + if (yaffs_dev_to_lc(dev)->spare_buffer) {
  13494. + kfree(yaffs_dev_to_lc(dev)->spare_buffer);
  13495. + yaffs_dev_to_lc(dev)->spare_buffer = NULL;
  13496. + }
  13497. +
  13498. + kfree(dev);
  13499. +
  13500. + yaffs_put_mtd_device(mtd);
  13501. +
  13502. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
  13503. + "yaffs_put_super done");
  13504. +}
  13505. +
  13506. +
  13507. +static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev)
  13508. +{
  13509. + return yaffs_gc_control;
  13510. +}
  13511. +
  13512. +
  13513. +#ifdef YAFFS_COMPILE_EXPORTFS
  13514. +
  13515. +static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
  13516. + uint32_t generation)
  13517. +{
  13518. + return Y_IGET(sb, ino);
  13519. +}
  13520. +
  13521. +static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb,
  13522. + struct fid *fid, int fh_len,
  13523. + int fh_type)
  13524. +{
  13525. + return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  13526. + yaffs2_nfs_get_inode);
  13527. +}
  13528. +
  13529. +static struct dentry *yaffs2_fh_to_parent(struct super_block *sb,
  13530. + struct fid *fid, int fh_len,
  13531. + int fh_type)
  13532. +{
  13533. + return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  13534. + yaffs2_nfs_get_inode);
  13535. +}
  13536. +
  13537. +struct dentry *yaffs2_get_parent(struct dentry *dentry)
  13538. +{
  13539. +
  13540. + struct super_block *sb = dentry->d_inode->i_sb;
  13541. + struct dentry *parent = ERR_PTR(-ENOENT);
  13542. + struct inode *inode;
  13543. + unsigned long parent_ino;
  13544. + struct yaffs_obj *d_obj;
  13545. + struct yaffs_obj *parent_obj;
  13546. +
  13547. + d_obj = yaffs_inode_to_obj(dentry->d_inode);
  13548. +
  13549. + if (d_obj) {
  13550. + parent_obj = d_obj->parent;
  13551. + if (parent_obj) {
  13552. + parent_ino = yaffs_get_obj_inode(parent_obj);
  13553. + inode = Y_IGET(sb, parent_ino);
  13554. +
  13555. + if (IS_ERR(inode)) {
  13556. + parent = ERR_CAST(inode);
  13557. + } else {
  13558. + parent = d_obtain_alias(inode);
  13559. + if (!IS_ERR(parent)) {
  13560. + parent = ERR_PTR(-ENOMEM);
  13561. + iput(inode);
  13562. + }
  13563. + }
  13564. + }
  13565. + }
  13566. +
  13567. + return parent;
  13568. +}
  13569. +
  13570. +/* Just declare a zero structure as a NULL value implies
  13571. + * using the default functions of exportfs.
  13572. + */
  13573. +
  13574. +static struct export_operations yaffs_export_ops = {
  13575. + .fh_to_dentry = yaffs2_fh_to_dentry,
  13576. + .fh_to_parent = yaffs2_fh_to_parent,
  13577. + .get_parent = yaffs2_get_parent,
  13578. +};
  13579. +
  13580. +#endif
  13581. +
  13582. +static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj)
  13583. +{
  13584. + /* Clear the association between the inode and
  13585. + * the struct yaffs_obj.
  13586. + */
  13587. + obj->my_inode = NULL;
  13588. + yaffs_inode_to_obj_lv(inode) = NULL;
  13589. +
  13590. + /* If the object freeing was deferred, then the real
  13591. + * free happens now.
  13592. + * This should fix the inode inconsistency problem.
  13593. + */
  13594. + yaffs_handle_defered_free(obj);
  13595. +}
  13596. +
  13597. +#ifdef YAFFS_HAS_EVICT_INODE
  13598. +/* yaffs_evict_inode combines into one operation what was previously done in
  13599. + * yaffs_clear_inode() and yaffs_delete_inode()
  13600. + *
  13601. + */
  13602. +static void yaffs_evict_inode(struct inode *inode)
  13603. +{
  13604. + struct yaffs_obj *obj;
  13605. + struct yaffs_dev *dev;
  13606. + int deleteme = 0;
  13607. +
  13608. + obj = yaffs_inode_to_obj(inode);
  13609. +
  13610. + yaffs_trace(YAFFS_TRACE_OS,
  13611. + "yaffs_evict_inode: ino %d, count %d %s",
  13612. + (int)inode->i_ino, atomic_read(&inode->i_count),
  13613. + obj ? "object exists" : "null object");
  13614. +
  13615. + if (!inode->i_nlink && !is_bad_inode(inode))
  13616. + deleteme = 1;
  13617. + truncate_inode_pages(&inode->i_data, 0);
  13618. + Y_CLEAR_INODE(inode);
  13619. +
  13620. + if (deleteme && obj) {
  13621. + dev = obj->my_dev;
  13622. + yaffs_gross_lock(dev);
  13623. + yaffs_del_obj(obj);
  13624. + yaffs_gross_unlock(dev);
  13625. + }
  13626. + if (obj) {
  13627. + dev = obj->my_dev;
  13628. + yaffs_gross_lock(dev);
  13629. + yaffs_unstitch_obj(inode, obj);
  13630. + yaffs_gross_unlock(dev);
  13631. + }
  13632. +}
  13633. +#else
  13634. +
  13635. +/* clear is called to tell the fs to release any per-inode data it holds.
  13636. + * The object might still exist on disk and is just being thrown out of the cache
  13637. + * or else the object has actually been deleted and we're being called via
  13638. + * the chain
  13639. + * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
  13640. + */
  13641. +
  13642. +static void yaffs_clear_inode(struct inode *inode)
  13643. +{
  13644. + struct yaffs_obj *obj;
  13645. + struct yaffs_dev *dev;
  13646. +
  13647. + obj = yaffs_inode_to_obj(inode);
  13648. +
  13649. + yaffs_trace(YAFFS_TRACE_OS,
  13650. + "yaffs_clear_inode: ino %d, count %d %s",
  13651. + (int)inode->i_ino, atomic_read(&inode->i_count),
  13652. + obj ? "object exists" : "null object");
  13653. +
  13654. + if (obj) {
  13655. + dev = obj->my_dev;
  13656. + yaffs_gross_lock(dev);
  13657. + yaffs_unstitch_obj(inode, obj);
  13658. + yaffs_gross_unlock(dev);
  13659. + }
  13660. +
  13661. +}
  13662. +
  13663. +/* delete is called when the link count is zero and the inode
  13664. + * is put (ie. nobody wants to know about it anymore, time to
  13665. + * delete the file).
  13666. + * NB Must call clear_inode()
  13667. + */
  13668. +static void yaffs_delete_inode(struct inode *inode)
  13669. +{
  13670. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  13671. + struct yaffs_dev *dev;
  13672. +
  13673. + yaffs_trace(YAFFS_TRACE_OS,
  13674. + "yaffs_delete_inode: ino %d, count %d %s",
  13675. + (int)inode->i_ino, atomic_read(&inode->i_count),
  13676. + obj ? "object exists" : "null object");
  13677. +
  13678. + if (obj) {
  13679. + dev = obj->my_dev;
  13680. + yaffs_gross_lock(dev);
  13681. + yaffs_del_obj(obj);
  13682. + yaffs_gross_unlock(dev);
  13683. + }
  13684. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
  13685. + truncate_inode_pages(&inode->i_data, 0);
  13686. +#endif
  13687. + clear_inode(inode);
  13688. +}
  13689. +#endif
  13690. +
  13691. +
  13692. +
  13693. +
  13694. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13695. +static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
  13696. +{
  13697. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  13698. + struct super_block *sb = dentry->d_sb;
  13699. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  13700. +static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
  13701. +{
  13702. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13703. +#else
  13704. +static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
  13705. +{
  13706. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13707. +#endif
  13708. +
  13709. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs");
  13710. +
  13711. + yaffs_gross_lock(dev);
  13712. +
  13713. + buf->f_type = YAFFS_MAGIC;
  13714. + buf->f_bsize = sb->s_blocksize;
  13715. + buf->f_namelen = 255;
  13716. +
  13717. + if (dev->data_bytes_per_chunk & (dev->data_bytes_per_chunk - 1)) {
  13718. + /* Do this if chunk size is not a power of 2 */
  13719. +
  13720. + uint64_t bytes_in_dev;
  13721. + uint64_t bytes_free;
  13722. +
  13723. + bytes_in_dev =
  13724. + ((uint64_t)
  13725. + ((dev->param.end_block - dev->param.start_block +
  13726. + 1))) * ((uint64_t) (dev->param.chunks_per_block *
  13727. + dev->data_bytes_per_chunk));
  13728. +
  13729. + do_div(bytes_in_dev, sb->s_blocksize); /* bytes_in_dev becomes the number of blocks */
  13730. + buf->f_blocks = bytes_in_dev;
  13731. +
  13732. + bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) *
  13733. + ((uint64_t) (dev->data_bytes_per_chunk));
  13734. +
  13735. + do_div(bytes_free, sb->s_blocksize);
  13736. +
  13737. + buf->f_bfree = bytes_free;
  13738. +
  13739. + } else if (sb->s_blocksize > dev->data_bytes_per_chunk) {
  13740. +
  13741. + buf->f_blocks =
  13742. + (dev->param.end_block - dev->param.start_block + 1) *
  13743. + dev->param.chunks_per_block /
  13744. + (sb->s_blocksize / dev->data_bytes_per_chunk);
  13745. + buf->f_bfree =
  13746. + yaffs_get_n_free_chunks(dev) /
  13747. + (sb->s_blocksize / dev->data_bytes_per_chunk);
  13748. + } else {
  13749. + buf->f_blocks =
  13750. + (dev->param.end_block - dev->param.start_block + 1) *
  13751. + dev->param.chunks_per_block *
  13752. + (dev->data_bytes_per_chunk / sb->s_blocksize);
  13753. +
  13754. + buf->f_bfree =
  13755. + yaffs_get_n_free_chunks(dev) *
  13756. + (dev->data_bytes_per_chunk / sb->s_blocksize);
  13757. + }
  13758. +
  13759. + buf->f_files = 0;
  13760. + buf->f_ffree = 0;
  13761. + buf->f_bavail = buf->f_bfree;
  13762. +
  13763. + yaffs_gross_unlock(dev);
  13764. + return 0;
  13765. +}
  13766. +
  13767. +
  13768. +
  13769. +static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
  13770. +{
  13771. +
  13772. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  13773. + unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
  13774. + unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
  13775. + int do_checkpoint;
  13776. + int dirty = yaffs_check_super_dirty(dev);
  13777. +
  13778. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
  13779. + "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
  13780. + gc_urgent,
  13781. + dirty ? "dirty" : "clean",
  13782. + request_checkpoint ? "checkpoint requested" : "no checkpoint",
  13783. + oneshot_checkpoint ? " one-shot" : "");
  13784. +
  13785. + yaffs_gross_lock(dev);
  13786. + do_checkpoint = ((request_checkpoint && !gc_urgent) ||
  13787. + oneshot_checkpoint) && !dev->is_checkpointed;
  13788. +
  13789. + if (dirty || do_checkpoint) {
  13790. + yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
  13791. + yaffs_clear_super_dirty(dev);
  13792. + if (oneshot_checkpoint)
  13793. + yaffs_auto_checkpoint &= ~4;
  13794. + }
  13795. + yaffs_gross_unlock(dev);
  13796. +
  13797. + return 0;
  13798. +}
  13799. +
  13800. +
  13801. +#ifdef YAFFS_HAS_WRITE_SUPER
  13802. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13803. +static void yaffs_write_super(struct super_block *sb)
  13804. +#else
  13805. +static int yaffs_write_super(struct super_block *sb)
  13806. +#endif
  13807. +{
  13808. + unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
  13809. +
  13810. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
  13811. + "yaffs_write_super %s",
  13812. + request_checkpoint ? " checkpt" : "");
  13813. +
  13814. + yaffs_do_sync_fs(sb, request_checkpoint);
  13815. +
  13816. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
  13817. + return 0;
  13818. +#endif
  13819. +}
  13820. +#endif
  13821. +
  13822. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  13823. +static int yaffs_sync_fs(struct super_block *sb, int wait)
  13824. +#else
  13825. +static int yaffs_sync_fs(struct super_block *sb)
  13826. +#endif
  13827. +{
  13828. + unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1);
  13829. +
  13830. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
  13831. + "yaffs_sync_fs%s", request_checkpoint ? " checkpt" : "");
  13832. +
  13833. + yaffs_do_sync_fs(sb, request_checkpoint);
  13834. +
  13835. + return 0;
  13836. +}
  13837. +
  13838. +
  13839. +
  13840. +static const struct super_operations yaffs_super_ops = {
  13841. + .statfs = yaffs_statfs,
  13842. +
  13843. +#ifndef YAFFS_USE_OWN_IGET
  13844. + .read_inode = yaffs_read_inode,
  13845. +#endif
  13846. +#ifdef YAFFS_HAS_PUT_INODE
  13847. + .put_inode = yaffs_put_inode,
  13848. +#endif
  13849. + .put_super = yaffs_put_super,
  13850. +#ifdef YAFFS_HAS_EVICT_INODE
  13851. + .evict_inode = yaffs_evict_inode,
  13852. +#else
  13853. + .delete_inode = yaffs_delete_inode,
  13854. + .clear_inode = yaffs_clear_inode,
  13855. +#endif
  13856. + .sync_fs = yaffs_sync_fs,
  13857. +#ifdef YAFFS_HAS_WRITE_SUPER
  13858. + .write_super = yaffs_write_super,
  13859. +#endif
  13860. +};
  13861. +
  13862. +struct yaffs_options {
  13863. + int inband_tags;
  13864. + int skip_checkpoint_read;
  13865. + int skip_checkpoint_write;
  13866. + int no_cache;
  13867. + int tags_ecc_on;
  13868. + int tags_ecc_overridden;
  13869. + int lazy_loading_enabled;
  13870. + int lazy_loading_overridden;
  13871. + int empty_lost_and_found;
  13872. + int empty_lost_and_found_overridden;
  13873. + int disable_summary;
  13874. +};
  13875. +
  13876. +#define MAX_OPT_LEN 30
  13877. +static int yaffs_parse_options(struct yaffs_options *options,
  13878. + const char *options_str)
  13879. +{
  13880. + char cur_opt[MAX_OPT_LEN + 1];
  13881. + int p;
  13882. + int error = 0;
  13883. +
  13884. + /* Parse through the options which is a comma seperated list */
  13885. +
  13886. + while (options_str && *options_str && !error) {
  13887. + memset(cur_opt, 0, MAX_OPT_LEN + 1);
  13888. + p = 0;
  13889. +
  13890. + while (*options_str == ',')
  13891. + options_str++;
  13892. +
  13893. + while (*options_str && *options_str != ',') {
  13894. + if (p < MAX_OPT_LEN) {
  13895. + cur_opt[p] = *options_str;
  13896. + p++;
  13897. + }
  13898. + options_str++;
  13899. + }
  13900. +
  13901. + if (!strcmp(cur_opt, "inband-tags")) {
  13902. + options->inband_tags = 1;
  13903. + } else if (!strcmp(cur_opt, "tags-ecc-off")) {
  13904. + options->tags_ecc_on = 0;
  13905. + options->tags_ecc_overridden = 1;
  13906. + } else if (!strcmp(cur_opt, "tags-ecc-on")) {
  13907. + options->tags_ecc_on = 1;
  13908. + options->tags_ecc_overridden = 1;
  13909. + } else if (!strcmp(cur_opt, "lazy-loading-off")) {
  13910. + options->lazy_loading_enabled = 0;
  13911. + options->lazy_loading_overridden = 1;
  13912. + } else if (!strcmp(cur_opt, "lazy-loading-on")) {
  13913. + options->lazy_loading_enabled = 1;
  13914. + options->lazy_loading_overridden = 1;
  13915. + } else if (!strcmp(cur_opt, "disable-summary")) {
  13916. + options->disable_summary = 1;
  13917. + } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
  13918. + options->empty_lost_and_found = 0;
  13919. + options->empty_lost_and_found_overridden = 1;
  13920. + } else if (!strcmp(cur_opt, "empty-lost-and-found-on")) {
  13921. + options->empty_lost_and_found = 1;
  13922. + options->empty_lost_and_found_overridden = 1;
  13923. + } else if (!strcmp(cur_opt, "no-cache")) {
  13924. + options->no_cache = 1;
  13925. + } else if (!strcmp(cur_opt, "no-checkpoint-read")) {
  13926. + options->skip_checkpoint_read = 1;
  13927. + } else if (!strcmp(cur_opt, "no-checkpoint-write")) {
  13928. + options->skip_checkpoint_write = 1;
  13929. + } else if (!strcmp(cur_opt, "no-checkpoint")) {
  13930. + options->skip_checkpoint_read = 1;
  13931. + options->skip_checkpoint_write = 1;
  13932. + } else {
  13933. + printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",
  13934. + cur_opt);
  13935. + error = 1;
  13936. + }
  13937. + }
  13938. +
  13939. + return error;
  13940. +}
  13941. +
  13942. +
  13943. +static struct dentry *yaffs_make_root(struct inode *inode)
  13944. +{
  13945. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
  13946. + struct dentry *root = d_alloc_root(inode);
  13947. +
  13948. + if (!root)
  13949. + iput(inode);
  13950. +
  13951. + return root;
  13952. +#else
  13953. + return d_make_root(inode);
  13954. +#endif
  13955. +}
  13956. +
  13957. +
  13958. +
  13959. +
  13960. +static struct super_block *yaffs_internal_read_super(int yaffs_version,
  13961. + struct super_block *sb,
  13962. + void *data, int silent)
  13963. +{
  13964. + int n_blocks;
  13965. + struct inode *inode = NULL;
  13966. + struct dentry *root;
  13967. + struct yaffs_dev *dev = 0;
  13968. + char devname_buf[BDEVNAME_SIZE + 1];
  13969. + struct mtd_info *mtd;
  13970. + int err;
  13971. + char *data_str = (char *)data;
  13972. + struct yaffs_linux_context *context = NULL;
  13973. + struct yaffs_param *param;
  13974. +
  13975. + int read_only = 0;
  13976. + int inband_tags = 0;
  13977. +
  13978. + struct yaffs_options options;
  13979. +
  13980. + unsigned mount_id;
  13981. + int found;
  13982. + struct yaffs_linux_context *context_iterator;
  13983. + struct list_head *l;
  13984. +
  13985. + if (!sb) {
  13986. + printk(KERN_INFO "yaffs: sb is NULL\n");
  13987. + return NULL;
  13988. + }
  13989. +
  13990. + sb->s_magic = YAFFS_MAGIC;
  13991. + sb->s_op = &yaffs_super_ops;
  13992. + sb->s_flags |= MS_NOATIME;
  13993. +
  13994. + read_only = ((sb->s_flags & MS_RDONLY) != 0);
  13995. +
  13996. +#ifdef YAFFS_COMPILE_EXPORTFS
  13997. + sb->s_export_op = &yaffs_export_ops;
  13998. +#endif
  13999. +
  14000. + if (!sb->s_dev)
  14001. + printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
  14002. + else if (!yaffs_devname(sb, devname_buf))
  14003. + printk(KERN_INFO "yaffs: devname is NULL\n");
  14004. + else
  14005. + printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
  14006. + sb->s_dev,
  14007. + yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw");
  14008. +
  14009. + if (!data_str)
  14010. + data_str = "";
  14011. +
  14012. + printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str);
  14013. +
  14014. + memset(&options, 0, sizeof(options));
  14015. +
  14016. + if (yaffs_parse_options(&options, data_str)) {
  14017. + /* Option parsing failed */
  14018. + return NULL;
  14019. + }
  14020. +
  14021. + sb->s_blocksize = PAGE_CACHE_SIZE;
  14022. + sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
  14023. +
  14024. + yaffs_trace(YAFFS_TRACE_OS,
  14025. + "yaffs_read_super: Using yaffs%d", yaffs_version);
  14026. + yaffs_trace(YAFFS_TRACE_OS,
  14027. + "yaffs_read_super: block size %d", (int)(sb->s_blocksize));
  14028. +
  14029. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  14030. + "yaffs: Attempting MTD mount of %u.%u,\"%s\"",
  14031. + MAJOR(sb->s_dev), MINOR(sb->s_dev),
  14032. + yaffs_devname(sb, devname_buf));
  14033. +
  14034. + /* Get the device */
  14035. + mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
  14036. + if (IS_ERR(mtd)) {
  14037. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  14038. + "yaffs: MTD device %u either not valid or unavailable",
  14039. + MINOR(sb->s_dev));
  14040. + return NULL;
  14041. + }
  14042. +
  14043. + if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
  14044. + yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
  14045. + yaffs_version = 2;
  14046. + }
  14047. +
  14048. + /* Added NCB 26/5/2006 for completeness */
  14049. + if (yaffs_version == 2 && !options.inband_tags
  14050. + && WRITE_SIZE(mtd) == 512) {
  14051. + yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
  14052. + yaffs_version = 1;
  14053. + }
  14054. +
  14055. + if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) ||
  14056. + options.inband_tags)
  14057. + inband_tags = 1;
  14058. +
  14059. + if(yaffs_verify_mtd(mtd, yaffs_version, inband_tags) < 0)
  14060. + return NULL;
  14061. +
  14062. + /* OK, so if we got here, we have an MTD that's NAND and looks
  14063. + * like it has the right capabilities
  14064. + * Set the struct yaffs_dev up for mtd
  14065. + */
  14066. +
  14067. + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
  14068. + read_only = 1;
  14069. + printk(KERN_INFO
  14070. + "yaffs: mtd is read only, setting superblock read only\n"
  14071. + );
  14072. + sb->s_flags |= MS_RDONLY;
  14073. + }
  14074. +
  14075. + dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL);
  14076. + context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
  14077. +
  14078. + if (!dev || !context) {
  14079. + kfree(dev);
  14080. + kfree(context);
  14081. + dev = NULL;
  14082. + context = NULL;
  14083. +
  14084. + /* Deep shit could not allocate device structure */
  14085. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  14086. + "yaffs_read_super: Failed trying to allocate struct yaffs_dev."
  14087. + );
  14088. + return NULL;
  14089. + }
  14090. + memset(dev, 0, sizeof(struct yaffs_dev));
  14091. + param = &(dev->param);
  14092. +
  14093. + memset(context, 0, sizeof(struct yaffs_linux_context));
  14094. + dev->os_context = context;
  14095. + INIT_LIST_HEAD(&(context->context_list));
  14096. + context->dev = dev;
  14097. + context->super = sb;
  14098. +
  14099. + dev->read_only = read_only;
  14100. +
  14101. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  14102. + sb->s_fs_info = dev;
  14103. +#else
  14104. + sb->u.generic_sbp = dev;
  14105. +#endif
  14106. +
  14107. +
  14108. + dev->driver_context = mtd;
  14109. + param->name = mtd->name;
  14110. +
  14111. + /* Set up the memory size parameters.... */
  14112. +
  14113. +
  14114. + param->n_reserved_blocks = 5;
  14115. + param->n_caches = (options.no_cache) ? 0 : 10;
  14116. + param->inband_tags = inband_tags;
  14117. +
  14118. + param->enable_xattr = 1;
  14119. + if (options.lazy_loading_overridden)
  14120. + param->disable_lazy_load = !options.lazy_loading_enabled;
  14121. +
  14122. + param->defered_dir_update = 1;
  14123. +
  14124. + if (options.tags_ecc_overridden)
  14125. + param->no_tags_ecc = !options.tags_ecc_on;
  14126. +
  14127. + param->empty_lost_n_found = 1;
  14128. + param->refresh_period = 500;
  14129. + param->disable_summary = options.disable_summary;
  14130. +
  14131. +
  14132. +#ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING
  14133. + param->disable_bad_block_marking = 1;
  14134. +#endif
  14135. + if (options.empty_lost_and_found_overridden)
  14136. + param->empty_lost_n_found = options.empty_lost_and_found;
  14137. +
  14138. + /* ... and the functions. */
  14139. + if (yaffs_version == 2) {
  14140. + param->is_yaffs2 = 1;
  14141. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  14142. + param->total_bytes_per_chunk = mtd->writesize;
  14143. + param->chunks_per_block = mtd->erasesize / mtd->writesize;
  14144. +#else
  14145. + param->total_bytes_per_chunk = mtd->oobblock;
  14146. + param->chunks_per_block = mtd->erasesize / mtd->oobblock;
  14147. +#endif
  14148. + n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize);
  14149. +
  14150. + param->start_block = 0;
  14151. + param->end_block = n_blocks - 1;
  14152. + } else {
  14153. + param->is_yaffs2 = 0;
  14154. + n_blocks = YCALCBLOCKS(mtd->size,
  14155. + YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
  14156. +
  14157. + param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
  14158. + param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
  14159. + }
  14160. +
  14161. + param->start_block = 0;
  14162. + param->end_block = n_blocks - 1;
  14163. +
  14164. + yaffs_mtd_drv_install(dev);
  14165. +
  14166. + param->sb_dirty_fn = yaffs_set_super_dirty;
  14167. + param->gc_control_fn = yaffs_gc_control_callback;
  14168. +
  14169. + yaffs_dev_to_lc(dev)->super = sb;
  14170. +
  14171. + param->use_nand_ecc = 1;
  14172. +
  14173. + param->skip_checkpt_rd = options.skip_checkpoint_read;
  14174. + param->skip_checkpt_wr = options.skip_checkpoint_write;
  14175. +
  14176. + mutex_lock(&yaffs_context_lock);
  14177. + /* Get a mount id */
  14178. + found = 0;
  14179. + for (mount_id = 0; !found; mount_id++) {
  14180. + found = 1;
  14181. + list_for_each(l, &yaffs_context_list) {
  14182. + context_iterator =
  14183. + list_entry(l, struct yaffs_linux_context,
  14184. + context_list);
  14185. + if (context_iterator->mount_id == mount_id)
  14186. + found = 0;
  14187. + }
  14188. + }
  14189. + context->mount_id = mount_id;
  14190. +
  14191. + list_add_tail(&(yaffs_dev_to_lc(dev)->context_list),
  14192. + &yaffs_context_list);
  14193. + mutex_unlock(&yaffs_context_lock);
  14194. +
  14195. + /* Directory search handling... */
  14196. + INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts));
  14197. + param->remove_obj_fn = yaffs_remove_obj_callback;
  14198. +
  14199. + mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock));
  14200. +
  14201. + yaffs_gross_lock(dev);
  14202. +
  14203. + err = yaffs_guts_initialise(dev);
  14204. +
  14205. + yaffs_trace(YAFFS_TRACE_OS,
  14206. + "yaffs_read_super: guts initialised %s",
  14207. + (err == YAFFS_OK) ? "OK" : "FAILED");
  14208. +
  14209. + if (err == YAFFS_OK)
  14210. + yaffs_bg_start(dev);
  14211. +
  14212. + if (!context->bg_thread)
  14213. + param->defered_dir_update = 0;
  14214. +
  14215. + sb->s_maxbytes = yaffs_max_file_size(dev);
  14216. +
  14217. + /* Release lock before yaffs_get_inode() */
  14218. + yaffs_gross_unlock(dev);
  14219. +
  14220. + /* Create root inode */
  14221. + if (err == YAFFS_OK)
  14222. + inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev));
  14223. +
  14224. + if (!inode)
  14225. + return NULL;
  14226. +
  14227. + inode->i_op = &yaffs_dir_inode_operations;
  14228. + inode->i_fop = &yaffs_dir_operations;
  14229. +
  14230. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: got root inode");
  14231. +
  14232. + root = yaffs_make_root(inode);
  14233. +
  14234. + if (!root)
  14235. + return NULL;
  14236. +
  14237. + sb->s_root = root;
  14238. + if(!dev->is_checkpointed)
  14239. + yaffs_set_super_dirty(dev);
  14240. +
  14241. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  14242. + "yaffs_read_super: is_checkpointed %d",
  14243. + dev->is_checkpointed);
  14244. +
  14245. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done");
  14246. + return sb;
  14247. +}
  14248. +
  14249. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  14250. +static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
  14251. + int silent)
  14252. +{
  14253. + return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
  14254. +}
  14255. +
  14256. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  14257. +static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags,
  14258. + const char *dev_name, void *data)
  14259. +{
  14260. + return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd);
  14261. +}
  14262. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  14263. +static int yaffs_read_super(struct file_system_type *fs,
  14264. + int flags, const char *dev_name,
  14265. + void *data, struct vfsmount *mnt)
  14266. +{
  14267. +
  14268. + return get_sb_bdev(fs, flags, dev_name, data,
  14269. + yaffs_internal_read_super_mtd, mnt);
  14270. +}
  14271. +#else
  14272. +static struct super_block *yaffs_read_super(struct file_system_type *fs,
  14273. + int flags, const char *dev_name,
  14274. + void *data)
  14275. +{
  14276. +
  14277. + return get_sb_bdev(fs, flags, dev_name, data,
  14278. + yaffs_internal_read_super_mtd);
  14279. +}
  14280. +#endif
  14281. +
  14282. +static struct file_system_type yaffs_fs_type = {
  14283. + .owner = THIS_MODULE,
  14284. + .name = "yaffs",
  14285. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  14286. + .mount = yaffs_mount,
  14287. +#else
  14288. + .get_sb = yaffs_read_super,
  14289. +#endif
  14290. + .kill_sb = kill_block_super,
  14291. + .fs_flags = FS_REQUIRES_DEV,
  14292. +};
  14293. +#else
  14294. +static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
  14295. + int silent)
  14296. +{
  14297. + return yaffs_internal_read_super(1, sb, data, silent);
  14298. +}
  14299. +
  14300. +static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
  14301. + FS_REQUIRES_DEV);
  14302. +#endif
  14303. +
  14304. +
  14305. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  14306. +static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
  14307. + int silent)
  14308. +{
  14309. + return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
  14310. +}
  14311. +
  14312. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  14313. +static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags,
  14314. + const char *dev_name, void *data)
  14315. +{
  14316. + return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd);
  14317. +}
  14318. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  14319. +static int yaffs2_read_super(struct file_system_type *fs,
  14320. + int flags, const char *dev_name, void *data,
  14321. + struct vfsmount *mnt)
  14322. +{
  14323. + return get_sb_bdev(fs, flags, dev_name, data,
  14324. + yaffs2_internal_read_super_mtd, mnt);
  14325. +}
  14326. +#else
  14327. +static struct super_block *yaffs2_read_super(struct file_system_type *fs,
  14328. + int flags, const char *dev_name,
  14329. + void *data)
  14330. +{
  14331. +
  14332. + return get_sb_bdev(fs, flags, dev_name, data,
  14333. + yaffs2_internal_read_super_mtd);
  14334. +}
  14335. +#endif
  14336. +
  14337. +static struct file_system_type yaffs2_fs_type = {
  14338. + .owner = THIS_MODULE,
  14339. + .name = "yaffs2",
  14340. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  14341. + .mount = yaffs2_mount,
  14342. +#else
  14343. + .get_sb = yaffs2_read_super,
  14344. +#endif
  14345. + .kill_sb = kill_block_super,
  14346. + .fs_flags = FS_REQUIRES_DEV,
  14347. +};
  14348. +#else
  14349. +static struct super_block *yaffs2_read_super(struct super_block *sb,
  14350. + void *data, int silent)
  14351. +{
  14352. + return yaffs_internal_read_super(2, sb, data, silent);
  14353. +}
  14354. +
  14355. +static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
  14356. + FS_REQUIRES_DEV);
  14357. +#endif
  14358. +
  14359. +
  14360. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
  14361. +static struct proc_dir_entry *my_proc_entry;
  14362. +
  14363. +static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
  14364. +{
  14365. + struct yaffs_param *param = &dev->param;
  14366. + int bs[10];
  14367. +
  14368. + yaffs_count_blocks_by_state(dev,bs);
  14369. +
  14370. + buf += sprintf(buf, "start_block.......... %d\n", param->start_block);
  14371. + buf += sprintf(buf, "end_block............ %d\n", param->end_block);
  14372. + buf += sprintf(buf, "total_bytes_per_chunk %d\n",
  14373. + param->total_bytes_per_chunk);
  14374. + buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc);
  14375. + buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc);
  14376. + buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2);
  14377. + buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags);
  14378. + buf += sprintf(buf, "empty_lost_n_found... %d\n",
  14379. + param->empty_lost_n_found);
  14380. + buf += sprintf(buf, "disable_lazy_load.... %d\n",
  14381. + param->disable_lazy_load);
  14382. + buf += sprintf(buf, "disable_bad_block_mrk %d\n",
  14383. + param->disable_bad_block_marking);
  14384. + buf += sprintf(buf, "refresh_period....... %d\n",
  14385. + param->refresh_period);
  14386. + buf += sprintf(buf, "n_caches............. %d\n", param->n_caches);
  14387. + buf += sprintf(buf, "n_reserved_blocks.... %d\n",
  14388. + param->n_reserved_blocks);
  14389. + buf += sprintf(buf, "always_check_erased.. %d\n",
  14390. + param->always_check_erased);
  14391. + buf += sprintf(buf, "\n");
  14392. + buf += sprintf(buf, "block count by state\n");
  14393. + buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n",
  14394. + bs[0], bs[1], bs[2], bs[3], bs[4]);
  14395. + buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n",
  14396. + bs[5], bs[6], bs[7], bs[8], bs[9]);
  14397. +
  14398. + return buf;
  14399. +}
  14400. +
  14401. +static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
  14402. +{
  14403. + buf += sprintf(buf, "max file size....... %lld\n",
  14404. + (long long) yaffs_max_file_size(dev));
  14405. + buf += sprintf(buf, "data_bytes_per_chunk. %d\n",
  14406. + dev->data_bytes_per_chunk);
  14407. + buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits);
  14408. + buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size);
  14409. + buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks);
  14410. + buf += sprintf(buf, "blocks_in_checkpt.... %d\n",
  14411. + dev->blocks_in_checkpt);
  14412. + buf += sprintf(buf, "\n");
  14413. + buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes);
  14414. + buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj);
  14415. + buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks);
  14416. + buf += sprintf(buf, "\n");
  14417. + buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes);
  14418. + buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads);
  14419. + buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures);
  14420. + buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies);
  14421. + buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs);
  14422. + buf += sprintf(buf, "passive_gc_count..... %u\n",
  14423. + dev->passive_gc_count);
  14424. + buf += sprintf(buf, "oldest_dirty_gc_count %u\n",
  14425. + dev->oldest_dirty_gc_count);
  14426. + buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks);
  14427. + buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs);
  14428. + buf += sprintf(buf, "n_retried_writes..... %u\n",
  14429. + dev->n_retried_writes);
  14430. + buf += sprintf(buf, "n_retired_blocks..... %u\n",
  14431. + dev->n_retired_blocks);
  14432. + buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed);
  14433. + buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed);
  14434. + buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n",
  14435. + dev->n_tags_ecc_fixed);
  14436. + buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n",
  14437. + dev->n_tags_ecc_unfixed);
  14438. + buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits);
  14439. + buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files);
  14440. + buf += sprintf(buf, "n_unlinked_files..... %u\n",
  14441. + dev->n_unlinked_files);
  14442. + buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
  14443. + buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
  14444. + buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
  14445. + buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
  14446. +
  14447. + return buf;
  14448. +}
  14449. +
  14450. +static int yaffs_proc_read(char *page,
  14451. + char **start,
  14452. + off_t offset, int count, int *eof, void *data)
  14453. +{
  14454. + struct list_head *item;
  14455. + char *buf = page;
  14456. + int step = offset;
  14457. + int n = 0;
  14458. +
  14459. + /* Get proc_file_read() to step 'offset' by one on each sucessive call.
  14460. + * We use 'offset' (*ppos) to indicate where we are in dev_list.
  14461. + * This also assumes the user has posted a read buffer large
  14462. + * enough to hold the complete output; but that's life in /proc.
  14463. + */
  14464. +
  14465. + *(int *)start = 1;
  14466. +
  14467. + /* Print header first */
  14468. + if (step == 0)
  14469. + buf +=
  14470. + sprintf(buf,
  14471. + "Multi-version YAFFS built:" __DATE__ " " __TIME__
  14472. + "\n");
  14473. + else if (step == 1)
  14474. + buf += sprintf(buf, "\n");
  14475. + else {
  14476. + step -= 2;
  14477. +
  14478. + mutex_lock(&yaffs_context_lock);
  14479. +
  14480. + /* Locate and print the Nth entry. Order N-squared but N is small. */
  14481. + list_for_each(item, &yaffs_context_list) {
  14482. + struct yaffs_linux_context *dc =
  14483. + list_entry(item, struct yaffs_linux_context,
  14484. + context_list);
  14485. + struct yaffs_dev *dev = dc->dev;
  14486. +
  14487. + if (n < (step & ~1)) {
  14488. + n += 2;
  14489. + continue;
  14490. + }
  14491. + if ((step & 1) == 0) {
  14492. + buf +=
  14493. + sprintf(buf, "\nDevice %d \"%s\"\n", n,
  14494. + dev->param.name);
  14495. + buf = yaffs_dump_dev_part0(buf, dev);
  14496. + } else {
  14497. + buf = yaffs_dump_dev_part1(buf, dev);
  14498. + }
  14499. +
  14500. + break;
  14501. + }
  14502. + mutex_unlock(&yaffs_context_lock);
  14503. + }
  14504. +
  14505. + return buf - page < count ? buf - page : count;
  14506. +}
  14507. +
  14508. +/**
  14509. + * Set the verbosity of the warnings and error messages.
  14510. + *
  14511. + * Note that the names can only be a..z or _ with the current code.
  14512. + */
  14513. +
  14514. +static struct {
  14515. + char *mask_name;
  14516. + unsigned mask_bitfield;
  14517. +} mask_flags[] = {
  14518. + {"allocate", YAFFS_TRACE_ALLOCATE},
  14519. + {"always", YAFFS_TRACE_ALWAYS},
  14520. + {"background", YAFFS_TRACE_BACKGROUND},
  14521. + {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS},
  14522. + {"buffers", YAFFS_TRACE_BUFFERS},
  14523. + {"bug", YAFFS_TRACE_BUG},
  14524. + {"checkpt", YAFFS_TRACE_CHECKPOINT},
  14525. + {"deletion", YAFFS_TRACE_DELETION},
  14526. + {"erase", YAFFS_TRACE_ERASE},
  14527. + {"error", YAFFS_TRACE_ERROR},
  14528. + {"gc_detail", YAFFS_TRACE_GC_DETAIL},
  14529. + {"gc", YAFFS_TRACE_GC},
  14530. + {"lock", YAFFS_TRACE_LOCK},
  14531. + {"mtd", YAFFS_TRACE_MTD},
  14532. + {"nandaccess", YAFFS_TRACE_NANDACCESS},
  14533. + {"os", YAFFS_TRACE_OS},
  14534. + {"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
  14535. + {"scan", YAFFS_TRACE_SCAN},
  14536. + {"mount", YAFFS_TRACE_MOUNT},
  14537. + {"tracing", YAFFS_TRACE_TRACING},
  14538. + {"sync", YAFFS_TRACE_SYNC},
  14539. + {"write", YAFFS_TRACE_WRITE},
  14540. + {"verify", YAFFS_TRACE_VERIFY},
  14541. + {"verify_nand", YAFFS_TRACE_VERIFY_NAND},
  14542. + {"verify_full", YAFFS_TRACE_VERIFY_FULL},
  14543. + {"verify_all", YAFFS_TRACE_VERIFY_ALL},
  14544. + {"all", 0xffffffff},
  14545. + {"none", 0},
  14546. + {NULL, 0},
  14547. +};
  14548. +
  14549. +#define MAX_MASK_NAME_LENGTH 40
  14550. +static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
  14551. + unsigned long count, void *data)
  14552. +{
  14553. + unsigned rg = 0, mask_bitfield;
  14554. + char *end;
  14555. + char *mask_name;
  14556. + const char *x;
  14557. + char substring[MAX_MASK_NAME_LENGTH + 1];
  14558. + int i;
  14559. + int done = 0;
  14560. + int add, len = 0;
  14561. + int pos = 0;
  14562. +
  14563. + rg = yaffs_trace_mask;
  14564. +
  14565. + while (!done && (pos < count)) {
  14566. + done = 1;
  14567. + while ((pos < count) && isspace(buf[pos]))
  14568. + pos++;
  14569. +
  14570. + switch (buf[pos]) {
  14571. + case '+':
  14572. + case '-':
  14573. + case '=':
  14574. + add = buf[pos];
  14575. + pos++;
  14576. + break;
  14577. +
  14578. + default:
  14579. + add = ' ';
  14580. + break;
  14581. + }
  14582. + mask_name = NULL;
  14583. +
  14584. + mask_bitfield = simple_strtoul(buf + pos, &end, 0);
  14585. +
  14586. + if (end > buf + pos) {
  14587. + mask_name = "numeral";
  14588. + len = end - (buf + pos);
  14589. + pos += len;
  14590. + done = 0;
  14591. + } else {
  14592. + for (x = buf + pos, i = 0;
  14593. + (*x == '_' || (*x >= 'a' && *x <= 'z')) &&
  14594. + i < MAX_MASK_NAME_LENGTH; x++, i++, pos++)
  14595. + substring[i] = *x;
  14596. + substring[i] = '\0';
  14597. +
  14598. + for (i = 0; mask_flags[i].mask_name != NULL; i++) {
  14599. + if (strcmp(substring, mask_flags[i].mask_name)
  14600. + == 0) {
  14601. + mask_name = mask_flags[i].mask_name;
  14602. + mask_bitfield =
  14603. + mask_flags[i].mask_bitfield;
  14604. + done = 0;
  14605. + break;
  14606. + }
  14607. + }
  14608. + }
  14609. +
  14610. + if (mask_name != NULL) {
  14611. + done = 0;
  14612. + switch (add) {
  14613. + case '-':
  14614. + rg &= ~mask_bitfield;
  14615. + break;
  14616. + case '+':
  14617. + rg |= mask_bitfield;
  14618. + break;
  14619. + case '=':
  14620. + rg = mask_bitfield;
  14621. + break;
  14622. + default:
  14623. + rg |= mask_bitfield;
  14624. + break;
  14625. + }
  14626. + }
  14627. + }
  14628. +
  14629. + yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS;
  14630. +
  14631. + printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask);
  14632. +
  14633. + if (rg & YAFFS_TRACE_ALWAYS) {
  14634. + for (i = 0; mask_flags[i].mask_name != NULL; i++) {
  14635. + char flag;
  14636. + flag = ((rg & mask_flags[i].mask_bitfield) ==
  14637. + mask_flags[i].mask_bitfield) ? '+' : '-';
  14638. + printk(KERN_DEBUG "%c%s\n", flag,
  14639. + mask_flags[i].mask_name);
  14640. + }
  14641. + }
  14642. +
  14643. + return count;
  14644. +}
  14645. +
  14646. +/* Debug strings are of the form:
  14647. + * .bnnn print info on block n
  14648. + * .cobjn,chunkn print nand chunk id for objn:chunkn
  14649. + */
  14650. +
  14651. +static int yaffs_proc_debug_write(struct file *file, const char *buf,
  14652. + unsigned long count, void *data)
  14653. +{
  14654. +
  14655. + char str[100];
  14656. + char *p0;
  14657. + char *p1;
  14658. + long p1_val;
  14659. + long p0_val;
  14660. + char cmd;
  14661. + struct list_head *item;
  14662. +
  14663. + memset(str, 0, sizeof(str));
  14664. + memcpy(str, buf, min(count, sizeof(str) -1));
  14665. +
  14666. + cmd = str[1];
  14667. +
  14668. + p0 = str + 2;
  14669. +
  14670. + p1 = p0;
  14671. +
  14672. + while (*p1 && *p1 != ',') {
  14673. + p1++;
  14674. + }
  14675. + *p1 = '\0';
  14676. + p1++;
  14677. +
  14678. + p0_val = simple_strtol(p0, NULL, 0);
  14679. + p1_val = simple_strtol(p1, NULL, 0);
  14680. +
  14681. +
  14682. + mutex_lock(&yaffs_context_lock);
  14683. +
  14684. + /* Locate and print the Nth entry. Order N-squared but N is small. */
  14685. + list_for_each(item, &yaffs_context_list) {
  14686. + struct yaffs_linux_context *dc =
  14687. + list_entry(item, struct yaffs_linux_context,
  14688. + context_list);
  14689. + struct yaffs_dev *dev = dc->dev;
  14690. +
  14691. + if (cmd == 'b') {
  14692. + struct yaffs_block_info *bi;
  14693. +
  14694. + bi = yaffs_get_block_info(dev,p0_val);
  14695. +
  14696. + if(bi) {
  14697. + printk("Block %d: state %d, retire %d, use %d, seq %d\n",
  14698. + (int)p0_val, bi->block_state,
  14699. + bi->needs_retiring, bi->pages_in_use,
  14700. + bi->seq_number);
  14701. + }
  14702. + } else if (cmd == 'c') {
  14703. + struct yaffs_obj *obj;
  14704. + int nand_chunk;
  14705. +
  14706. + obj = yaffs_find_by_number(dev, p0_val);
  14707. + if (!obj)
  14708. + printk("No obj %d\n", (int)p0_val);
  14709. + else {
  14710. + if(p1_val == 0)
  14711. + nand_chunk = obj->hdr_chunk;
  14712. + else
  14713. + nand_chunk =
  14714. + yaffs_find_chunk_in_file(obj,
  14715. + p1_val, NULL);
  14716. + printk("Nand chunk for %d:%d is %d\n",
  14717. + (int)p0_val, (int)p1_val, nand_chunk);
  14718. + }
  14719. + }
  14720. + }
  14721. +
  14722. + mutex_unlock(&yaffs_context_lock);
  14723. +
  14724. + return count;
  14725. +}
  14726. +
  14727. +static int yaffs_proc_write(struct file *file, const char *buf,
  14728. + unsigned long count, void *data)
  14729. +{
  14730. + if (buf[0] == '.')
  14731. + return yaffs_proc_debug_write(file, buf, count, data);
  14732. + return yaffs_proc_write_trace_options(file, buf, count, data);
  14733. +}
  14734. +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) */
  14735. +
  14736. +/* Stuff to handle installation of file systems */
  14737. +struct file_system_to_install {
  14738. + struct file_system_type *fst;
  14739. + int installed;
  14740. +};
  14741. +
  14742. +static struct file_system_to_install fs_to_install[] = {
  14743. + {&yaffs_fs_type, 0},
  14744. + {&yaffs2_fs_type, 0},
  14745. + {NULL, 0}
  14746. +};
  14747. +
  14748. +static int __init init_yaffs_fs(void)
  14749. +{
  14750. + int error = 0;
  14751. + struct file_system_to_install *fsinst;
  14752. +
  14753. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  14754. + "yaffs built " __DATE__ " " __TIME__ " Installing.");
  14755. +
  14756. + mutex_init(&yaffs_context_lock);
  14757. +
  14758. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
  14759. + /* Install the proc_fs entries */
  14760. + my_proc_entry = create_proc_entry("yaffs",
  14761. + S_IRUGO | S_IFREG, YPROC_ROOT);
  14762. +
  14763. + if (my_proc_entry) {
  14764. + my_proc_entry->write_proc = yaffs_proc_write;
  14765. + my_proc_entry->read_proc = yaffs_proc_read;
  14766. + my_proc_entry->data = NULL;
  14767. + } else {
  14768. + return -ENOMEM;
  14769. + }
  14770. +#endif
  14771. +
  14772. + /* Now add the file system entries */
  14773. +
  14774. + fsinst = fs_to_install;
  14775. +
  14776. + while (fsinst->fst && !error) {
  14777. + error = register_filesystem(fsinst->fst);
  14778. + if (!error)
  14779. + fsinst->installed = 1;
  14780. + fsinst++;
  14781. + }
  14782. +
  14783. + /* Any errors? uninstall */
  14784. + if (error) {
  14785. + fsinst = fs_to_install;
  14786. +
  14787. + while (fsinst->fst) {
  14788. + if (fsinst->installed) {
  14789. + unregister_filesystem(fsinst->fst);
  14790. + fsinst->installed = 0;
  14791. + }
  14792. + fsinst++;
  14793. + }
  14794. + }
  14795. +
  14796. + return error;
  14797. +}
  14798. +
  14799. +static void __exit exit_yaffs_fs(void)
  14800. +{
  14801. +
  14802. + struct file_system_to_install *fsinst;
  14803. +
  14804. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  14805. + "yaffs built " __DATE__ " " __TIME__ " removing.");
  14806. +
  14807. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
  14808. + remove_proc_entry("yaffs", YPROC_ROOT);
  14809. +#endif
  14810. +
  14811. + fsinst = fs_to_install;
  14812. +
  14813. + while (fsinst->fst) {
  14814. + if (fsinst->installed) {
  14815. + unregister_filesystem(fsinst->fst);
  14816. + fsinst->installed = 0;
  14817. + }
  14818. + fsinst++;
  14819. + }
  14820. +}
  14821. +
  14822. +module_init(init_yaffs_fs)
  14823. + module_exit(exit_yaffs_fs)
  14824. +
  14825. + MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
  14826. +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
  14827. +MODULE_LICENSE("GPL");
  14828. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_vfs.c.orig linux-3.14.4/fs/yaffs2/yaffs_vfs.c.orig
  14829. --- linux-3.14.4.orig/fs/yaffs2/yaffs_vfs.c.orig 1970-01-01 01:00:00.000000000 +0100
  14830. +++ linux-3.14.4/fs/yaffs2/yaffs_vfs.c.orig 2014-05-14 12:41:23.992792475 +0200
  14831. @@ -0,0 +1,3485 @@
  14832. +/*
  14833. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  14834. + *
  14835. + * Copyright (C) 2002-2011 Aleph One Ltd.
  14836. + * for Toby Churchill Ltd and Brightstar Engineering
  14837. + *
  14838. + * Created by Charles Manning <charles@aleph1.co.uk>
  14839. + * Acknowledgements:
  14840. + * Luc van OostenRyck for numerous patches.
  14841. + * Nick Bane for numerous patches.
  14842. + * Nick Bane for 2.5/2.6 integration.
  14843. + * Andras Toth for mknod rdev issue.
  14844. + * Michael Fischer for finding the problem with inode inconsistency.
  14845. + * Some code bodily lifted from JFFS
  14846. + *
  14847. + * This program is free software; you can redistribute it and/or modify
  14848. + * it under the terms of the GNU General Public License version 2 as
  14849. + * published by the Free Software Foundation.
  14850. + */
  14851. +
  14852. +/*
  14853. + *
  14854. + * This is the file system front-end to YAFFS that hooks it up to
  14855. + * the VFS.
  14856. + *
  14857. + * Special notes:
  14858. + * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with
  14859. + * this superblock
  14860. + * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this
  14861. + * superblock
  14862. + * >> inode->u.generic_ip points to the associated struct yaffs_obj.
  14863. + */
  14864. +
  14865. +/*
  14866. + * There are two variants of the VFS glue code. This variant should compile
  14867. + * for any version of Linux.
  14868. + */
  14869. +#include <linux/version.h>
  14870. +
  14871. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
  14872. +#define YAFFS_COMPILE_BACKGROUND
  14873. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23))
  14874. +#define YAFFS_COMPILE_FREEZER
  14875. +#endif
  14876. +#endif
  14877. +
  14878. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
  14879. +#define YAFFS_COMPILE_EXPORTFS
  14880. +#endif
  14881. +
  14882. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
  14883. +#define YAFFS_USE_SETATTR_COPY
  14884. +#define YAFFS_USE_TRUNCATE_SETSIZE
  14885. +#endif
  14886. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
  14887. +#define YAFFS_HAS_EVICT_INODE
  14888. +#endif
  14889. +
  14890. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
  14891. +#define YAFFS_NEW_FOLLOW_LINK 1
  14892. +#else
  14893. +#define YAFFS_NEW_FOLLOW_LINK 0
  14894. +#endif
  14895. +
  14896. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
  14897. +#define YAFFS_HAS_WRITE_SUPER
  14898. +#endif
  14899. +
  14900. +
  14901. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  14902. +#include <linux/config.h>
  14903. +#endif
  14904. +
  14905. +#include <linux/kernel.h>
  14906. +#include <linux/module.h>
  14907. +#include <linux/slab.h>
  14908. +#include <linux/init.h>
  14909. +#include <linux/fs.h>
  14910. +#include <linux/proc_fs.h>
  14911. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
  14912. +#include <linux/smp_lock.h>
  14913. +#endif
  14914. +#include <linux/pagemap.h>
  14915. +#include <linux/mtd/mtd.h>
  14916. +#include <linux/interrupt.h>
  14917. +#include <linux/string.h>
  14918. +#include <linux/ctype.h>
  14919. +
  14920. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  14921. +#include <linux/namei.h>
  14922. +#endif
  14923. +
  14924. +#ifdef YAFFS_COMPILE_EXPORTFS
  14925. +#include <linux/exportfs.h>
  14926. +#endif
  14927. +
  14928. +#ifdef YAFFS_COMPILE_BACKGROUND
  14929. +#include <linux/kthread.h>
  14930. +#include <linux/delay.h>
  14931. +#endif
  14932. +#ifdef YAFFS_COMPILE_FREEZER
  14933. +#include <linux/freezer.h>
  14934. +#endif
  14935. +
  14936. +#include <asm/div64.h>
  14937. +
  14938. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  14939. +
  14940. +#include <linux/statfs.h>
  14941. +
  14942. +#define UnlockPage(p) unlock_page(p)
  14943. +#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
  14944. +
  14945. +/* FIXME: use sb->s_id instead ? */
  14946. +#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
  14947. +
  14948. +#else
  14949. +
  14950. +#include <linux/locks.h>
  14951. +#define BDEVNAME_SIZE 0
  14952. +#define yaffs_devname(sb, buf) kdevname(sb->s_dev)
  14953. +
  14954. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
  14955. +/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
  14956. +#define __user
  14957. +#endif
  14958. +
  14959. +#endif
  14960. +
  14961. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
  14962. +#define YPROC_ROOT (&proc_root)
  14963. +#else
  14964. +#define YPROC_ROOT NULL
  14965. +#endif
  14966. +
  14967. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
  14968. +#define Y_INIT_TIMER(a) init_timer(a)
  14969. +#else
  14970. +#define Y_INIT_TIMER(a) init_timer_on_stack(a)
  14971. +#endif
  14972. +
  14973. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
  14974. +#define YAFFS_USE_WRITE_BEGIN_END 1
  14975. +#else
  14976. +#define YAFFS_USE_WRITE_BEGIN_END 0
  14977. +#endif
  14978. +
  14979. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
  14980. +#define YAFFS_SUPER_HAS_DIRTY
  14981. +#endif
  14982. +
  14983. +
  14984. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
  14985. +#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0)
  14986. +#endif
  14987. +
  14988. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
  14989. +static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
  14990. +{
  14991. + uint64_t result = partition_size;
  14992. + do_div(result, block_size);
  14993. + return (uint32_t) result;
  14994. +}
  14995. +#else
  14996. +#define YCALCBLOCKS(s, b) ((s)/(b))
  14997. +#endif
  14998. +
  14999. +#include <linux/uaccess.h>
  15000. +#include <linux/mtd/mtd.h>
  15001. +
  15002. +#include "yportenv.h"
  15003. +#include "yaffs_trace.h"
  15004. +#include "yaffs_guts.h"
  15005. +#include "yaffs_attribs.h"
  15006. +
  15007. +#include "yaffs_linux.h"
  15008. +
  15009. +#include "yaffs_mtdif.h"
  15010. +#include "yaffs_packedtags2.h"
  15011. +#include "yaffs_getblockinfo.h"
  15012. +
  15013. +unsigned int yaffs_trace_mask =
  15014. + YAFFS_TRACE_BAD_BLOCKS |
  15015. + YAFFS_TRACE_ALWAYS |
  15016. + 0;
  15017. +
  15018. +unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
  15019. +unsigned int yaffs_auto_checkpoint = 1;
  15020. +unsigned int yaffs_gc_control = 1;
  15021. +unsigned int yaffs_bg_enable = 1;
  15022. +unsigned int yaffs_auto_select = 1;
  15023. +/* Module Parameters */
  15024. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  15025. +module_param(yaffs_trace_mask, uint, 0644);
  15026. +module_param(yaffs_wr_attempts, uint, 0644);
  15027. +module_param(yaffs_auto_checkpoint, uint, 0644);
  15028. +module_param(yaffs_gc_control, uint, 0644);
  15029. +module_param(yaffs_bg_enable, uint, 0644);
  15030. +#else
  15031. +MODULE_PARM(yaffs_trace_mask, "i");
  15032. +MODULE_PARM(yaffs_wr_attempts, "i");
  15033. +MODULE_PARM(yaffs_auto_checkpoint, "i");
  15034. +MODULE_PARM(yaffs_gc_control, "i");
  15035. +#endif
  15036. +
  15037. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
  15038. +/* use iget and read_inode */
  15039. +#define Y_IGET(sb, inum) iget((sb), (inum))
  15040. +
  15041. +#else
  15042. +/* Call local equivalent */
  15043. +#define YAFFS_USE_OWN_IGET
  15044. +#define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
  15045. +
  15046. +#endif
  15047. +
  15048. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
  15049. +#define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private)
  15050. +#else
  15051. +#define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
  15052. +#endif
  15053. +
  15054. +#define yaffs_inode_to_obj(iptr) \
  15055. + ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
  15056. +#define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode)
  15057. +
  15058. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  15059. +#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info)
  15060. +#else
  15061. +#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp)
  15062. +#endif
  15063. +
  15064. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  15065. +#define Y_CLEAR_INODE(i) clear_inode(i)
  15066. +#else
  15067. +#define Y_CLEAR_INODE(i) end_writeback(i)
  15068. +#endif
  15069. +
  15070. +
  15071. +#define update_dir_time(dir) do {\
  15072. + (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
  15073. + } while (0)
  15074. +
  15075. +static void yaffs_fill_inode_from_obj(struct inode *inode,
  15076. + struct yaffs_obj *obj);
  15077. +
  15078. +
  15079. +static void yaffs_gross_lock(struct yaffs_dev *dev)
  15080. +{
  15081. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locking %p", current);
  15082. + mutex_lock(&(yaffs_dev_to_lc(dev)->gross_lock));
  15083. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locked %p", current);
  15084. +}
  15085. +
  15086. +static void yaffs_gross_unlock(struct yaffs_dev *dev)
  15087. +{
  15088. + yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current);
  15089. + mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock));
  15090. +}
  15091. +
  15092. +
  15093. +static int yaffs_readpage_nolock(struct file *f, struct page *pg)
  15094. +{
  15095. + /* Lifted from jffs2 */
  15096. +
  15097. + struct yaffs_obj *obj;
  15098. + unsigned char *pg_buf;
  15099. + int ret;
  15100. + loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
  15101. + struct yaffs_dev *dev;
  15102. +
  15103. + yaffs_trace(YAFFS_TRACE_OS,
  15104. + "yaffs_readpage_nolock at %lld, size %08x",
  15105. + (long long)pos,
  15106. + (unsigned)PAGE_CACHE_SIZE);
  15107. +
  15108. + obj = yaffs_dentry_to_obj(f->f_dentry);
  15109. +
  15110. + dev = obj->my_dev;
  15111. +
  15112. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  15113. + BUG_ON(!PageLocked(pg));
  15114. +#else
  15115. + if (!PageLocked(pg))
  15116. + PAGE_BUG(pg);
  15117. +#endif
  15118. +
  15119. + pg_buf = kmap(pg);
  15120. + /* FIXME: Can kmap fail? */
  15121. +
  15122. + yaffs_gross_lock(dev);
  15123. +
  15124. + ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE);
  15125. +
  15126. + yaffs_gross_unlock(dev);
  15127. +
  15128. + if (ret >= 0)
  15129. + ret = 0;
  15130. +
  15131. + if (ret) {
  15132. + ClearPageUptodate(pg);
  15133. + SetPageError(pg);
  15134. + } else {
  15135. + SetPageUptodate(pg);
  15136. + ClearPageError(pg);
  15137. + }
  15138. +
  15139. + flush_dcache_page(pg);
  15140. + kunmap(pg);
  15141. +
  15142. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done");
  15143. + return ret;
  15144. +}
  15145. +
  15146. +static int yaffs_readpage_unlock(struct file *f, struct page *pg)
  15147. +{
  15148. + int ret = yaffs_readpage_nolock(f, pg);
  15149. + UnlockPage(pg);
  15150. + return ret;
  15151. +}
  15152. +
  15153. +static int yaffs_readpage(struct file *f, struct page *pg)
  15154. +{
  15155. + int ret;
  15156. +
  15157. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage");
  15158. + ret = yaffs_readpage_unlock(f, pg);
  15159. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done");
  15160. + return ret;
  15161. +}
  15162. +
  15163. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  15164. +#define YCRED_FSUID() from_kuid(&init_user_ns, current_fsuid())
  15165. +#define YCRED_FSGID() from_kgid(&init_user_ns, current_fsgid())
  15166. +#else
  15167. +#define YCRED_FSUID() YCRED(current)->fsuid
  15168. +#define YCRED_FSGID() YCRED(current)->fsgid
  15169. +
  15170. +static inline uid_t i_uid_read(const struct inode *inode)
  15171. +{
  15172. + return inode->i_uid;
  15173. +}
  15174. +
  15175. +static inline gid_t i_gid_read(const struct inode *inode)
  15176. +{
  15177. + return inode->i_gid;
  15178. +}
  15179. +
  15180. +static inline void i_uid_write(struct inode *inode, uid_t uid)
  15181. +{
  15182. + inode->i_uid = uid;
  15183. +}
  15184. +
  15185. +static inline void i_gid_write(struct inode *inode, gid_t gid)
  15186. +{
  15187. + inode->i_gid = gid;
  15188. +}
  15189. +#endif
  15190. +
  15191. +static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
  15192. +{
  15193. + struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
  15194. +
  15195. + if (lc)
  15196. + lc->dirty = val;
  15197. +
  15198. +# ifdef YAFFS_SUPER_HAS_DIRTY
  15199. + {
  15200. + struct super_block *sb = lc->super;
  15201. +
  15202. + if (sb)
  15203. + sb->s_dirt = val;
  15204. + }
  15205. +#endif
  15206. +
  15207. +}
  15208. +
  15209. +static void yaffs_set_super_dirty(struct yaffs_dev *dev)
  15210. +{
  15211. + yaffs_set_super_dirty_val(dev, 1);
  15212. +}
  15213. +
  15214. +static void yaffs_clear_super_dirty(struct yaffs_dev *dev)
  15215. +{
  15216. + yaffs_set_super_dirty_val(dev, 0);
  15217. +}
  15218. +
  15219. +static int yaffs_check_super_dirty(struct yaffs_dev *dev)
  15220. +{
  15221. + struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
  15222. +
  15223. + if (lc && lc->dirty)
  15224. + return 1;
  15225. +
  15226. +# ifdef YAFFS_SUPER_HAS_DIRTY
  15227. + {
  15228. + struct super_block *sb = lc->super;
  15229. +
  15230. + if (sb && sb->s_dirt)
  15231. + return 1;
  15232. + }
  15233. +#endif
  15234. + return 0;
  15235. +
  15236. +}
  15237. +
  15238. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  15239. +static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
  15240. +#else
  15241. +static int yaffs_writepage(struct page *page)
  15242. +#endif
  15243. +{
  15244. + struct yaffs_dev *dev;
  15245. + struct address_space *mapping = page->mapping;
  15246. + struct inode *inode;
  15247. + unsigned long end_index;
  15248. + char *buffer;
  15249. + struct yaffs_obj *obj;
  15250. + int n_written = 0;
  15251. + unsigned n_bytes;
  15252. + loff_t i_size;
  15253. +
  15254. + if (!mapping)
  15255. + BUG();
  15256. + inode = mapping->host;
  15257. + if (!inode)
  15258. + BUG();
  15259. + i_size = i_size_read(inode);
  15260. +
  15261. + end_index = i_size >> PAGE_CACHE_SHIFT;
  15262. +
  15263. + if (page->index < end_index)
  15264. + n_bytes = PAGE_CACHE_SIZE;
  15265. + else {
  15266. + n_bytes = i_size & (PAGE_CACHE_SIZE - 1);
  15267. +
  15268. + if (page->index > end_index || !n_bytes) {
  15269. + yaffs_trace(YAFFS_TRACE_OS,
  15270. + "yaffs_writepage at %lld, inode size = %lld!!",
  15271. + ((loff_t)page->index) << PAGE_CACHE_SHIFT,
  15272. + inode->i_size);
  15273. + yaffs_trace(YAFFS_TRACE_OS,
  15274. + " -> don't care!!");
  15275. +
  15276. + zero_user_segment(page, 0, PAGE_CACHE_SIZE);
  15277. + set_page_writeback(page);
  15278. + unlock_page(page);
  15279. + end_page_writeback(page);
  15280. + return 0;
  15281. + }
  15282. + }
  15283. +
  15284. + if (n_bytes != PAGE_CACHE_SIZE)
  15285. + zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE);
  15286. +
  15287. + get_page(page);
  15288. +
  15289. + buffer = kmap(page);
  15290. +
  15291. + obj = yaffs_inode_to_obj(inode);
  15292. + dev = obj->my_dev;
  15293. + yaffs_gross_lock(dev);
  15294. +
  15295. + yaffs_trace(YAFFS_TRACE_OS,
  15296. + "yaffs_writepage at %lld, size %08x",
  15297. + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes);
  15298. + yaffs_trace(YAFFS_TRACE_OS,
  15299. + "writepag0: obj = %lld, ino = %lld",
  15300. + obj->variant.file_variant.file_size, inode->i_size);
  15301. +
  15302. + n_written = yaffs_wr_file(obj, buffer,
  15303. + ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0);
  15304. +
  15305. + yaffs_set_super_dirty(dev);
  15306. +
  15307. + yaffs_trace(YAFFS_TRACE_OS,
  15308. + "writepag1: obj = %lld, ino = %lld",
  15309. + obj->variant.file_variant.file_size, inode->i_size);
  15310. +
  15311. + yaffs_gross_unlock(dev);
  15312. +
  15313. + kunmap(page);
  15314. + set_page_writeback(page);
  15315. + unlock_page(page);
  15316. + end_page_writeback(page);
  15317. + put_page(page);
  15318. +
  15319. + return (n_written == n_bytes) ? 0 : -ENOSPC;
  15320. +}
  15321. +
  15322. +/* Space holding and freeing is done to ensure we have space available for write_begin/end */
  15323. +/* For now we just assume few parallel writes and check against a small number. */
  15324. +/* Todo: need to do this with a counter to handle parallel reads better */
  15325. +
  15326. +static ssize_t yaffs_hold_space(struct file *f)
  15327. +{
  15328. + struct yaffs_obj *obj;
  15329. + struct yaffs_dev *dev;
  15330. +
  15331. + int n_free_chunks;
  15332. +
  15333. + obj = yaffs_dentry_to_obj(f->f_dentry);
  15334. +
  15335. + dev = obj->my_dev;
  15336. +
  15337. + yaffs_gross_lock(dev);
  15338. +
  15339. + n_free_chunks = yaffs_get_n_free_chunks(dev);
  15340. +
  15341. + yaffs_gross_unlock(dev);
  15342. +
  15343. + return (n_free_chunks > 20) ? 1 : 0;
  15344. +}
  15345. +
  15346. +static void yaffs_release_space(struct file *f)
  15347. +{
  15348. + struct yaffs_obj *obj;
  15349. + struct yaffs_dev *dev;
  15350. +
  15351. + obj = yaffs_dentry_to_obj(f->f_dentry);
  15352. +
  15353. + dev = obj->my_dev;
  15354. +
  15355. + yaffs_gross_lock(dev);
  15356. +
  15357. + yaffs_gross_unlock(dev);
  15358. +}
  15359. +
  15360. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  15361. +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
  15362. + loff_t pos, unsigned len, unsigned flags,
  15363. + struct page **pagep, void **fsdata)
  15364. +{
  15365. + struct page *pg = NULL;
  15366. + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  15367. +
  15368. + int ret = 0;
  15369. + int space_held = 0;
  15370. +
  15371. + /* Get a page */
  15372. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
  15373. + pg = grab_cache_page_write_begin(mapping, index, flags);
  15374. +#else
  15375. + pg = __grab_cache_page(mapping, index);
  15376. +#endif
  15377. +
  15378. + *pagep = pg;
  15379. + if (!pg) {
  15380. + ret = -ENOMEM;
  15381. + goto out;
  15382. + }
  15383. + yaffs_trace(YAFFS_TRACE_OS,
  15384. + "start yaffs_write_begin index %d(%x) uptodate %d",
  15385. + (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0);
  15386. +
  15387. + /* Get fs space */
  15388. + space_held = yaffs_hold_space(filp);
  15389. +
  15390. + if (!space_held) {
  15391. + ret = -ENOSPC;
  15392. + goto out;
  15393. + }
  15394. +
  15395. + /* Update page if required */
  15396. +
  15397. + if (!Page_Uptodate(pg))
  15398. + ret = yaffs_readpage_nolock(filp, pg);
  15399. +
  15400. + if (ret)
  15401. + goto out;
  15402. +
  15403. + /* Happy path return */
  15404. + yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok");
  15405. +
  15406. + return 0;
  15407. +
  15408. +out:
  15409. + yaffs_trace(YAFFS_TRACE_OS,
  15410. + "end yaffs_write_begin fail returning %d", ret);
  15411. + if (space_held)
  15412. + yaffs_release_space(filp);
  15413. + if (pg) {
  15414. + unlock_page(pg);
  15415. + page_cache_release(pg);
  15416. + }
  15417. + return ret;
  15418. +}
  15419. +
  15420. +#else
  15421. +
  15422. +static int yaffs_prepare_write(struct file *f, struct page *pg,
  15423. + unsigned offset, unsigned to)
  15424. +{
  15425. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write");
  15426. +
  15427. + if (!Page_Uptodate(pg))
  15428. + return yaffs_readpage_nolock(f, pg);
  15429. + return 0;
  15430. +}
  15431. +#endif
  15432. +
  15433. +
  15434. +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
  15435. + loff_t * pos)
  15436. +{
  15437. + struct yaffs_obj *obj;
  15438. + int n_written;
  15439. + loff_t ipos;
  15440. + struct inode *inode;
  15441. + struct yaffs_dev *dev;
  15442. +
  15443. + obj = yaffs_dentry_to_obj(f->f_dentry);
  15444. +
  15445. + if (!obj) {
  15446. + yaffs_trace(YAFFS_TRACE_OS,
  15447. + "yaffs_file_write: hey obj is null!");
  15448. + return -EINVAL;
  15449. + }
  15450. +
  15451. + dev = obj->my_dev;
  15452. +
  15453. + yaffs_gross_lock(dev);
  15454. +
  15455. + inode = f->f_dentry->d_inode;
  15456. +
  15457. + if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
  15458. + ipos = inode->i_size;
  15459. + else
  15460. + ipos = *pos;
  15461. +
  15462. + yaffs_trace(YAFFS_TRACE_OS,
  15463. + "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
  15464. + (unsigned)n, (unsigned)n, obj->obj_id, ipos);
  15465. +
  15466. + n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
  15467. +
  15468. + yaffs_set_super_dirty(dev);
  15469. +
  15470. + yaffs_trace(YAFFS_TRACE_OS,
  15471. + "yaffs_file_write: %d(%x) bytes written",
  15472. + (unsigned)n, (unsigned)n);
  15473. +
  15474. + if (n_written > 0) {
  15475. + ipos += n_written;
  15476. + *pos = ipos;
  15477. + if (ipos > inode->i_size) {
  15478. + inode->i_size = ipos;
  15479. + inode->i_blocks = (ipos + 511) >> 9;
  15480. +
  15481. + yaffs_trace(YAFFS_TRACE_OS,
  15482. + "yaffs_file_write size updated to %lld bytes, %d blocks",
  15483. + ipos, (int)(inode->i_blocks));
  15484. + }
  15485. +
  15486. + }
  15487. + yaffs_gross_unlock(dev);
  15488. + return (n_written == 0) && (n > 0) ? -ENOSPC : n_written;
  15489. +}
  15490. +
  15491. +
  15492. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  15493. +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
  15494. + loff_t pos, unsigned len, unsigned copied,
  15495. + struct page *pg, void *fsdadata)
  15496. +{
  15497. + int ret = 0;
  15498. + void *addr, *kva;
  15499. + uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
  15500. +
  15501. + kva = kmap(pg);
  15502. + addr = kva + offset_into_page;
  15503. +
  15504. + yaffs_trace(YAFFS_TRACE_OS,
  15505. + "yaffs_write_end addr %p pos %lld n_bytes %d",
  15506. + addr, pos, copied);
  15507. +
  15508. + ret = yaffs_file_write(filp, addr, copied, &pos);
  15509. +
  15510. + if (ret != copied) {
  15511. + yaffs_trace(YAFFS_TRACE_OS,
  15512. + "yaffs_write_end not same size ret %d copied %d",
  15513. + ret, copied);
  15514. + SetPageError(pg);
  15515. + }
  15516. +
  15517. + kunmap(pg);
  15518. +
  15519. + yaffs_release_space(filp);
  15520. + unlock_page(pg);
  15521. + page_cache_release(pg);
  15522. + return ret;
  15523. +}
  15524. +#else
  15525. +
  15526. +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
  15527. + unsigned to)
  15528. +{
  15529. + void *addr, *kva;
  15530. +
  15531. + loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
  15532. + int n_bytes = to - offset;
  15533. + int n_written;
  15534. +
  15535. + kva = kmap(pg);
  15536. + addr = kva + offset;
  15537. +
  15538. + yaffs_trace(YAFFS_TRACE_OS,
  15539. + "yaffs_commit_write addr %p pos %lld n_bytes %d",
  15540. + addr, pos, n_bytes);
  15541. +
  15542. + n_written = yaffs_file_write(f, addr, n_bytes, &pos);
  15543. +
  15544. + if (n_written != n_bytes) {
  15545. + yaffs_trace(YAFFS_TRACE_OS,
  15546. + "yaffs_commit_write not same size n_written %d n_bytes %d",
  15547. + n_written, n_bytes);
  15548. + SetPageError(pg);
  15549. + }
  15550. + kunmap(pg);
  15551. +
  15552. + yaffs_trace(YAFFS_TRACE_OS,
  15553. + "yaffs_commit_write returning %d",
  15554. + n_written == n_bytes ? 0 : n_written);
  15555. +
  15556. + return n_written == n_bytes ? 0 : n_written;
  15557. +}
  15558. +#endif
  15559. +
  15560. +static struct address_space_operations yaffs_file_address_operations = {
  15561. + .readpage = yaffs_readpage,
  15562. + .writepage = yaffs_writepage,
  15563. +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
  15564. + .write_begin = yaffs_write_begin,
  15565. + .write_end = yaffs_write_end,
  15566. +#else
  15567. + .prepare_write = yaffs_prepare_write,
  15568. + .commit_write = yaffs_commit_write,
  15569. +#endif
  15570. +};
  15571. +
  15572. +
  15573. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  15574. +static int yaffs_file_flush(struct file *file, fl_owner_t id)
  15575. +#else
  15576. +static int yaffs_file_flush(struct file *file)
  15577. +#endif
  15578. +{
  15579. + struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
  15580. +
  15581. + struct yaffs_dev *dev = obj->my_dev;
  15582. +
  15583. + yaffs_trace(YAFFS_TRACE_OS,
  15584. + "yaffs_file_flush object %d (%s)",
  15585. + obj->obj_id,
  15586. + obj->dirty ? "dirty" : "clean");
  15587. +
  15588. + yaffs_gross_lock(dev);
  15589. +
  15590. + yaffs_flush_file(obj, 1, 0);
  15591. +
  15592. + yaffs_gross_unlock(dev);
  15593. +
  15594. + return 0;
  15595. +}
  15596. +
  15597. +
  15598. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  15599. +static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync)
  15600. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
  15601. +static int yaffs_sync_object(struct file *file, int datasync)
  15602. +#else
  15603. +static int yaffs_sync_object(struct file *file, struct dentry *dentry,
  15604. + int datasync)
  15605. +#endif
  15606. +{
  15607. + struct yaffs_obj *obj;
  15608. + struct yaffs_dev *dev;
  15609. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
  15610. + struct dentry *dentry = file->f_path.dentry;
  15611. +#endif
  15612. +
  15613. + obj = yaffs_dentry_to_obj(dentry);
  15614. +
  15615. + dev = obj->my_dev;
  15616. +
  15617. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
  15618. + "yaffs_sync_object");
  15619. + yaffs_gross_lock(dev);
  15620. + yaffs_flush_file(obj, 1, datasync);
  15621. + yaffs_gross_unlock(dev);
  15622. + return 0;
  15623. +}
  15624. +
  15625. +
  15626. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
  15627. +static const struct file_operations yaffs_file_operations = {
  15628. + .read = do_sync_read,
  15629. + .write = do_sync_write,
  15630. + .aio_read = generic_file_aio_read,
  15631. + .aio_write = generic_file_aio_write,
  15632. + .mmap = generic_file_mmap,
  15633. + .flush = yaffs_file_flush,
  15634. + .fsync = yaffs_sync_object,
  15635. + .splice_read = generic_file_splice_read,
  15636. + .splice_write = generic_file_splice_write,
  15637. + .llseek = generic_file_llseek,
  15638. +};
  15639. +
  15640. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
  15641. +
  15642. +static const struct file_operations yaffs_file_operations = {
  15643. + .read = do_sync_read,
  15644. + .write = do_sync_write,
  15645. + .aio_read = generic_file_aio_read,
  15646. + .aio_write = generic_file_aio_write,
  15647. + .mmap = generic_file_mmap,
  15648. + .flush = yaffs_file_flush,
  15649. + .fsync = yaffs_sync_object,
  15650. + .sendfile = generic_file_sendfile,
  15651. +};
  15652. +
  15653. +#else
  15654. +
  15655. +static const struct file_operations yaffs_file_operations = {
  15656. + .read = generic_file_read,
  15657. + .write = generic_file_write,
  15658. + .mmap = generic_file_mmap,
  15659. + .flush = yaffs_file_flush,
  15660. + .fsync = yaffs_sync_object,
  15661. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  15662. + .sendfile = generic_file_sendfile,
  15663. +#endif
  15664. +};
  15665. +#endif
  15666. +
  15667. +
  15668. +
  15669. +
  15670. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
  15671. +static void zero_user_segment(struct page *page, unsigned start, unsigned end)
  15672. +{
  15673. + void *kaddr = kmap_atomic(page, KM_USER0);
  15674. + memset(kaddr + start, 0, end - start);
  15675. + kunmap_atomic(kaddr, KM_USER0);
  15676. + flush_dcache_page(page);
  15677. +}
  15678. +#endif
  15679. +
  15680. +
  15681. +static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
  15682. +{
  15683. +#ifdef YAFFS_USE_TRUNCATE_SETSIZE
  15684. + truncate_setsize(inode, newsize);
  15685. + return 0;
  15686. +#else
  15687. + truncate_inode_pages(&inode->i_data, newsize);
  15688. + return 0;
  15689. +#endif
  15690. +
  15691. +}
  15692. +
  15693. +
  15694. +static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
  15695. +{
  15696. +#ifdef YAFFS_USE_SETATTR_COPY
  15697. + setattr_copy(inode, attr);
  15698. + return 0;
  15699. +#else
  15700. + return inode_setattr(inode, attr);
  15701. +#endif
  15702. +
  15703. +}
  15704. +
  15705. +static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
  15706. +{
  15707. + struct inode *inode = dentry->d_inode;
  15708. + int error = 0;
  15709. + struct yaffs_dev *dev;
  15710. +
  15711. + yaffs_trace(YAFFS_TRACE_OS,
  15712. + "yaffs_setattr of object %d",
  15713. + yaffs_inode_to_obj(inode)->obj_id);
  15714. +#if 0
  15715. + /* Fail if a requested resize >= 2GB */
  15716. + if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
  15717. + error = -EINVAL;
  15718. +#endif
  15719. +
  15720. + if (error == 0)
  15721. + error = inode_change_ok(inode, attr);
  15722. + if (error == 0) {
  15723. + int result;
  15724. + if (!error) {
  15725. + error = yaffs_vfs_setattr(inode, attr);
  15726. + yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called");
  15727. + if (attr->ia_valid & ATTR_SIZE) {
  15728. + yaffs_vfs_setsize(inode, attr->ia_size);
  15729. + inode->i_blocks = (inode->i_size + 511) >> 9;
  15730. + }
  15731. + }
  15732. + dev = yaffs_inode_to_obj(inode)->my_dev;
  15733. + if (attr->ia_valid & ATTR_SIZE) {
  15734. + yaffs_trace(YAFFS_TRACE_OS,
  15735. + "resize to %d(%x)",
  15736. + (int)(attr->ia_size),
  15737. + (int)(attr->ia_size));
  15738. + }
  15739. + yaffs_gross_lock(dev);
  15740. + result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr);
  15741. + if (result == YAFFS_OK) {
  15742. + error = 0;
  15743. + } else {
  15744. + error = -EPERM;
  15745. + }
  15746. + yaffs_gross_unlock(dev);
  15747. +
  15748. + }
  15749. +
  15750. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error);
  15751. +
  15752. + return error;
  15753. +}
  15754. +
  15755. +static int yaffs_setxattr(struct dentry *dentry, const char *name,
  15756. + const void *value, size_t size, int flags)
  15757. +{
  15758. + struct inode *inode = dentry->d_inode;
  15759. + int error = 0;
  15760. + struct yaffs_dev *dev;
  15761. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  15762. +
  15763. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id);
  15764. +
  15765. + if (error == 0) {
  15766. + int result;
  15767. + dev = obj->my_dev;
  15768. + yaffs_gross_lock(dev);
  15769. + result = yaffs_set_xattrib(obj, name, value, size, flags);
  15770. + if (result == YAFFS_OK)
  15771. + error = 0;
  15772. + else if (result < 0)
  15773. + error = result;
  15774. + yaffs_gross_unlock(dev);
  15775. +
  15776. + }
  15777. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error);
  15778. +
  15779. + return error;
  15780. +}
  15781. +
  15782. +static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name,
  15783. + void *buff, size_t size)
  15784. +{
  15785. + struct inode *inode = dentry->d_inode;
  15786. + int error = 0;
  15787. + struct yaffs_dev *dev;
  15788. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  15789. +
  15790. + yaffs_trace(YAFFS_TRACE_OS,
  15791. + "yaffs_getxattr \"%s\" from object %d",
  15792. + name, obj->obj_id);
  15793. +
  15794. + if (error == 0) {
  15795. + dev = obj->my_dev;
  15796. + yaffs_gross_lock(dev);
  15797. + error = yaffs_get_xattrib(obj, name, buff, size);
  15798. + yaffs_gross_unlock(dev);
  15799. +
  15800. + }
  15801. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error);
  15802. +
  15803. + return error;
  15804. +}
  15805. +
  15806. +static int yaffs_removexattr(struct dentry *dentry, const char *name)
  15807. +{
  15808. + struct inode *inode = dentry->d_inode;
  15809. + int error = 0;
  15810. + struct yaffs_dev *dev;
  15811. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  15812. +
  15813. + yaffs_trace(YAFFS_TRACE_OS,
  15814. + "yaffs_removexattr of object %d", obj->obj_id);
  15815. +
  15816. + if (error == 0) {
  15817. + int result;
  15818. + dev = obj->my_dev;
  15819. + yaffs_gross_lock(dev);
  15820. + result = yaffs_remove_xattrib(obj, name);
  15821. + if (result == YAFFS_OK)
  15822. + error = 0;
  15823. + else if (result < 0)
  15824. + error = result;
  15825. + yaffs_gross_unlock(dev);
  15826. +
  15827. + }
  15828. + yaffs_trace(YAFFS_TRACE_OS,
  15829. + "yaffs_removexattr done returning %d", error);
  15830. +
  15831. + return error;
  15832. +}
  15833. +
  15834. +static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size)
  15835. +{
  15836. + struct inode *inode = dentry->d_inode;
  15837. + int error = 0;
  15838. + struct yaffs_dev *dev;
  15839. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  15840. +
  15841. + yaffs_trace(YAFFS_TRACE_OS,
  15842. + "yaffs_listxattr of object %d", obj->obj_id);
  15843. +
  15844. + if (error == 0) {
  15845. + dev = obj->my_dev;
  15846. + yaffs_gross_lock(dev);
  15847. + error = yaffs_list_xattrib(obj, buff, size);
  15848. + yaffs_gross_unlock(dev);
  15849. +
  15850. + }
  15851. + yaffs_trace(YAFFS_TRACE_OS,
  15852. + "yaffs_listxattr done returning %d", error);
  15853. +
  15854. + return error;
  15855. +}
  15856. +
  15857. +
  15858. +static const struct inode_operations yaffs_file_inode_operations = {
  15859. + .setattr = yaffs_setattr,
  15860. + .setxattr = yaffs_setxattr,
  15861. + .getxattr = yaffs_getxattr,
  15862. + .listxattr = yaffs_listxattr,
  15863. + .removexattr = yaffs_removexattr,
  15864. +};
  15865. +
  15866. +
  15867. +static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
  15868. + int buflen)
  15869. +{
  15870. + unsigned char *alias;
  15871. + int ret;
  15872. +
  15873. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  15874. +
  15875. + yaffs_gross_lock(dev);
  15876. +
  15877. + alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
  15878. +
  15879. + yaffs_gross_unlock(dev);
  15880. +
  15881. + if (!alias)
  15882. + return -ENOMEM;
  15883. +
  15884. + ret = vfs_readlink(dentry, buffer, buflen, alias);
  15885. + kfree(alias);
  15886. + return ret;
  15887. +}
  15888. +
  15889. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  15890. +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
  15891. +{
  15892. + void *ret;
  15893. +#else
  15894. +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
  15895. +{
  15896. + int ret
  15897. +#endif
  15898. + unsigned char *alias;
  15899. + int ret_int = 0;
  15900. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  15901. +
  15902. + yaffs_gross_lock(dev);
  15903. +
  15904. + alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
  15905. + yaffs_gross_unlock(dev);
  15906. +
  15907. + if (!alias) {
  15908. + ret_int = -ENOMEM;
  15909. + goto out;
  15910. + }
  15911. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  15912. + nd_set_link(nd, alias);
  15913. + ret = alias;
  15914. +out:
  15915. + if (ret_int)
  15916. + ret = ERR_PTR(ret_int);
  15917. + return ret;
  15918. +#else
  15919. + ret = vfs_follow_link(nd, alias);
  15920. + kfree(alias);
  15921. +out:
  15922. + if (ret_int)
  15923. + ret = ret_int;
  15924. + return ret;
  15925. +#endif
  15926. +}
  15927. +
  15928. +
  15929. +#ifdef YAFFS_HAS_PUT_INODE
  15930. +
  15931. +/* For now put inode is just for debugging
  15932. + * Put inode is called when the inode **structure** is put.
  15933. + */
  15934. +static void yaffs_put_inode(struct inode *inode)
  15935. +{
  15936. + yaffs_trace(YAFFS_TRACE_OS,
  15937. + "yaffs_put_inode: ino %d, count %d"),
  15938. + (int)inode->i_ino, atomic_read(&inode->i_count);
  15939. +
  15940. +}
  15941. +#endif
  15942. +
  15943. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  15944. +void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias)
  15945. +{
  15946. + kfree(alias);
  15947. +}
  15948. +#endif
  15949. +
  15950. +static const struct inode_operations yaffs_symlink_inode_operations = {
  15951. + .readlink = yaffs_readlink,
  15952. + .follow_link = yaffs_follow_link,
  15953. +#if (YAFFS_NEW_FOLLOW_LINK == 1)
  15954. + .put_link = yaffs_put_link,
  15955. +#endif
  15956. + .setattr = yaffs_setattr,
  15957. + .setxattr = yaffs_setxattr,
  15958. + .getxattr = yaffs_getxattr,
  15959. + .listxattr = yaffs_listxattr,
  15960. + .removexattr = yaffs_removexattr,
  15961. +};
  15962. +
  15963. +#ifdef YAFFS_USE_OWN_IGET
  15964. +
  15965. +static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
  15966. +{
  15967. + struct inode *inode;
  15968. + struct yaffs_obj *obj;
  15969. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  15970. +
  15971. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino);
  15972. +
  15973. + inode = iget_locked(sb, ino);
  15974. + if (!inode)
  15975. + return ERR_PTR(-ENOMEM);
  15976. + if (!(inode->i_state & I_NEW))
  15977. + return inode;
  15978. +
  15979. + /* NB This is called as a side effect of other functions, but
  15980. + * we had to release the lock to prevent deadlocks, so
  15981. + * need to lock again.
  15982. + */
  15983. +
  15984. + yaffs_gross_lock(dev);
  15985. +
  15986. + obj = yaffs_find_by_number(dev, inode->i_ino);
  15987. +
  15988. + yaffs_fill_inode_from_obj(inode, obj);
  15989. +
  15990. + yaffs_gross_unlock(dev);
  15991. +
  15992. + unlock_new_inode(inode);
  15993. + return inode;
  15994. +}
  15995. +
  15996. +#else
  15997. +
  15998. +static void yaffs_read_inode(struct inode *inode)
  15999. +{
  16000. + /* NB This is called as a side effect of other functions, but
  16001. + * we had to release the lock to prevent deadlocks, so
  16002. + * need to lock again.
  16003. + */
  16004. +
  16005. + struct yaffs_obj *obj;
  16006. + struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb);
  16007. +
  16008. + yaffs_trace(YAFFS_TRACE_OS,
  16009. + "yaffs_read_inode for %d", (int)inode->i_ino);
  16010. +
  16011. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  16012. + yaffs_gross_lock(dev);
  16013. +
  16014. + obj = yaffs_find_by_number(dev, inode->i_ino);
  16015. +
  16016. + yaffs_fill_inode_from_obj(inode, obj);
  16017. +
  16018. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  16019. + yaffs_gross_unlock(dev);
  16020. +}
  16021. +
  16022. +#endif
  16023. +
  16024. +
  16025. +
  16026. +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
  16027. + struct yaffs_obj *obj)
  16028. +{
  16029. + struct inode *inode;
  16030. +
  16031. + if (!sb) {
  16032. + yaffs_trace(YAFFS_TRACE_OS,
  16033. + "yaffs_get_inode for NULL super_block!!");
  16034. + return NULL;
  16035. +
  16036. + }
  16037. +
  16038. + if (!obj) {
  16039. + yaffs_trace(YAFFS_TRACE_OS,
  16040. + "yaffs_get_inode for NULL object!!");
  16041. + return NULL;
  16042. +
  16043. + }
  16044. +
  16045. + yaffs_trace(YAFFS_TRACE_OS,
  16046. + "yaffs_get_inode for object %d", obj->obj_id);
  16047. +
  16048. + inode = Y_IGET(sb, obj->obj_id);
  16049. + if (IS_ERR(inode))
  16050. + return NULL;
  16051. +
  16052. + /* NB Side effect: iget calls back to yaffs_read_inode(). */
  16053. + /* iget also increments the inode's i_count */
  16054. + /* NB You can't be holding gross_lock or deadlock will happen! */
  16055. +
  16056. + return inode;
  16057. +}
  16058. +
  16059. +
  16060. +
  16061. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
  16062. +#define YCRED(x) x
  16063. +#else
  16064. +#define YCRED(x) (x->cred)
  16065. +#endif
  16066. +
  16067. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  16068. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
  16069. + dev_t rdev)
  16070. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  16071. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
  16072. + dev_t rdev)
  16073. +#else
  16074. +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
  16075. + int rdev)
  16076. +#endif
  16077. +{
  16078. + struct inode *inode;
  16079. +
  16080. + struct yaffs_obj *obj = NULL;
  16081. + struct yaffs_dev *dev;
  16082. +
  16083. + struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
  16084. +
  16085. + int error = -ENOSPC;
  16086. + uid_t uid = YCRED_FSUID();
  16087. + gid_t gid =
  16088. + (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
  16089. +
  16090. + if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
  16091. + mode |= S_ISGID;
  16092. +
  16093. + if (parent) {
  16094. + yaffs_trace(YAFFS_TRACE_OS,
  16095. + "yaffs_mknod: parent object %d type %d",
  16096. + parent->obj_id, parent->variant_type);
  16097. + } else {
  16098. + yaffs_trace(YAFFS_TRACE_OS,
  16099. + "yaffs_mknod: could not get parent object");
  16100. + return -EPERM;
  16101. + }
  16102. +
  16103. + yaffs_trace(YAFFS_TRACE_OS,
  16104. + "yaffs_mknod: making oject for %s, mode %x dev %x",
  16105. + dentry->d_name.name, mode, rdev);
  16106. +
  16107. + dev = parent->my_dev;
  16108. +
  16109. + yaffs_gross_lock(dev);
  16110. +
  16111. + switch (mode & S_IFMT) {
  16112. + default:
  16113. + /* Special (socket, fifo, device...) */
  16114. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making special");
  16115. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  16116. + obj =
  16117. + yaffs_create_special(parent, dentry->d_name.name, mode, uid,
  16118. + gid, old_encode_dev(rdev));
  16119. +#else
  16120. + obj =
  16121. + yaffs_create_special(parent, dentry->d_name.name, mode, uid,
  16122. + gid, rdev);
  16123. +#endif
  16124. + break;
  16125. + case S_IFREG: /* file */
  16126. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making file");
  16127. + obj = yaffs_create_file(parent, dentry->d_name.name, mode, uid,
  16128. + gid);
  16129. + break;
  16130. + case S_IFDIR: /* directory */
  16131. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making directory");
  16132. + obj = yaffs_create_dir(parent, dentry->d_name.name, mode,
  16133. + uid, gid);
  16134. + break;
  16135. + case S_IFLNK: /* symlink */
  16136. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink");
  16137. + obj = NULL; /* Do we ever get here? */
  16138. + break;
  16139. + }
  16140. +
  16141. + /* Can not call yaffs_get_inode() with gross lock held */
  16142. + yaffs_gross_unlock(dev);
  16143. +
  16144. + if (obj) {
  16145. + inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
  16146. + d_instantiate(dentry, inode);
  16147. + update_dir_time(dir);
  16148. + yaffs_trace(YAFFS_TRACE_OS,
  16149. + "yaffs_mknod created object %d count = %d",
  16150. + obj->obj_id, atomic_read(&inode->i_count));
  16151. + error = 0;
  16152. + yaffs_fill_inode_from_obj(dir, parent);
  16153. + } else {
  16154. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object");
  16155. + error = -ENOMEM;
  16156. + }
  16157. +
  16158. + return error;
  16159. +}
  16160. +
  16161. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  16162. +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  16163. +#else
  16164. +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  16165. +#endif
  16166. +{
  16167. + int ret_val;
  16168. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir");
  16169. + ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
  16170. + return ret_val;
  16171. +}
  16172. +
  16173. +
  16174. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  16175. +static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  16176. + bool dummy)
  16177. +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
  16178. +static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  16179. + struct nameidata *n)
  16180. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  16181. +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
  16182. + struct nameidata *n)
  16183. +#else
  16184. +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
  16185. +#endif
  16186. +{
  16187. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_create");
  16188. + return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
  16189. +}
  16190. +
  16191. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  16192. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
  16193. + unsigned int dummy)
  16194. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  16195. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
  16196. + struct nameidata *n)
  16197. +#else
  16198. +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
  16199. +#endif
  16200. +{
  16201. + struct yaffs_obj *obj;
  16202. + struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */
  16203. +
  16204. + struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev;
  16205. +
  16206. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  16207. + yaffs_gross_lock(dev);
  16208. +
  16209. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s",
  16210. + yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name);
  16211. +
  16212. + obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name);
  16213. +
  16214. + obj = yaffs_get_equivalent_obj(obj); /* in case it was a hardlink */
  16215. +
  16216. + /* Can't hold gross lock when calling yaffs_get_inode() */
  16217. + if (current != yaffs_dev_to_lc(dev)->readdir_process)
  16218. + yaffs_gross_unlock(dev);
  16219. +
  16220. + if (obj) {
  16221. + yaffs_trace(YAFFS_TRACE_OS,
  16222. + "yaffs_lookup found %d", obj->obj_id);
  16223. +
  16224. + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
  16225. + } else {
  16226. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found");
  16227. +
  16228. + }
  16229. +
  16230. +/* added NCB for 2.5/6 compatability - forces add even if inode is
  16231. + * NULL which creates dentry hash */
  16232. + d_add(dentry, inode);
  16233. +
  16234. + return NULL;
  16235. +}
  16236. +
  16237. +/*
  16238. + * Create a link...
  16239. + */
  16240. +static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
  16241. + struct dentry *dentry)
  16242. +{
  16243. + struct inode *inode = old_dentry->d_inode;
  16244. + struct yaffs_obj *obj = NULL;
  16245. + struct yaffs_obj *link = NULL;
  16246. + struct yaffs_dev *dev;
  16247. +
  16248. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_link");
  16249. +
  16250. + obj = yaffs_inode_to_obj(inode);
  16251. + dev = obj->my_dev;
  16252. +
  16253. + yaffs_gross_lock(dev);
  16254. +
  16255. + if (!S_ISDIR(inode->i_mode)) /* Don't link directories */
  16256. + link =
  16257. + yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name,
  16258. + obj);
  16259. +
  16260. + if (link) {
  16261. + set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj));
  16262. + d_instantiate(dentry, old_dentry->d_inode);
  16263. + atomic_inc(&old_dentry->d_inode->i_count);
  16264. + yaffs_trace(YAFFS_TRACE_OS,
  16265. + "yaffs_link link count %d i_count %d",
  16266. + old_dentry->d_inode->i_nlink,
  16267. + atomic_read(&old_dentry->d_inode->i_count));
  16268. + }
  16269. +
  16270. + yaffs_gross_unlock(dev);
  16271. +
  16272. + if (link) {
  16273. + update_dir_time(dir);
  16274. + return 0;
  16275. + }
  16276. +
  16277. + return -EPERM;
  16278. +}
  16279. +
  16280. +static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
  16281. + const char *symname)
  16282. +{
  16283. + struct yaffs_obj *obj;
  16284. + struct yaffs_dev *dev;
  16285. + uid_t uid = YCRED_FSUID();
  16286. + gid_t gid =
  16287. + (dir->i_mode & S_ISGID) ? i_gid_read(dir) : YCRED_FSGID();
  16288. +
  16289. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
  16290. +
  16291. + if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) >
  16292. + YAFFS_MAX_NAME_LENGTH)
  16293. + return -ENAMETOOLONG;
  16294. +
  16295. + if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) >
  16296. + YAFFS_MAX_ALIAS_LENGTH)
  16297. + return -ENAMETOOLONG;
  16298. +
  16299. + dev = yaffs_inode_to_obj(dir)->my_dev;
  16300. + yaffs_gross_lock(dev);
  16301. + obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name,
  16302. + S_IFLNK | S_IRWXUGO, uid, gid, symname);
  16303. + yaffs_gross_unlock(dev);
  16304. +
  16305. + if (obj) {
  16306. + struct inode *inode;
  16307. +
  16308. + inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
  16309. + d_instantiate(dentry, inode);
  16310. + update_dir_time(dir);
  16311. + yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
  16312. + return 0;
  16313. + } else {
  16314. + yaffs_trace(YAFFS_TRACE_OS, "symlink not created");
  16315. + }
  16316. +
  16317. + return -ENOMEM;
  16318. +}
  16319. +
  16320. +/*
  16321. + * The VFS layer already does all the dentry stuff for rename.
  16322. + *
  16323. + * NB: POSIX says you can rename an object over an old object of the same name
  16324. + */
  16325. +static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
  16326. + struct inode *new_dir, struct dentry *new_dentry)
  16327. +{
  16328. + struct yaffs_dev *dev;
  16329. + int ret_val = YAFFS_FAIL;
  16330. + struct yaffs_obj *target;
  16331. +
  16332. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename");
  16333. + dev = yaffs_inode_to_obj(old_dir)->my_dev;
  16334. +
  16335. + yaffs_gross_lock(dev);
  16336. +
  16337. + /* Check if the target is an existing directory that is not empty. */
  16338. + target = yaffs_find_by_name(yaffs_inode_to_obj(new_dir),
  16339. + new_dentry->d_name.name);
  16340. +
  16341. + if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
  16342. + !list_empty(&target->variant.dir_variant.children)) {
  16343. +
  16344. + yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir");
  16345. +
  16346. + ret_val = YAFFS_FAIL;
  16347. + } else {
  16348. + /* Now does unlinking internally using shadowing mechanism */
  16349. + yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj");
  16350. +
  16351. + ret_val = yaffs_rename_obj(yaffs_inode_to_obj(old_dir),
  16352. + old_dentry->d_name.name,
  16353. + yaffs_inode_to_obj(new_dir),
  16354. + new_dentry->d_name.name);
  16355. + }
  16356. + yaffs_gross_unlock(dev);
  16357. +
  16358. + if (ret_val == YAFFS_OK) {
  16359. + if (target)
  16360. + inode_dec_link_count(new_dentry->d_inode);
  16361. +
  16362. + update_dir_time(old_dir);
  16363. + if (old_dir != new_dir)
  16364. + update_dir_time(new_dir);
  16365. + return 0;
  16366. + } else {
  16367. + return -ENOTEMPTY;
  16368. + }
  16369. +}
  16370. +
  16371. +
  16372. +
  16373. +
  16374. +static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
  16375. +{
  16376. + int ret_val;
  16377. +
  16378. + struct yaffs_dev *dev;
  16379. + struct yaffs_obj *obj;
  16380. +
  16381. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_unlink %d:%s",
  16382. + (int)(dir->i_ino), dentry->d_name.name);
  16383. + obj = yaffs_inode_to_obj(dir);
  16384. + dev = obj->my_dev;
  16385. +
  16386. + yaffs_gross_lock(dev);
  16387. +
  16388. + ret_val = yaffs_unlinker(obj, dentry->d_name.name);
  16389. +
  16390. + if (ret_val == YAFFS_OK) {
  16391. + inode_dec_link_count(dentry->d_inode);
  16392. + dir->i_version++;
  16393. + yaffs_gross_unlock(dev);
  16394. + update_dir_time(dir);
  16395. + return 0;
  16396. + }
  16397. + yaffs_gross_unlock(dev);
  16398. + return -ENOTEMPTY;
  16399. +}
  16400. +
  16401. +
  16402. +
  16403. +static const struct inode_operations yaffs_dir_inode_operations = {
  16404. + .create = yaffs_create,
  16405. + .lookup = yaffs_lookup,
  16406. + .link = yaffs_link,
  16407. + .unlink = yaffs_unlink,
  16408. + .symlink = yaffs_symlink,
  16409. + .mkdir = yaffs_mkdir,
  16410. + .rmdir = yaffs_unlink,
  16411. + .mknod = yaffs_mknod,
  16412. + .rename = yaffs_rename,
  16413. + .setattr = yaffs_setattr,
  16414. + .setxattr = yaffs_setxattr,
  16415. + .getxattr = yaffs_getxattr,
  16416. + .listxattr = yaffs_listxattr,
  16417. + .removexattr = yaffs_removexattr,
  16418. +};
  16419. +
  16420. +/*-----------------------------------------------------------------*/
  16421. +/* Directory search context allows us to unlock access to yaffs during
  16422. + * filldir without causing problems with the directory being modified.
  16423. + * This is similar to the tried and tested mechanism used in yaffs direct.
  16424. + *
  16425. + * A search context iterates along a doubly linked list of siblings in the
  16426. + * directory. If the iterating object is deleted then this would corrupt
  16427. + * the list iteration, likely causing a crash. The search context avoids
  16428. + * this by using the remove_obj_fn to move the search context to the
  16429. + * next object before the object is deleted.
  16430. + *
  16431. + * Many readdirs (and thus seach conexts) may be alive simulateously so
  16432. + * each struct yaffs_dev has a list of these.
  16433. + *
  16434. + * A seach context lives for the duration of a readdir.
  16435. + *
  16436. + * All these functions must be called while yaffs is locked.
  16437. + */
  16438. +
  16439. +struct yaffs_search_context {
  16440. + struct yaffs_dev *dev;
  16441. + struct yaffs_obj *dir_obj;
  16442. + struct yaffs_obj *next_return;
  16443. + struct list_head others;
  16444. +};
  16445. +
  16446. +/*
  16447. + * yaffs_new_search() creates a new search context, initialises it and
  16448. + * adds it to the device's search context list.
  16449. + *
  16450. + * Called at start of readdir.
  16451. + */
  16452. +static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir)
  16453. +{
  16454. + struct yaffs_dev *dev = dir->my_dev;
  16455. + struct yaffs_search_context *sc =
  16456. + kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS);
  16457. + if (sc) {
  16458. + sc->dir_obj = dir;
  16459. + sc->dev = dev;
  16460. + if (list_empty(&sc->dir_obj->variant.dir_variant.children))
  16461. + sc->next_return = NULL;
  16462. + else
  16463. + sc->next_return =
  16464. + list_entry(dir->variant.dir_variant.children.next,
  16465. + struct yaffs_obj, siblings);
  16466. + INIT_LIST_HEAD(&sc->others);
  16467. + list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts));
  16468. + }
  16469. + return sc;
  16470. +}
  16471. +
  16472. +/*
  16473. + * yaffs_search_end() disposes of a search context and cleans up.
  16474. + */
  16475. +static void yaffs_search_end(struct yaffs_search_context *sc)
  16476. +{
  16477. + if (sc) {
  16478. + list_del(&sc->others);
  16479. + kfree(sc);
  16480. + }
  16481. +}
  16482. +
  16483. +/*
  16484. + * yaffs_search_advance() moves a search context to the next object.
  16485. + * Called when the search iterates or when an object removal causes
  16486. + * the search context to be moved to the next object.
  16487. + */
  16488. +static void yaffs_search_advance(struct yaffs_search_context *sc)
  16489. +{
  16490. + if (!sc)
  16491. + return;
  16492. +
  16493. + if (sc->next_return == NULL ||
  16494. + list_empty(&sc->dir_obj->variant.dir_variant.children))
  16495. + sc->next_return = NULL;
  16496. + else {
  16497. + struct list_head *next = sc->next_return->siblings.next;
  16498. +
  16499. + if (next == &sc->dir_obj->variant.dir_variant.children)
  16500. + sc->next_return = NULL; /* end of list */
  16501. + else
  16502. + sc->next_return =
  16503. + list_entry(next, struct yaffs_obj, siblings);
  16504. + }
  16505. +}
  16506. +
  16507. +/*
  16508. + * yaffs_remove_obj_callback() is called when an object is unlinked.
  16509. + * We check open search contexts and advance any which are currently
  16510. + * on the object being iterated.
  16511. + */
  16512. +static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
  16513. +{
  16514. +
  16515. + struct list_head *i;
  16516. + struct yaffs_search_context *sc;
  16517. + struct list_head *search_contexts =
  16518. + &(yaffs_dev_to_lc(obj->my_dev)->search_contexts);
  16519. +
  16520. + /* Iterate through the directory search contexts.
  16521. + * If any are currently on the object being removed, then advance
  16522. + * the search context to the next object to prevent a hanging pointer.
  16523. + */
  16524. + list_for_each(i, search_contexts) {
  16525. + sc = list_entry(i, struct yaffs_search_context, others);
  16526. + if (sc->next_return == obj)
  16527. + yaffs_search_advance(sc);
  16528. + }
  16529. +
  16530. +}
  16531. +
  16532. +
  16533. +/*-----------------------------------------------------------------*/
  16534. +
  16535. +static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
  16536. +{
  16537. + struct yaffs_obj *obj;
  16538. + struct yaffs_dev *dev;
  16539. + struct yaffs_search_context *sc;
  16540. + struct inode *inode = f->f_dentry->d_inode;
  16541. + unsigned long offset, curoffs;
  16542. + struct yaffs_obj *l;
  16543. + int ret_val = 0;
  16544. +
  16545. + char name[YAFFS_MAX_NAME_LENGTH + 1];
  16546. +
  16547. + obj = yaffs_dentry_to_obj(f->f_dentry);
  16548. + dev = obj->my_dev;
  16549. +
  16550. + yaffs_gross_lock(dev);
  16551. +
  16552. + yaffs_dev_to_lc(dev)->readdir_process = current;
  16553. +
  16554. + offset = f->f_pos;
  16555. +
  16556. + sc = yaffs_new_search(obj);
  16557. + if (!sc) {
  16558. + ret_val = -ENOMEM;
  16559. + goto out;
  16560. + }
  16561. +
  16562. + yaffs_trace(YAFFS_TRACE_OS,
  16563. + "yaffs_readdir: starting at %d", (int)offset);
  16564. +
  16565. + if (offset == 0) {
  16566. + yaffs_trace(YAFFS_TRACE_OS,
  16567. + "yaffs_readdir: entry . ino %d",
  16568. + (int)inode->i_ino);
  16569. + yaffs_gross_unlock(dev);
  16570. + if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) {
  16571. + yaffs_gross_lock(dev);
  16572. + goto out;
  16573. + }
  16574. + yaffs_gross_lock(dev);
  16575. + offset++;
  16576. + f->f_pos++;
  16577. + }
  16578. + if (offset == 1) {
  16579. + yaffs_trace(YAFFS_TRACE_OS,
  16580. + "yaffs_readdir: entry .. ino %d",
  16581. + (int)f->f_dentry->d_parent->d_inode->i_ino);
  16582. + yaffs_gross_unlock(dev);
  16583. + if (filldir(dirent, "..", 2, offset,
  16584. + f->f_dentry->d_parent->d_inode->i_ino,
  16585. + DT_DIR) < 0) {
  16586. + yaffs_gross_lock(dev);
  16587. + goto out;
  16588. + }
  16589. + yaffs_gross_lock(dev);
  16590. + offset++;
  16591. + f->f_pos++;
  16592. + }
  16593. +
  16594. + curoffs = 1;
  16595. +
  16596. + /* If the directory has changed since the open or last call to
  16597. + readdir, rewind to after the 2 canned entries. */
  16598. + if (f->f_version != inode->i_version) {
  16599. + offset = 2;
  16600. + f->f_pos = offset;
  16601. + f->f_version = inode->i_version;
  16602. + }
  16603. +
  16604. + while (sc->next_return) {
  16605. + curoffs++;
  16606. + l = sc->next_return;
  16607. + if (curoffs >= offset) {
  16608. + int this_inode = yaffs_get_obj_inode(l);
  16609. + int this_type = yaffs_get_obj_type(l);
  16610. +
  16611. + yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
  16612. + yaffs_trace(YAFFS_TRACE_OS,
  16613. + "yaffs_readdir: %s inode %d",
  16614. + name, yaffs_get_obj_inode(l));
  16615. +
  16616. + yaffs_gross_unlock(dev);
  16617. +
  16618. + if (filldir(dirent,
  16619. + name,
  16620. + strlen(name),
  16621. + offset, this_inode, this_type) < 0) {
  16622. + yaffs_gross_lock(dev);
  16623. + goto out;
  16624. + }
  16625. +
  16626. + yaffs_gross_lock(dev);
  16627. +
  16628. + offset++;
  16629. + f->f_pos++;
  16630. + }
  16631. + yaffs_search_advance(sc);
  16632. + }
  16633. +
  16634. +out:
  16635. + yaffs_search_end(sc);
  16636. + yaffs_dev_to_lc(dev)->readdir_process = NULL;
  16637. + yaffs_gross_unlock(dev);
  16638. +
  16639. + return ret_val;
  16640. +}
  16641. +
  16642. +static const struct file_operations yaffs_dir_operations = {
  16643. + .read = generic_read_dir,
  16644. + .readdir = yaffs_readdir,
  16645. + .fsync = yaffs_sync_object,
  16646. + .llseek = generic_file_llseek,
  16647. +};
  16648. +
  16649. +static void yaffs_fill_inode_from_obj(struct inode *inode,
  16650. + struct yaffs_obj *obj)
  16651. +{
  16652. + if (inode && obj) {
  16653. +
  16654. + /* Check mode against the variant type and attempt to repair if broken. */
  16655. + u32 mode = obj->yst_mode;
  16656. + switch (obj->variant_type) {
  16657. + case YAFFS_OBJECT_TYPE_FILE:
  16658. + if (!S_ISREG(mode)) {
  16659. + obj->yst_mode &= ~S_IFMT;
  16660. + obj->yst_mode |= S_IFREG;
  16661. + }
  16662. +
  16663. + break;
  16664. + case YAFFS_OBJECT_TYPE_SYMLINK:
  16665. + if (!S_ISLNK(mode)) {
  16666. + obj->yst_mode &= ~S_IFMT;
  16667. + obj->yst_mode |= S_IFLNK;
  16668. + }
  16669. +
  16670. + break;
  16671. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  16672. + if (!S_ISDIR(mode)) {
  16673. + obj->yst_mode &= ~S_IFMT;
  16674. + obj->yst_mode |= S_IFDIR;
  16675. + }
  16676. +
  16677. + break;
  16678. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  16679. + case YAFFS_OBJECT_TYPE_HARDLINK:
  16680. + case YAFFS_OBJECT_TYPE_SPECIAL:
  16681. + default:
  16682. + /* TODO? */
  16683. + break;
  16684. + }
  16685. +
  16686. + inode->i_flags |= S_NOATIME;
  16687. +
  16688. + inode->i_ino = obj->obj_id;
  16689. + inode->i_mode = obj->yst_mode;
  16690. + i_uid_write(inode, obj->yst_uid);
  16691. + i_gid_write(inode, obj->yst_gid);
  16692. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  16693. + inode->i_blksize = inode->i_sb->s_blocksize;
  16694. +#endif
  16695. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  16696. +
  16697. + inode->i_rdev = old_decode_dev(obj->yst_rdev);
  16698. + inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
  16699. + inode->i_atime.tv_nsec = 0;
  16700. + inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
  16701. + inode->i_mtime.tv_nsec = 0;
  16702. + inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
  16703. + inode->i_ctime.tv_nsec = 0;
  16704. +#else
  16705. + inode->i_rdev = obj->yst_rdev;
  16706. + inode->i_atime = obj->yst_atime;
  16707. + inode->i_mtime = obj->yst_mtime;
  16708. + inode->i_ctime = obj->yst_ctime;
  16709. +#endif
  16710. + inode->i_size = yaffs_get_obj_length(obj);
  16711. + inode->i_blocks = (inode->i_size + 511) >> 9;
  16712. +
  16713. + set_nlink(inode, yaffs_get_obj_link_count(obj));
  16714. +
  16715. + yaffs_trace(YAFFS_TRACE_OS,
  16716. + "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
  16717. + inode->i_mode, i_uid_read(inode), i_gid_read(inode),
  16718. + inode->i_size, atomic_read(&inode->i_count));
  16719. +
  16720. + switch (obj->yst_mode & S_IFMT) {
  16721. + default: /* fifo, device or socket */
  16722. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  16723. + init_special_inode(inode, obj->yst_mode,
  16724. + old_decode_dev(obj->yst_rdev));
  16725. +#else
  16726. + init_special_inode(inode, obj->yst_mode,
  16727. + (dev_t) (obj->yst_rdev));
  16728. +#endif
  16729. + break;
  16730. + case S_IFREG: /* file */
  16731. + inode->i_op = &yaffs_file_inode_operations;
  16732. + inode->i_fop = &yaffs_file_operations;
  16733. + inode->i_mapping->a_ops =
  16734. + &yaffs_file_address_operations;
  16735. + break;
  16736. + case S_IFDIR: /* directory */
  16737. + inode->i_op = &yaffs_dir_inode_operations;
  16738. + inode->i_fop = &yaffs_dir_operations;
  16739. + break;
  16740. + case S_IFLNK: /* symlink */
  16741. + inode->i_op = &yaffs_symlink_inode_operations;
  16742. + break;
  16743. + }
  16744. +
  16745. + yaffs_inode_to_obj_lv(inode) = obj;
  16746. +
  16747. + obj->my_inode = inode;
  16748. +
  16749. + } else {
  16750. + yaffs_trace(YAFFS_TRACE_OS,
  16751. + "yaffs_fill_inode invalid parameters");
  16752. + }
  16753. +
  16754. +}
  16755. +
  16756. +
  16757. +
  16758. +/*
  16759. + * yaffs background thread functions .
  16760. + * yaffs_bg_thread_fn() the thread function
  16761. + * yaffs_bg_start() launches the background thread.
  16762. + * yaffs_bg_stop() cleans up the background thread.
  16763. + *
  16764. + * NB:
  16765. + * The thread should only run after the yaffs is initialised
  16766. + * The thread should be stopped before yaffs is unmounted.
  16767. + * The thread should not do any writing while the fs is in read only.
  16768. + */
  16769. +
  16770. +static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
  16771. +{
  16772. + unsigned erased_chunks =
  16773. + dev->n_erased_blocks * dev->param.chunks_per_block;
  16774. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  16775. + unsigned scattered = 0; /* Free chunks not in an erased block */
  16776. +
  16777. + if (erased_chunks < dev->n_free_chunks)
  16778. + scattered = (dev->n_free_chunks - erased_chunks);
  16779. +
  16780. + if (!context->bg_running)
  16781. + return 0;
  16782. + else if (scattered < (dev->param.chunks_per_block * 2))
  16783. + return 0;
  16784. + else if (erased_chunks > dev->n_free_chunks / 2)
  16785. + return 0;
  16786. + else if (erased_chunks > dev->n_free_chunks / 4)
  16787. + return 1;
  16788. + else
  16789. + return 2;
  16790. +}
  16791. +
  16792. +#ifdef YAFFS_COMPILE_BACKGROUND
  16793. +
  16794. +void yaffs_background_waker(unsigned long data)
  16795. +{
  16796. + wake_up_process((struct task_struct *)data);
  16797. +}
  16798. +
  16799. +static int yaffs_bg_thread_fn(void *data)
  16800. +{
  16801. + struct yaffs_dev *dev = (struct yaffs_dev *)data;
  16802. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  16803. + unsigned long now = jiffies;
  16804. + unsigned long next_dir_update = now;
  16805. + unsigned long next_gc = now;
  16806. + unsigned long expires;
  16807. + unsigned int urgency;
  16808. +
  16809. + int gc_result;
  16810. + struct timer_list timer;
  16811. +
  16812. + yaffs_trace(YAFFS_TRACE_BACKGROUND,
  16813. + "yaffs_background starting for dev %p", (void *)dev);
  16814. +
  16815. +#ifdef YAFFS_COMPILE_FREEZER
  16816. + set_freezable();
  16817. +#endif
  16818. + while (context->bg_running) {
  16819. + yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background");
  16820. +
  16821. + if (kthread_should_stop())
  16822. + break;
  16823. +
  16824. +#ifdef YAFFS_COMPILE_FREEZER
  16825. + if (try_to_freeze())
  16826. + continue;
  16827. +#endif
  16828. + yaffs_gross_lock(dev);
  16829. +
  16830. + now = jiffies;
  16831. +
  16832. + if (time_after(now, next_dir_update) && yaffs_bg_enable) {
  16833. + yaffs_update_dirty_dirs(dev);
  16834. + next_dir_update = now + HZ;
  16835. + }
  16836. +
  16837. + if (time_after(now, next_gc) && yaffs_bg_enable) {
  16838. + if (!dev->is_checkpointed) {
  16839. + urgency = yaffs_bg_gc_urgency(dev);
  16840. + gc_result = yaffs_bg_gc(dev, urgency);
  16841. + if (urgency > 1)
  16842. + next_gc = now + HZ / 20 + 1;
  16843. + else if (urgency > 0)
  16844. + next_gc = now + HZ / 10 + 1;
  16845. + else
  16846. + next_gc = now + HZ * 2;
  16847. + } else {
  16848. + /*
  16849. + * gc not running so set to next_dir_update
  16850. + * to cut down on wake ups
  16851. + */
  16852. + next_gc = next_dir_update;
  16853. + }
  16854. + }
  16855. + yaffs_gross_unlock(dev);
  16856. +#if 1
  16857. + expires = next_dir_update;
  16858. + if (time_before(next_gc, expires))
  16859. + expires = next_gc;
  16860. + if (time_before(expires, now))
  16861. + expires = now + HZ;
  16862. +
  16863. + Y_INIT_TIMER(&timer);
  16864. + timer.expires = expires + 1;
  16865. + timer.data = (unsigned long)current;
  16866. + timer.function = yaffs_background_waker;
  16867. +
  16868. + set_current_state(TASK_INTERRUPTIBLE);
  16869. + add_timer(&timer);
  16870. + schedule();
  16871. + del_timer_sync(&timer);
  16872. +#else
  16873. + msleep(10);
  16874. +#endif
  16875. + }
  16876. +
  16877. + return 0;
  16878. +}
  16879. +
  16880. +static int yaffs_bg_start(struct yaffs_dev *dev)
  16881. +{
  16882. + int retval = 0;
  16883. + struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
  16884. +
  16885. + if (dev->read_only)
  16886. + return -1;
  16887. +
  16888. + context->bg_running = 1;
  16889. +
  16890. + context->bg_thread = kthread_run(yaffs_bg_thread_fn,
  16891. + (void *)dev, "yaffs-bg-%d",
  16892. + context->mount_id);
  16893. +
  16894. + if (IS_ERR(context->bg_thread)) {
  16895. + retval = PTR_ERR(context->bg_thread);
  16896. + context->bg_thread = NULL;
  16897. + context->bg_running = 0;
  16898. + }
  16899. + return retval;
  16900. +}
  16901. +
  16902. +static void yaffs_bg_stop(struct yaffs_dev *dev)
  16903. +{
  16904. + struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev);
  16905. +
  16906. + ctxt->bg_running = 0;
  16907. +
  16908. + if (ctxt->bg_thread) {
  16909. + kthread_stop(ctxt->bg_thread);
  16910. + ctxt->bg_thread = NULL;
  16911. + }
  16912. +}
  16913. +#else
  16914. +static int yaffs_bg_thread_fn(void *data)
  16915. +{
  16916. + return 0;
  16917. +}
  16918. +
  16919. +static int yaffs_bg_start(struct yaffs_dev *dev)
  16920. +{
  16921. + return 0;
  16922. +}
  16923. +
  16924. +static void yaffs_bg_stop(struct yaffs_dev *dev)
  16925. +{
  16926. +}
  16927. +#endif
  16928. +
  16929. +
  16930. +static void yaffs_flush_inodes(struct super_block *sb)
  16931. +{
  16932. + struct inode *iptr;
  16933. + struct yaffs_obj *obj;
  16934. +
  16935. + list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
  16936. + obj = yaffs_inode_to_obj(iptr);
  16937. + if (obj) {
  16938. + yaffs_trace(YAFFS_TRACE_OS,
  16939. + "flushing obj %d",
  16940. + obj->obj_id);
  16941. + yaffs_flush_file(obj, 1, 0);
  16942. + }
  16943. + }
  16944. +}
  16945. +
  16946. +static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
  16947. +{
  16948. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  16949. + if (!dev)
  16950. + return;
  16951. +
  16952. + yaffs_flush_inodes(sb);
  16953. + yaffs_update_dirty_dirs(dev);
  16954. + yaffs_flush_whole_cache(dev);
  16955. + if (do_checkpoint)
  16956. + yaffs_checkpoint_save(dev);
  16957. +}
  16958. +
  16959. +static LIST_HEAD(yaffs_context_list);
  16960. +struct mutex yaffs_context_lock;
  16961. +
  16962. +static void yaffs_put_super(struct super_block *sb)
  16963. +{
  16964. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  16965. + struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  16966. +
  16967. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
  16968. + "yaffs_put_super");
  16969. +
  16970. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
  16971. + "Shutting down yaffs background thread");
  16972. + yaffs_bg_stop(dev);
  16973. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
  16974. + "yaffs background thread shut down");
  16975. +
  16976. + yaffs_gross_lock(dev);
  16977. +
  16978. + yaffs_flush_super(sb, 1);
  16979. +
  16980. + yaffs_deinitialise(dev);
  16981. +
  16982. + yaffs_gross_unlock(dev);
  16983. +
  16984. + mutex_lock(&yaffs_context_lock);
  16985. + list_del_init(&(yaffs_dev_to_lc(dev)->context_list));
  16986. + mutex_unlock(&yaffs_context_lock);
  16987. +
  16988. + if (yaffs_dev_to_lc(dev)->spare_buffer) {
  16989. + kfree(yaffs_dev_to_lc(dev)->spare_buffer);
  16990. + yaffs_dev_to_lc(dev)->spare_buffer = NULL;
  16991. + }
  16992. +
  16993. + kfree(dev);
  16994. +
  16995. + yaffs_put_mtd_device(mtd);
  16996. +
  16997. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
  16998. + "yaffs_put_super done");
  16999. +}
  17000. +
  17001. +
  17002. +static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev)
  17003. +{
  17004. + return yaffs_gc_control;
  17005. +}
  17006. +
  17007. +
  17008. +#ifdef YAFFS_COMPILE_EXPORTFS
  17009. +
  17010. +static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
  17011. + uint32_t generation)
  17012. +{
  17013. + return Y_IGET(sb, ino);
  17014. +}
  17015. +
  17016. +static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb,
  17017. + struct fid *fid, int fh_len,
  17018. + int fh_type)
  17019. +{
  17020. + return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  17021. + yaffs2_nfs_get_inode);
  17022. +}
  17023. +
  17024. +static struct dentry *yaffs2_fh_to_parent(struct super_block *sb,
  17025. + struct fid *fid, int fh_len,
  17026. + int fh_type)
  17027. +{
  17028. + return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  17029. + yaffs2_nfs_get_inode);
  17030. +}
  17031. +
  17032. +struct dentry *yaffs2_get_parent(struct dentry *dentry)
  17033. +{
  17034. +
  17035. + struct super_block *sb = dentry->d_inode->i_sb;
  17036. + struct dentry *parent = ERR_PTR(-ENOENT);
  17037. + struct inode *inode;
  17038. + unsigned long parent_ino;
  17039. + struct yaffs_obj *d_obj;
  17040. + struct yaffs_obj *parent_obj;
  17041. +
  17042. + d_obj = yaffs_inode_to_obj(dentry->d_inode);
  17043. +
  17044. + if (d_obj) {
  17045. + parent_obj = d_obj->parent;
  17046. + if (parent_obj) {
  17047. + parent_ino = yaffs_get_obj_inode(parent_obj);
  17048. + inode = Y_IGET(sb, parent_ino);
  17049. +
  17050. + if (IS_ERR(inode)) {
  17051. + parent = ERR_CAST(inode);
  17052. + } else {
  17053. + parent = d_obtain_alias(inode);
  17054. + if (!IS_ERR(parent)) {
  17055. + parent = ERR_PTR(-ENOMEM);
  17056. + iput(inode);
  17057. + }
  17058. + }
  17059. + }
  17060. + }
  17061. +
  17062. + return parent;
  17063. +}
  17064. +
  17065. +/* Just declare a zero structure as a NULL value implies
  17066. + * using the default functions of exportfs.
  17067. + */
  17068. +
  17069. +static struct export_operations yaffs_export_ops = {
  17070. + .fh_to_dentry = yaffs2_fh_to_dentry,
  17071. + .fh_to_parent = yaffs2_fh_to_parent,
  17072. + .get_parent = yaffs2_get_parent,
  17073. +};
  17074. +
  17075. +#endif
  17076. +
  17077. +static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj)
  17078. +{
  17079. + /* Clear the association between the inode and
  17080. + * the struct yaffs_obj.
  17081. + */
  17082. + obj->my_inode = NULL;
  17083. + yaffs_inode_to_obj_lv(inode) = NULL;
  17084. +
  17085. + /* If the object freeing was deferred, then the real
  17086. + * free happens now.
  17087. + * This should fix the inode inconsistency problem.
  17088. + */
  17089. + yaffs_handle_defered_free(obj);
  17090. +}
  17091. +
  17092. +#ifdef YAFFS_HAS_EVICT_INODE
  17093. +/* yaffs_evict_inode combines into one operation what was previously done in
  17094. + * yaffs_clear_inode() and yaffs_delete_inode()
  17095. + *
  17096. + */
  17097. +static void yaffs_evict_inode(struct inode *inode)
  17098. +{
  17099. + struct yaffs_obj *obj;
  17100. + struct yaffs_dev *dev;
  17101. + int deleteme = 0;
  17102. +
  17103. + obj = yaffs_inode_to_obj(inode);
  17104. +
  17105. + yaffs_trace(YAFFS_TRACE_OS,
  17106. + "yaffs_evict_inode: ino %d, count %d %s",
  17107. + (int)inode->i_ino, atomic_read(&inode->i_count),
  17108. + obj ? "object exists" : "null object");
  17109. +
  17110. + if (!inode->i_nlink && !is_bad_inode(inode))
  17111. + deleteme = 1;
  17112. + truncate_inode_pages(&inode->i_data, 0);
  17113. + Y_CLEAR_INODE(inode);
  17114. +
  17115. + if (deleteme && obj) {
  17116. + dev = obj->my_dev;
  17117. + yaffs_gross_lock(dev);
  17118. + yaffs_del_obj(obj);
  17119. + yaffs_gross_unlock(dev);
  17120. + }
  17121. + if (obj) {
  17122. + dev = obj->my_dev;
  17123. + yaffs_gross_lock(dev);
  17124. + yaffs_unstitch_obj(inode, obj);
  17125. + yaffs_gross_unlock(dev);
  17126. + }
  17127. +}
  17128. +#else
  17129. +
  17130. +/* clear is called to tell the fs to release any per-inode data it holds.
  17131. + * The object might still exist on disk and is just being thrown out of the cache
  17132. + * or else the object has actually been deleted and we're being called via
  17133. + * the chain
  17134. + * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
  17135. + */
  17136. +
  17137. +static void yaffs_clear_inode(struct inode *inode)
  17138. +{
  17139. + struct yaffs_obj *obj;
  17140. + struct yaffs_dev *dev;
  17141. +
  17142. + obj = yaffs_inode_to_obj(inode);
  17143. +
  17144. + yaffs_trace(YAFFS_TRACE_OS,
  17145. + "yaffs_clear_inode: ino %d, count %d %s",
  17146. + (int)inode->i_ino, atomic_read(&inode->i_count),
  17147. + obj ? "object exists" : "null object");
  17148. +
  17149. + if (obj) {
  17150. + dev = obj->my_dev;
  17151. + yaffs_gross_lock(dev);
  17152. + yaffs_unstitch_obj(inode, obj);
  17153. + yaffs_gross_unlock(dev);
  17154. + }
  17155. +
  17156. +}
  17157. +
  17158. +/* delete is called when the link count is zero and the inode
  17159. + * is put (ie. nobody wants to know about it anymore, time to
  17160. + * delete the file).
  17161. + * NB Must call clear_inode()
  17162. + */
  17163. +static void yaffs_delete_inode(struct inode *inode)
  17164. +{
  17165. + struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
  17166. + struct yaffs_dev *dev;
  17167. +
  17168. + yaffs_trace(YAFFS_TRACE_OS,
  17169. + "yaffs_delete_inode: ino %d, count %d %s",
  17170. + (int)inode->i_ino, atomic_read(&inode->i_count),
  17171. + obj ? "object exists" : "null object");
  17172. +
  17173. + if (obj) {
  17174. + dev = obj->my_dev;
  17175. + yaffs_gross_lock(dev);
  17176. + yaffs_del_obj(obj);
  17177. + yaffs_gross_unlock(dev);
  17178. + }
  17179. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
  17180. + truncate_inode_pages(&inode->i_data, 0);
  17181. +#endif
  17182. + clear_inode(inode);
  17183. +}
  17184. +#endif
  17185. +
  17186. +
  17187. +
  17188. +
  17189. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  17190. +static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
  17191. +{
  17192. + struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
  17193. + struct super_block *sb = dentry->d_sb;
  17194. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  17195. +static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
  17196. +{
  17197. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  17198. +#else
  17199. +static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
  17200. +{
  17201. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  17202. +#endif
  17203. +
  17204. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs");
  17205. +
  17206. + yaffs_gross_lock(dev);
  17207. +
  17208. + buf->f_type = YAFFS_MAGIC;
  17209. + buf->f_bsize = sb->s_blocksize;
  17210. + buf->f_namelen = 255;
  17211. +
  17212. + if (dev->data_bytes_per_chunk & (dev->data_bytes_per_chunk - 1)) {
  17213. + /* Do this if chunk size is not a power of 2 */
  17214. +
  17215. + uint64_t bytes_in_dev;
  17216. + uint64_t bytes_free;
  17217. +
  17218. + bytes_in_dev =
  17219. + ((uint64_t)
  17220. + ((dev->param.end_block - dev->param.start_block +
  17221. + 1))) * ((uint64_t) (dev->param.chunks_per_block *
  17222. + dev->data_bytes_per_chunk));
  17223. +
  17224. + do_div(bytes_in_dev, sb->s_blocksize); /* bytes_in_dev becomes the number of blocks */
  17225. + buf->f_blocks = bytes_in_dev;
  17226. +
  17227. + bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) *
  17228. + ((uint64_t) (dev->data_bytes_per_chunk));
  17229. +
  17230. + do_div(bytes_free, sb->s_blocksize);
  17231. +
  17232. + buf->f_bfree = bytes_free;
  17233. +
  17234. + } else if (sb->s_blocksize > dev->data_bytes_per_chunk) {
  17235. +
  17236. + buf->f_blocks =
  17237. + (dev->param.end_block - dev->param.start_block + 1) *
  17238. + dev->param.chunks_per_block /
  17239. + (sb->s_blocksize / dev->data_bytes_per_chunk);
  17240. + buf->f_bfree =
  17241. + yaffs_get_n_free_chunks(dev) /
  17242. + (sb->s_blocksize / dev->data_bytes_per_chunk);
  17243. + } else {
  17244. + buf->f_blocks =
  17245. + (dev->param.end_block - dev->param.start_block + 1) *
  17246. + dev->param.chunks_per_block *
  17247. + (dev->data_bytes_per_chunk / sb->s_blocksize);
  17248. +
  17249. + buf->f_bfree =
  17250. + yaffs_get_n_free_chunks(dev) *
  17251. + (dev->data_bytes_per_chunk / sb->s_blocksize);
  17252. + }
  17253. +
  17254. + buf->f_files = 0;
  17255. + buf->f_ffree = 0;
  17256. + buf->f_bavail = buf->f_bfree;
  17257. +
  17258. + yaffs_gross_unlock(dev);
  17259. + return 0;
  17260. +}
  17261. +
  17262. +
  17263. +
  17264. +static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
  17265. +{
  17266. +
  17267. + struct yaffs_dev *dev = yaffs_super_to_dev(sb);
  17268. + unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
  17269. + unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
  17270. + int do_checkpoint;
  17271. + int dirty = yaffs_check_super_dirty(dev);
  17272. +
  17273. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
  17274. + "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
  17275. + gc_urgent,
  17276. + dirty ? "dirty" : "clean",
  17277. + request_checkpoint ? "checkpoint requested" : "no checkpoint",
  17278. + oneshot_checkpoint ? " one-shot" : "");
  17279. +
  17280. + yaffs_gross_lock(dev);
  17281. + do_checkpoint = ((request_checkpoint && !gc_urgent) ||
  17282. + oneshot_checkpoint) && !dev->is_checkpointed;
  17283. +
  17284. + if (dirty || do_checkpoint) {
  17285. + yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
  17286. + yaffs_clear_super_dirty(dev);
  17287. + if (oneshot_checkpoint)
  17288. + yaffs_auto_checkpoint &= ~4;
  17289. + }
  17290. + yaffs_gross_unlock(dev);
  17291. +
  17292. + return 0;
  17293. +}
  17294. +
  17295. +
  17296. +#ifdef YAFFS_HAS_WRITE_SUPER
  17297. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  17298. +static void yaffs_write_super(struct super_block *sb)
  17299. +#else
  17300. +static int yaffs_write_super(struct super_block *sb)
  17301. +#endif
  17302. +{
  17303. + unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
  17304. +
  17305. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
  17306. + "yaffs_write_super %s",
  17307. + request_checkpoint ? " checkpt" : "");
  17308. +
  17309. + yaffs_do_sync_fs(sb, request_checkpoint);
  17310. +
  17311. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
  17312. + return 0;
  17313. +#endif
  17314. +}
  17315. +#endif
  17316. +
  17317. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  17318. +static int yaffs_sync_fs(struct super_block *sb, int wait)
  17319. +#else
  17320. +static int yaffs_sync_fs(struct super_block *sb)
  17321. +#endif
  17322. +{
  17323. + unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1);
  17324. +
  17325. + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
  17326. + "yaffs_sync_fs%s", request_checkpoint ? " checkpt" : "");
  17327. +
  17328. + yaffs_do_sync_fs(sb, request_checkpoint);
  17329. +
  17330. + return 0;
  17331. +}
  17332. +
  17333. +
  17334. +
  17335. +static const struct super_operations yaffs_super_ops = {
  17336. + .statfs = yaffs_statfs,
  17337. +
  17338. +#ifndef YAFFS_USE_OWN_IGET
  17339. + .read_inode = yaffs_read_inode,
  17340. +#endif
  17341. +#ifdef YAFFS_HAS_PUT_INODE
  17342. + .put_inode = yaffs_put_inode,
  17343. +#endif
  17344. + .put_super = yaffs_put_super,
  17345. +#ifdef YAFFS_HAS_EVICT_INODE
  17346. + .evict_inode = yaffs_evict_inode,
  17347. +#else
  17348. + .delete_inode = yaffs_delete_inode,
  17349. + .clear_inode = yaffs_clear_inode,
  17350. +#endif
  17351. + .sync_fs = yaffs_sync_fs,
  17352. +#ifdef YAFFS_HAS_WRITE_SUPER
  17353. + .write_super = yaffs_write_super,
  17354. +#endif
  17355. +};
  17356. +
  17357. +struct yaffs_options {
  17358. + int inband_tags;
  17359. + int skip_checkpoint_read;
  17360. + int skip_checkpoint_write;
  17361. + int no_cache;
  17362. + int tags_ecc_on;
  17363. + int tags_ecc_overridden;
  17364. + int lazy_loading_enabled;
  17365. + int lazy_loading_overridden;
  17366. + int empty_lost_and_found;
  17367. + int empty_lost_and_found_overridden;
  17368. + int disable_summary;
  17369. +};
  17370. +
  17371. +#define MAX_OPT_LEN 30
  17372. +static int yaffs_parse_options(struct yaffs_options *options,
  17373. + const char *options_str)
  17374. +{
  17375. + char cur_opt[MAX_OPT_LEN + 1];
  17376. + int p;
  17377. + int error = 0;
  17378. +
  17379. + /* Parse through the options which is a comma seperated list */
  17380. +
  17381. + while (options_str && *options_str && !error) {
  17382. + memset(cur_opt, 0, MAX_OPT_LEN + 1);
  17383. + p = 0;
  17384. +
  17385. + while (*options_str == ',')
  17386. + options_str++;
  17387. +
  17388. + while (*options_str && *options_str != ',') {
  17389. + if (p < MAX_OPT_LEN) {
  17390. + cur_opt[p] = *options_str;
  17391. + p++;
  17392. + }
  17393. + options_str++;
  17394. + }
  17395. +
  17396. + if (!strcmp(cur_opt, "inband-tags")) {
  17397. + options->inband_tags = 1;
  17398. + } else if (!strcmp(cur_opt, "tags-ecc-off")) {
  17399. + options->tags_ecc_on = 0;
  17400. + options->tags_ecc_overridden = 1;
  17401. + } else if (!strcmp(cur_opt, "tags-ecc-on")) {
  17402. + options->tags_ecc_on = 1;
  17403. + options->tags_ecc_overridden = 1;
  17404. + } else if (!strcmp(cur_opt, "lazy-loading-off")) {
  17405. + options->lazy_loading_enabled = 0;
  17406. + options->lazy_loading_overridden = 1;
  17407. + } else if (!strcmp(cur_opt, "lazy-loading-on")) {
  17408. + options->lazy_loading_enabled = 1;
  17409. + options->lazy_loading_overridden = 1;
  17410. + } else if (!strcmp(cur_opt, "disable-summary")) {
  17411. + options->disable_summary = 1;
  17412. + } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
  17413. + options->empty_lost_and_found = 0;
  17414. + options->empty_lost_and_found_overridden = 1;
  17415. + } else if (!strcmp(cur_opt, "empty-lost-and-found-on")) {
  17416. + options->empty_lost_and_found = 1;
  17417. + options->empty_lost_and_found_overridden = 1;
  17418. + } else if (!strcmp(cur_opt, "no-cache")) {
  17419. + options->no_cache = 1;
  17420. + } else if (!strcmp(cur_opt, "no-checkpoint-read")) {
  17421. + options->skip_checkpoint_read = 1;
  17422. + } else if (!strcmp(cur_opt, "no-checkpoint-write")) {
  17423. + options->skip_checkpoint_write = 1;
  17424. + } else if (!strcmp(cur_opt, "no-checkpoint")) {
  17425. + options->skip_checkpoint_read = 1;
  17426. + options->skip_checkpoint_write = 1;
  17427. + } else {
  17428. + printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",
  17429. + cur_opt);
  17430. + error = 1;
  17431. + }
  17432. + }
  17433. +
  17434. + return error;
  17435. +}
  17436. +
  17437. +
  17438. +static struct dentry *yaffs_make_root(struct inode *inode)
  17439. +{
  17440. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
  17441. + struct dentry *root = d_alloc_root(inode);
  17442. +
  17443. + if (!root)
  17444. + iput(inode);
  17445. +
  17446. + return root;
  17447. +#else
  17448. + return d_make_root(inode);
  17449. +#endif
  17450. +}
  17451. +
  17452. +
  17453. +
  17454. +
  17455. +static struct super_block *yaffs_internal_read_super(int yaffs_version,
  17456. + struct super_block *sb,
  17457. + void *data, int silent)
  17458. +{
  17459. + int n_blocks;
  17460. + struct inode *inode = NULL;
  17461. + struct dentry *root;
  17462. + struct yaffs_dev *dev = 0;
  17463. + char devname_buf[BDEVNAME_SIZE + 1];
  17464. + struct mtd_info *mtd;
  17465. + int err;
  17466. + char *data_str = (char *)data;
  17467. + struct yaffs_linux_context *context = NULL;
  17468. + struct yaffs_param *param;
  17469. +
  17470. + int read_only = 0;
  17471. + int inband_tags = 0;
  17472. +
  17473. + struct yaffs_options options;
  17474. +
  17475. + unsigned mount_id;
  17476. + int found;
  17477. + struct yaffs_linux_context *context_iterator;
  17478. + struct list_head *l;
  17479. +
  17480. + if (!sb) {
  17481. + printk(KERN_INFO "yaffs: sb is NULL\n");
  17482. + return NULL;
  17483. + }
  17484. +
  17485. + sb->s_magic = YAFFS_MAGIC;
  17486. + sb->s_op = &yaffs_super_ops;
  17487. + sb->s_flags |= MS_NOATIME;
  17488. +
  17489. + read_only = ((sb->s_flags & MS_RDONLY) != 0);
  17490. +
  17491. +#ifdef YAFFS_COMPILE_EXPORTFS
  17492. + sb->s_export_op = &yaffs_export_ops;
  17493. +#endif
  17494. +
  17495. + if (!sb->s_dev)
  17496. + printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
  17497. + else if (!yaffs_devname(sb, devname_buf))
  17498. + printk(KERN_INFO "yaffs: devname is NULL\n");
  17499. + else
  17500. + printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
  17501. + sb->s_dev,
  17502. + yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw");
  17503. +
  17504. + if (!data_str)
  17505. + data_str = "";
  17506. +
  17507. + printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str);
  17508. +
  17509. + memset(&options, 0, sizeof(options));
  17510. +
  17511. + if (yaffs_parse_options(&options, data_str)) {
  17512. + /* Option parsing failed */
  17513. + return NULL;
  17514. + }
  17515. +
  17516. + sb->s_blocksize = PAGE_CACHE_SIZE;
  17517. + sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
  17518. +
  17519. + yaffs_trace(YAFFS_TRACE_OS,
  17520. + "yaffs_read_super: Using yaffs%d", yaffs_version);
  17521. + yaffs_trace(YAFFS_TRACE_OS,
  17522. + "yaffs_read_super: block size %d", (int)(sb->s_blocksize));
  17523. +
  17524. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  17525. + "yaffs: Attempting MTD mount of %u.%u,\"%s\"",
  17526. + MAJOR(sb->s_dev), MINOR(sb->s_dev),
  17527. + yaffs_devname(sb, devname_buf));
  17528. +
  17529. + /* Get the device */
  17530. + mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
  17531. + if (IS_ERR(mtd)) {
  17532. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  17533. + "yaffs: MTD device %u either not valid or unavailable",
  17534. + MINOR(sb->s_dev));
  17535. + return NULL;
  17536. + }
  17537. +
  17538. + if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
  17539. + yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
  17540. + yaffs_version = 2;
  17541. + }
  17542. +
  17543. + /* Added NCB 26/5/2006 for completeness */
  17544. + if (yaffs_version == 2 && !options.inband_tags
  17545. + && WRITE_SIZE(mtd) == 512) {
  17546. + yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
  17547. + yaffs_version = 1;
  17548. + }
  17549. +
  17550. + if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) ||
  17551. + options.inband_tags)
  17552. + inband_tags = 1;
  17553. +
  17554. + if(yaffs_verify_mtd(mtd, yaffs_version, inband_tags) < 0)
  17555. + return NULL;
  17556. +
  17557. + /* OK, so if we got here, we have an MTD that's NAND and looks
  17558. + * like it has the right capabilities
  17559. + * Set the struct yaffs_dev up for mtd
  17560. + */
  17561. +
  17562. + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
  17563. + read_only = 1;
  17564. + printk(KERN_INFO
  17565. + "yaffs: mtd is read only, setting superblock read only\n"
  17566. + );
  17567. + sb->s_flags |= MS_RDONLY;
  17568. + }
  17569. +
  17570. + dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL);
  17571. + context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
  17572. +
  17573. + if (!dev || !context) {
  17574. + kfree(dev);
  17575. + kfree(context);
  17576. + dev = NULL;
  17577. + context = NULL;
  17578. +
  17579. + /* Deep shit could not allocate device structure */
  17580. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  17581. + "yaffs_read_super: Failed trying to allocate struct yaffs_dev."
  17582. + );
  17583. + return NULL;
  17584. + }
  17585. + memset(dev, 0, sizeof(struct yaffs_dev));
  17586. + param = &(dev->param);
  17587. +
  17588. + memset(context, 0, sizeof(struct yaffs_linux_context));
  17589. + dev->os_context = context;
  17590. + INIT_LIST_HEAD(&(context->context_list));
  17591. + context->dev = dev;
  17592. + context->super = sb;
  17593. +
  17594. + dev->read_only = read_only;
  17595. +
  17596. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  17597. + sb->s_fs_info = dev;
  17598. +#else
  17599. + sb->u.generic_sbp = dev;
  17600. +#endif
  17601. +
  17602. +
  17603. + dev->driver_context = mtd;
  17604. + param->name = mtd->name;
  17605. +
  17606. + /* Set up the memory size parameters.... */
  17607. +
  17608. +
  17609. + param->n_reserved_blocks = 5;
  17610. + param->n_caches = (options.no_cache) ? 0 : 10;
  17611. + param->inband_tags = inband_tags;
  17612. +
  17613. + param->enable_xattr = 1;
  17614. + if (options.lazy_loading_overridden)
  17615. + param->disable_lazy_load = !options.lazy_loading_enabled;
  17616. +
  17617. + param->defered_dir_update = 1;
  17618. +
  17619. + if (options.tags_ecc_overridden)
  17620. + param->no_tags_ecc = !options.tags_ecc_on;
  17621. +
  17622. + param->empty_lost_n_found = 1;
  17623. + param->refresh_period = 500;
  17624. + param->disable_summary = options.disable_summary;
  17625. +
  17626. +
  17627. +#ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING
  17628. + param->disable_bad_block_marking = 1;
  17629. +#endif
  17630. + if (options.empty_lost_and_found_overridden)
  17631. + param->empty_lost_n_found = options.empty_lost_and_found;
  17632. +
  17633. + /* ... and the functions. */
  17634. + if (yaffs_version == 2) {
  17635. + param->is_yaffs2 = 1;
  17636. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  17637. + param->total_bytes_per_chunk = mtd->writesize;
  17638. + param->chunks_per_block = mtd->erasesize / mtd->writesize;
  17639. +#else
  17640. + param->total_bytes_per_chunk = mtd->oobblock;
  17641. + param->chunks_per_block = mtd->erasesize / mtd->oobblock;
  17642. +#endif
  17643. + n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize);
  17644. +
  17645. + param->start_block = 0;
  17646. + param->end_block = n_blocks - 1;
  17647. + } else {
  17648. + param->is_yaffs2 = 0;
  17649. + n_blocks = YCALCBLOCKS(mtd->size,
  17650. + YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
  17651. +
  17652. + param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
  17653. + param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
  17654. + }
  17655. +
  17656. + param->start_block = 0;
  17657. + param->end_block = n_blocks - 1;
  17658. +
  17659. + yaffs_mtd_drv_install(dev);
  17660. +
  17661. + param->sb_dirty_fn = yaffs_set_super_dirty;
  17662. + param->gc_control_fn = yaffs_gc_control_callback;
  17663. +
  17664. + yaffs_dev_to_lc(dev)->super = sb;
  17665. +
  17666. + param->use_nand_ecc = 1;
  17667. +
  17668. + param->skip_checkpt_rd = options.skip_checkpoint_read;
  17669. + param->skip_checkpt_wr = options.skip_checkpoint_write;
  17670. +
  17671. + mutex_lock(&yaffs_context_lock);
  17672. + /* Get a mount id */
  17673. + found = 0;
  17674. + for (mount_id = 0; !found; mount_id++) {
  17675. + found = 1;
  17676. + list_for_each(l, &yaffs_context_list) {
  17677. + context_iterator =
  17678. + list_entry(l, struct yaffs_linux_context,
  17679. + context_list);
  17680. + if (context_iterator->mount_id == mount_id)
  17681. + found = 0;
  17682. + }
  17683. + }
  17684. + context->mount_id = mount_id;
  17685. +
  17686. + list_add_tail(&(yaffs_dev_to_lc(dev)->context_list),
  17687. + &yaffs_context_list);
  17688. + mutex_unlock(&yaffs_context_lock);
  17689. +
  17690. + /* Directory search handling... */
  17691. + INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts));
  17692. + param->remove_obj_fn = yaffs_remove_obj_callback;
  17693. +
  17694. + mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock));
  17695. +
  17696. + yaffs_gross_lock(dev);
  17697. +
  17698. + err = yaffs_guts_initialise(dev);
  17699. +
  17700. + yaffs_trace(YAFFS_TRACE_OS,
  17701. + "yaffs_read_super: guts initialised %s",
  17702. + (err == YAFFS_OK) ? "OK" : "FAILED");
  17703. +
  17704. + if (err == YAFFS_OK)
  17705. + yaffs_bg_start(dev);
  17706. +
  17707. + if (!context->bg_thread)
  17708. + param->defered_dir_update = 0;
  17709. +
  17710. + sb->s_maxbytes = yaffs_max_file_size(dev);
  17711. +
  17712. + /* Release lock before yaffs_get_inode() */
  17713. + yaffs_gross_unlock(dev);
  17714. +
  17715. + /* Create root inode */
  17716. + if (err == YAFFS_OK)
  17717. + inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev));
  17718. +
  17719. + if (!inode)
  17720. + return NULL;
  17721. +
  17722. + inode->i_op = &yaffs_dir_inode_operations;
  17723. + inode->i_fop = &yaffs_dir_operations;
  17724. +
  17725. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: got root inode");
  17726. +
  17727. + root = yaffs_make_root(inode);
  17728. +
  17729. + if (!root)
  17730. + return NULL;
  17731. +
  17732. + sb->s_root = root;
  17733. + if(!dev->is_checkpointed)
  17734. + yaffs_set_super_dirty(dev);
  17735. +
  17736. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  17737. + "yaffs_read_super: is_checkpointed %d",
  17738. + dev->is_checkpointed);
  17739. +
  17740. + yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done");
  17741. + return sb;
  17742. +}
  17743. +
  17744. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  17745. +static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
  17746. + int silent)
  17747. +{
  17748. + return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
  17749. +}
  17750. +
  17751. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  17752. +static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags,
  17753. + const char *dev_name, void *data)
  17754. +{
  17755. + return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd);
  17756. +}
  17757. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  17758. +static int yaffs_read_super(struct file_system_type *fs,
  17759. + int flags, const char *dev_name,
  17760. + void *data, struct vfsmount *mnt)
  17761. +{
  17762. +
  17763. + return get_sb_bdev(fs, flags, dev_name, data,
  17764. + yaffs_internal_read_super_mtd, mnt);
  17765. +}
  17766. +#else
  17767. +static struct super_block *yaffs_read_super(struct file_system_type *fs,
  17768. + int flags, const char *dev_name,
  17769. + void *data)
  17770. +{
  17771. +
  17772. + return get_sb_bdev(fs, flags, dev_name, data,
  17773. + yaffs_internal_read_super_mtd);
  17774. +}
  17775. +#endif
  17776. +
  17777. +static struct file_system_type yaffs_fs_type = {
  17778. + .owner = THIS_MODULE,
  17779. + .name = "yaffs",
  17780. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  17781. + .mount = yaffs_mount,
  17782. +#else
  17783. + .get_sb = yaffs_read_super,
  17784. +#endif
  17785. + .kill_sb = kill_block_super,
  17786. + .fs_flags = FS_REQUIRES_DEV,
  17787. +};
  17788. +#else
  17789. +static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
  17790. + int silent)
  17791. +{
  17792. + return yaffs_internal_read_super(1, sb, data, silent);
  17793. +}
  17794. +
  17795. +static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
  17796. + FS_REQUIRES_DEV);
  17797. +#endif
  17798. +
  17799. +
  17800. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  17801. +static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
  17802. + int silent)
  17803. +{
  17804. + return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
  17805. +}
  17806. +
  17807. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  17808. +static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags,
  17809. + const char *dev_name, void *data)
  17810. +{
  17811. + return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd);
  17812. +}
  17813. +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
  17814. +static int yaffs2_read_super(struct file_system_type *fs,
  17815. + int flags, const char *dev_name, void *data,
  17816. + struct vfsmount *mnt)
  17817. +{
  17818. + return get_sb_bdev(fs, flags, dev_name, data,
  17819. + yaffs2_internal_read_super_mtd, mnt);
  17820. +}
  17821. +#else
  17822. +static struct super_block *yaffs2_read_super(struct file_system_type *fs,
  17823. + int flags, const char *dev_name,
  17824. + void *data)
  17825. +{
  17826. +
  17827. + return get_sb_bdev(fs, flags, dev_name, data,
  17828. + yaffs2_internal_read_super_mtd);
  17829. +}
  17830. +#endif
  17831. +
  17832. +static struct file_system_type yaffs2_fs_type = {
  17833. + .owner = THIS_MODULE,
  17834. + .name = "yaffs2",
  17835. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
  17836. + .mount = yaffs2_mount,
  17837. +#else
  17838. + .get_sb = yaffs2_read_super,
  17839. +#endif
  17840. + .kill_sb = kill_block_super,
  17841. + .fs_flags = FS_REQUIRES_DEV,
  17842. +};
  17843. +#else
  17844. +static struct super_block *yaffs2_read_super(struct super_block *sb,
  17845. + void *data, int silent)
  17846. +{
  17847. + return yaffs_internal_read_super(2, sb, data, silent);
  17848. +}
  17849. +
  17850. +static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
  17851. + FS_REQUIRES_DEV);
  17852. +#endif
  17853. +
  17854. +
  17855. +static struct proc_dir_entry *my_proc_entry;
  17856. +
  17857. +static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
  17858. +{
  17859. + struct yaffs_param *param = &dev->param;
  17860. + int bs[10];
  17861. +
  17862. + yaffs_count_blocks_by_state(dev,bs);
  17863. +
  17864. + buf += sprintf(buf, "start_block.......... %d\n", param->start_block);
  17865. + buf += sprintf(buf, "end_block............ %d\n", param->end_block);
  17866. + buf += sprintf(buf, "total_bytes_per_chunk %d\n",
  17867. + param->total_bytes_per_chunk);
  17868. + buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc);
  17869. + buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc);
  17870. + buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2);
  17871. + buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags);
  17872. + buf += sprintf(buf, "empty_lost_n_found... %d\n",
  17873. + param->empty_lost_n_found);
  17874. + buf += sprintf(buf, "disable_lazy_load.... %d\n",
  17875. + param->disable_lazy_load);
  17876. + buf += sprintf(buf, "disable_bad_block_mrk %d\n",
  17877. + param->disable_bad_block_marking);
  17878. + buf += sprintf(buf, "refresh_period....... %d\n",
  17879. + param->refresh_period);
  17880. + buf += sprintf(buf, "n_caches............. %d\n", param->n_caches);
  17881. + buf += sprintf(buf, "n_reserved_blocks.... %d\n",
  17882. + param->n_reserved_blocks);
  17883. + buf += sprintf(buf, "always_check_erased.. %d\n",
  17884. + param->always_check_erased);
  17885. + buf += sprintf(buf, "\n");
  17886. + buf += sprintf(buf, "block count by state\n");
  17887. + buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n",
  17888. + bs[0], bs[1], bs[2], bs[3], bs[4]);
  17889. + buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n",
  17890. + bs[5], bs[6], bs[7], bs[8], bs[9]);
  17891. +
  17892. + return buf;
  17893. +}
  17894. +
  17895. +static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
  17896. +{
  17897. + buf += sprintf(buf, "max file size....... %lld\n",
  17898. + (long long) yaffs_max_file_size(dev));
  17899. + buf += sprintf(buf, "data_bytes_per_chunk. %d\n",
  17900. + dev->data_bytes_per_chunk);
  17901. + buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits);
  17902. + buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size);
  17903. + buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks);
  17904. + buf += sprintf(buf, "blocks_in_checkpt.... %d\n",
  17905. + dev->blocks_in_checkpt);
  17906. + buf += sprintf(buf, "\n");
  17907. + buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes);
  17908. + buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj);
  17909. + buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks);
  17910. + buf += sprintf(buf, "\n");
  17911. + buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes);
  17912. + buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads);
  17913. + buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures);
  17914. + buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies);
  17915. + buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs);
  17916. + buf += sprintf(buf, "passive_gc_count..... %u\n",
  17917. + dev->passive_gc_count);
  17918. + buf += sprintf(buf, "oldest_dirty_gc_count %u\n",
  17919. + dev->oldest_dirty_gc_count);
  17920. + buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks);
  17921. + buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs);
  17922. + buf += sprintf(buf, "n_retried_writes..... %u\n",
  17923. + dev->n_retried_writes);
  17924. + buf += sprintf(buf, "n_retired_blocks..... %u\n",
  17925. + dev->n_retired_blocks);
  17926. + buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed);
  17927. + buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed);
  17928. + buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n",
  17929. + dev->n_tags_ecc_fixed);
  17930. + buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n",
  17931. + dev->n_tags_ecc_unfixed);
  17932. + buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits);
  17933. + buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files);
  17934. + buf += sprintf(buf, "n_unlinked_files..... %u\n",
  17935. + dev->n_unlinked_files);
  17936. + buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
  17937. + buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
  17938. + buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
  17939. + buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
  17940. +
  17941. + return buf;
  17942. +}
  17943. +
  17944. +static int yaffs_proc_read(char *page,
  17945. + char **start,
  17946. + off_t offset, int count, int *eof, void *data)
  17947. +{
  17948. + struct list_head *item;
  17949. + char *buf = page;
  17950. + int step = offset;
  17951. + int n = 0;
  17952. +
  17953. + /* Get proc_file_read() to step 'offset' by one on each sucessive call.
  17954. + * We use 'offset' (*ppos) to indicate where we are in dev_list.
  17955. + * This also assumes the user has posted a read buffer large
  17956. + * enough to hold the complete output; but that's life in /proc.
  17957. + */
  17958. +
  17959. + *(int *)start = 1;
  17960. +
  17961. + /* Print header first */
  17962. + if (step == 0)
  17963. + buf +=
  17964. + sprintf(buf,
  17965. + "Multi-version YAFFS built:" __DATE__ " " __TIME__
  17966. + "\n");
  17967. + else if (step == 1)
  17968. + buf += sprintf(buf, "\n");
  17969. + else {
  17970. + step -= 2;
  17971. +
  17972. + mutex_lock(&yaffs_context_lock);
  17973. +
  17974. + /* Locate and print the Nth entry. Order N-squared but N is small. */
  17975. + list_for_each(item, &yaffs_context_list) {
  17976. + struct yaffs_linux_context *dc =
  17977. + list_entry(item, struct yaffs_linux_context,
  17978. + context_list);
  17979. + struct yaffs_dev *dev = dc->dev;
  17980. +
  17981. + if (n < (step & ~1)) {
  17982. + n += 2;
  17983. + continue;
  17984. + }
  17985. + if ((step & 1) == 0) {
  17986. + buf +=
  17987. + sprintf(buf, "\nDevice %d \"%s\"\n", n,
  17988. + dev->param.name);
  17989. + buf = yaffs_dump_dev_part0(buf, dev);
  17990. + } else {
  17991. + buf = yaffs_dump_dev_part1(buf, dev);
  17992. + }
  17993. +
  17994. + break;
  17995. + }
  17996. + mutex_unlock(&yaffs_context_lock);
  17997. + }
  17998. +
  17999. + return buf - page < count ? buf - page : count;
  18000. +}
  18001. +
  18002. +/**
  18003. + * Set the verbosity of the warnings and error messages.
  18004. + *
  18005. + * Note that the names can only be a..z or _ with the current code.
  18006. + */
  18007. +
  18008. +static struct {
  18009. + char *mask_name;
  18010. + unsigned mask_bitfield;
  18011. +} mask_flags[] = {
  18012. + {"allocate", YAFFS_TRACE_ALLOCATE},
  18013. + {"always", YAFFS_TRACE_ALWAYS},
  18014. + {"background", YAFFS_TRACE_BACKGROUND},
  18015. + {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS},
  18016. + {"buffers", YAFFS_TRACE_BUFFERS},
  18017. + {"bug", YAFFS_TRACE_BUG},
  18018. + {"checkpt", YAFFS_TRACE_CHECKPOINT},
  18019. + {"deletion", YAFFS_TRACE_DELETION},
  18020. + {"erase", YAFFS_TRACE_ERASE},
  18021. + {"error", YAFFS_TRACE_ERROR},
  18022. + {"gc_detail", YAFFS_TRACE_GC_DETAIL},
  18023. + {"gc", YAFFS_TRACE_GC},
  18024. + {"lock", YAFFS_TRACE_LOCK},
  18025. + {"mtd", YAFFS_TRACE_MTD},
  18026. + {"nandaccess", YAFFS_TRACE_NANDACCESS},
  18027. + {"os", YAFFS_TRACE_OS},
  18028. + {"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
  18029. + {"scan", YAFFS_TRACE_SCAN},
  18030. + {"mount", YAFFS_TRACE_MOUNT},
  18031. + {"tracing", YAFFS_TRACE_TRACING},
  18032. + {"sync", YAFFS_TRACE_SYNC},
  18033. + {"write", YAFFS_TRACE_WRITE},
  18034. + {"verify", YAFFS_TRACE_VERIFY},
  18035. + {"verify_nand", YAFFS_TRACE_VERIFY_NAND},
  18036. + {"verify_full", YAFFS_TRACE_VERIFY_FULL},
  18037. + {"verify_all", YAFFS_TRACE_VERIFY_ALL},
  18038. + {"all", 0xffffffff},
  18039. + {"none", 0},
  18040. + {NULL, 0},
  18041. +};
  18042. +
  18043. +#define MAX_MASK_NAME_LENGTH 40
  18044. +static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
  18045. + unsigned long count, void *data)
  18046. +{
  18047. + unsigned rg = 0, mask_bitfield;
  18048. + char *end;
  18049. + char *mask_name;
  18050. + const char *x;
  18051. + char substring[MAX_MASK_NAME_LENGTH + 1];
  18052. + int i;
  18053. + int done = 0;
  18054. + int add, len = 0;
  18055. + int pos = 0;
  18056. +
  18057. + rg = yaffs_trace_mask;
  18058. +
  18059. + while (!done && (pos < count)) {
  18060. + done = 1;
  18061. + while ((pos < count) && isspace(buf[pos]))
  18062. + pos++;
  18063. +
  18064. + switch (buf[pos]) {
  18065. + case '+':
  18066. + case '-':
  18067. + case '=':
  18068. + add = buf[pos];
  18069. + pos++;
  18070. + break;
  18071. +
  18072. + default:
  18073. + add = ' ';
  18074. + break;
  18075. + }
  18076. + mask_name = NULL;
  18077. +
  18078. + mask_bitfield = simple_strtoul(buf + pos, &end, 0);
  18079. +
  18080. + if (end > buf + pos) {
  18081. + mask_name = "numeral";
  18082. + len = end - (buf + pos);
  18083. + pos += len;
  18084. + done = 0;
  18085. + } else {
  18086. + for (x = buf + pos, i = 0;
  18087. + (*x == '_' || (*x >= 'a' && *x <= 'z')) &&
  18088. + i < MAX_MASK_NAME_LENGTH; x++, i++, pos++)
  18089. + substring[i] = *x;
  18090. + substring[i] = '\0';
  18091. +
  18092. + for (i = 0; mask_flags[i].mask_name != NULL; i++) {
  18093. + if (strcmp(substring, mask_flags[i].mask_name)
  18094. + == 0) {
  18095. + mask_name = mask_flags[i].mask_name;
  18096. + mask_bitfield =
  18097. + mask_flags[i].mask_bitfield;
  18098. + done = 0;
  18099. + break;
  18100. + }
  18101. + }
  18102. + }
  18103. +
  18104. + if (mask_name != NULL) {
  18105. + done = 0;
  18106. + switch (add) {
  18107. + case '-':
  18108. + rg &= ~mask_bitfield;
  18109. + break;
  18110. + case '+':
  18111. + rg |= mask_bitfield;
  18112. + break;
  18113. + case '=':
  18114. + rg = mask_bitfield;
  18115. + break;
  18116. + default:
  18117. + rg |= mask_bitfield;
  18118. + break;
  18119. + }
  18120. + }
  18121. + }
  18122. +
  18123. + yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS;
  18124. +
  18125. + printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask);
  18126. +
  18127. + if (rg & YAFFS_TRACE_ALWAYS) {
  18128. + for (i = 0; mask_flags[i].mask_name != NULL; i++) {
  18129. + char flag;
  18130. + flag = ((rg & mask_flags[i].mask_bitfield) ==
  18131. + mask_flags[i].mask_bitfield) ? '+' : '-';
  18132. + printk(KERN_DEBUG "%c%s\n", flag,
  18133. + mask_flags[i].mask_name);
  18134. + }
  18135. + }
  18136. +
  18137. + return count;
  18138. +}
  18139. +
  18140. +/* Debug strings are of the form:
  18141. + * .bnnn print info on block n
  18142. + * .cobjn,chunkn print nand chunk id for objn:chunkn
  18143. + */
  18144. +
  18145. +static int yaffs_proc_debug_write(struct file *file, const char *buf,
  18146. + unsigned long count, void *data)
  18147. +{
  18148. +
  18149. + char str[100];
  18150. + char *p0;
  18151. + char *p1;
  18152. + long p1_val;
  18153. + long p0_val;
  18154. + char cmd;
  18155. + struct list_head *item;
  18156. +
  18157. + memset(str, 0, sizeof(str));
  18158. + memcpy(str, buf, min(count, sizeof(str) -1));
  18159. +
  18160. + cmd = str[1];
  18161. +
  18162. + p0 = str + 2;
  18163. +
  18164. + p1 = p0;
  18165. +
  18166. + while (*p1 && *p1 != ',') {
  18167. + p1++;
  18168. + }
  18169. + *p1 = '\0';
  18170. + p1++;
  18171. +
  18172. + p0_val = simple_strtol(p0, NULL, 0);
  18173. + p1_val = simple_strtol(p1, NULL, 0);
  18174. +
  18175. +
  18176. + mutex_lock(&yaffs_context_lock);
  18177. +
  18178. + /* Locate and print the Nth entry. Order N-squared but N is small. */
  18179. + list_for_each(item, &yaffs_context_list) {
  18180. + struct yaffs_linux_context *dc =
  18181. + list_entry(item, struct yaffs_linux_context,
  18182. + context_list);
  18183. + struct yaffs_dev *dev = dc->dev;
  18184. +
  18185. + if (cmd == 'b') {
  18186. + struct yaffs_block_info *bi;
  18187. +
  18188. + bi = yaffs_get_block_info(dev,p0_val);
  18189. +
  18190. + if(bi) {
  18191. + printk("Block %d: state %d, retire %d, use %d, seq %d\n",
  18192. + (int)p0_val, bi->block_state,
  18193. + bi->needs_retiring, bi->pages_in_use,
  18194. + bi->seq_number);
  18195. + }
  18196. + } else if (cmd == 'c') {
  18197. + struct yaffs_obj *obj;
  18198. + int nand_chunk;
  18199. +
  18200. + obj = yaffs_find_by_number(dev, p0_val);
  18201. + if (!obj)
  18202. + printk("No obj %d\n", (int)p0_val);
  18203. + else {
  18204. + if(p1_val == 0)
  18205. + nand_chunk = obj->hdr_chunk;
  18206. + else
  18207. + nand_chunk =
  18208. + yaffs_find_chunk_in_file(obj,
  18209. + p1_val, NULL);
  18210. + printk("Nand chunk for %d:%d is %d\n",
  18211. + (int)p0_val, (int)p1_val, nand_chunk);
  18212. + }
  18213. + }
  18214. + }
  18215. +
  18216. + mutex_unlock(&yaffs_context_lock);
  18217. +
  18218. + return count;
  18219. +}
  18220. +
  18221. +static int yaffs_proc_write(struct file *file, const char *buf,
  18222. + unsigned long count, void *data)
  18223. +{
  18224. + if (buf[0] == '.')
  18225. + return yaffs_proc_debug_write(file, buf, count, data);
  18226. + return yaffs_proc_write_trace_options(file, buf, count, data);
  18227. +}
  18228. +
  18229. +/* Stuff to handle installation of file systems */
  18230. +struct file_system_to_install {
  18231. + struct file_system_type *fst;
  18232. + int installed;
  18233. +};
  18234. +
  18235. +static struct file_system_to_install fs_to_install[] = {
  18236. + {&yaffs_fs_type, 0},
  18237. + {&yaffs2_fs_type, 0},
  18238. + {NULL, 0}
  18239. +};
  18240. +
  18241. +static int __init init_yaffs_fs(void)
  18242. +{
  18243. + int error = 0;
  18244. + struct file_system_to_install *fsinst;
  18245. +
  18246. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  18247. + "yaffs built " __DATE__ " " __TIME__ " Installing.");
  18248. +
  18249. + mutex_init(&yaffs_context_lock);
  18250. +
  18251. + /* Install the proc_fs entries */
  18252. + my_proc_entry = create_proc_entry("yaffs",
  18253. + S_IRUGO | S_IFREG, YPROC_ROOT);
  18254. +
  18255. + if (my_proc_entry) {
  18256. + my_proc_entry->write_proc = yaffs_proc_write;
  18257. + my_proc_entry->read_proc = yaffs_proc_read;
  18258. + my_proc_entry->data = NULL;
  18259. + } else {
  18260. + return -ENOMEM;
  18261. + }
  18262. +
  18263. + /* Now add the file system entries */
  18264. +
  18265. + fsinst = fs_to_install;
  18266. +
  18267. + while (fsinst->fst && !error) {
  18268. + error = register_filesystem(fsinst->fst);
  18269. + if (!error)
  18270. + fsinst->installed = 1;
  18271. + fsinst++;
  18272. + }
  18273. +
  18274. + /* Any errors? uninstall */
  18275. + if (error) {
  18276. + fsinst = fs_to_install;
  18277. +
  18278. + while (fsinst->fst) {
  18279. + if (fsinst->installed) {
  18280. + unregister_filesystem(fsinst->fst);
  18281. + fsinst->installed = 0;
  18282. + }
  18283. + fsinst++;
  18284. + }
  18285. + }
  18286. +
  18287. + return error;
  18288. +}
  18289. +
  18290. +static void __exit exit_yaffs_fs(void)
  18291. +{
  18292. +
  18293. + struct file_system_to_install *fsinst;
  18294. +
  18295. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  18296. + "yaffs built " __DATE__ " " __TIME__ " removing.");
  18297. +
  18298. + remove_proc_entry("yaffs", YPROC_ROOT);
  18299. +
  18300. + fsinst = fs_to_install;
  18301. +
  18302. + while (fsinst->fst) {
  18303. + if (fsinst->installed) {
  18304. + unregister_filesystem(fsinst->fst);
  18305. + fsinst->installed = 0;
  18306. + }
  18307. + fsinst++;
  18308. + }
  18309. +}
  18310. +
  18311. +module_init(init_yaffs_fs)
  18312. + module_exit(exit_yaffs_fs)
  18313. +
  18314. + MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
  18315. +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
  18316. +MODULE_LICENSE("GPL");
  18317. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs1.c linux-3.14.4/fs/yaffs2/yaffs_yaffs1.c
  18318. --- linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs1.c 1970-01-01 01:00:00.000000000 +0100
  18319. +++ linux-3.14.4/fs/yaffs2/yaffs_yaffs1.c 2014-05-14 12:41:23.992792475 +0200
  18320. @@ -0,0 +1,422 @@
  18321. +/*
  18322. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  18323. + *
  18324. + * Copyright (C) 2002-2011 Aleph One Ltd.
  18325. + * for Toby Churchill Ltd and Brightstar Engineering
  18326. + *
  18327. + * Created by Charles Manning <charles@aleph1.co.uk>
  18328. + *
  18329. + * This program is free software; you can redistribute it and/or modify
  18330. + * it under the terms of the GNU General Public License version 2 as
  18331. + * published by the Free Software Foundation.
  18332. + */
  18333. +
  18334. +#include "yaffs_yaffs1.h"
  18335. +#include "yportenv.h"
  18336. +#include "yaffs_trace.h"
  18337. +#include "yaffs_bitmap.h"
  18338. +#include "yaffs_getblockinfo.h"
  18339. +#include "yaffs_nand.h"
  18340. +#include "yaffs_attribs.h"
  18341. +
  18342. +int yaffs1_scan(struct yaffs_dev *dev)
  18343. +{
  18344. + struct yaffs_ext_tags tags;
  18345. + int blk;
  18346. + int result;
  18347. + int chunk;
  18348. + int c;
  18349. + int deleted;
  18350. + enum yaffs_block_state state;
  18351. + LIST_HEAD(hard_list);
  18352. + struct yaffs_block_info *bi;
  18353. + u32 seq_number;
  18354. + struct yaffs_obj_hdr *oh;
  18355. + struct yaffs_obj *in;
  18356. + struct yaffs_obj *parent;
  18357. + int alloc_failed = 0;
  18358. + struct yaffs_shadow_fixer *shadow_fixers = NULL;
  18359. + u8 *chunk_data;
  18360. +
  18361. + yaffs_trace(YAFFS_TRACE_SCAN,
  18362. + "yaffs1_scan starts intstartblk %d intendblk %d...",
  18363. + dev->internal_start_block, dev->internal_end_block);
  18364. +
  18365. + chunk_data = yaffs_get_temp_buffer(dev);
  18366. +
  18367. + dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
  18368. +
  18369. + /* Scan all the blocks to determine their state */
  18370. + bi = dev->block_info;
  18371. + for (blk = dev->internal_start_block; blk <= dev->internal_end_block;
  18372. + blk++) {
  18373. + yaffs_clear_chunk_bits(dev, blk);
  18374. + bi->pages_in_use = 0;
  18375. + bi->soft_del_pages = 0;
  18376. +
  18377. + yaffs_query_init_block_state(dev, blk, &state, &seq_number);
  18378. +
  18379. + bi->block_state = state;
  18380. + bi->seq_number = seq_number;
  18381. +
  18382. + if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK)
  18383. + bi->block_state = state = YAFFS_BLOCK_STATE_DEAD;
  18384. +
  18385. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG,
  18386. + "Block scanning block %d state %d seq %d",
  18387. + blk, state, seq_number);
  18388. +
  18389. + if (state == YAFFS_BLOCK_STATE_DEAD) {
  18390. + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
  18391. + "block %d is bad", blk);
  18392. + } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
  18393. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty ");
  18394. + dev->n_erased_blocks++;
  18395. + dev->n_free_chunks += dev->param.chunks_per_block;
  18396. + }
  18397. + bi++;
  18398. + }
  18399. +
  18400. + /* For each block.... */
  18401. + for (blk = dev->internal_start_block;
  18402. + !alloc_failed && blk <= dev->internal_end_block; blk++) {
  18403. +
  18404. + cond_resched();
  18405. +
  18406. + bi = yaffs_get_block_info(dev, blk);
  18407. + state = bi->block_state;
  18408. +
  18409. + deleted = 0;
  18410. +
  18411. + /* For each chunk in each block that needs scanning.... */
  18412. + for (c = 0;
  18413. + !alloc_failed && c < dev->param.chunks_per_block &&
  18414. + state == YAFFS_BLOCK_STATE_NEEDS_SCAN; c++) {
  18415. + /* Read the tags and decide what to do */
  18416. + chunk = blk * dev->param.chunks_per_block + c;
  18417. +
  18418. + result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL,
  18419. + &tags);
  18420. +
  18421. + /* Let's have a good look at this chunk... */
  18422. +
  18423. + if (tags.ecc_result == YAFFS_ECC_RESULT_UNFIXED ||
  18424. + tags.is_deleted) {
  18425. + /* YAFFS1 only...
  18426. + * A deleted chunk
  18427. + */
  18428. + deleted++;
  18429. + dev->n_free_chunks++;
  18430. + } else if (!tags.chunk_used) {
  18431. + /* An unassigned chunk in the block
  18432. + * This means that either the block is empty or
  18433. + * this is the one being allocated from
  18434. + */
  18435. +
  18436. + if (c == 0) {
  18437. + /* We're looking at the first chunk in
  18438. + *the block so the block is unused */
  18439. + state = YAFFS_BLOCK_STATE_EMPTY;
  18440. + dev->n_erased_blocks++;
  18441. + } else {
  18442. + /* this is the block being allocated */
  18443. + yaffs_trace(YAFFS_TRACE_SCAN,
  18444. + " Allocating from %d %d",
  18445. + blk, c);
  18446. + state = YAFFS_BLOCK_STATE_ALLOCATING;
  18447. + dev->alloc_block = blk;
  18448. + dev->alloc_page = c;
  18449. + dev->alloc_block_finder = blk;
  18450. +
  18451. + }
  18452. +
  18453. + dev->n_free_chunks +=
  18454. + (dev->param.chunks_per_block - c);
  18455. + } else if (tags.chunk_id > 0) {
  18456. + /* chunk_id > 0 so it is a data chunk... */
  18457. + unsigned int endpos;
  18458. +
  18459. + yaffs_set_chunk_bit(dev, blk, c);
  18460. + bi->pages_in_use++;
  18461. +
  18462. + in = yaffs_find_or_create_by_number(dev,
  18463. + tags.obj_id,
  18464. + YAFFS_OBJECT_TYPE_FILE);
  18465. + /* PutChunkIntoFile checks for a clash
  18466. + * (two data chunks with the same chunk_id).
  18467. + */
  18468. +
  18469. + if (!in)
  18470. + alloc_failed = 1;
  18471. +
  18472. + if (in) {
  18473. + if (!yaffs_put_chunk_in_file
  18474. + (in, tags.chunk_id, chunk, 1))
  18475. + alloc_failed = 1;
  18476. + }
  18477. +
  18478. + endpos =
  18479. + (tags.chunk_id - 1) *
  18480. + dev->data_bytes_per_chunk +
  18481. + tags.n_bytes;
  18482. + if (in &&
  18483. + in->variant_type ==
  18484. + YAFFS_OBJECT_TYPE_FILE &&
  18485. + in->variant.file_variant.scanned_size <
  18486. + endpos) {
  18487. + in->variant.file_variant.scanned_size =
  18488. + endpos;
  18489. + if (!dev->param.use_header_file_size) {
  18490. + in->variant.
  18491. + file_variant.file_size =
  18492. + in->variant.
  18493. + file_variant.scanned_size;
  18494. + }
  18495. +
  18496. + }
  18497. + } else {
  18498. + /* chunk_id == 0, so it is an ObjectHeader.
  18499. + * Make the object
  18500. + */
  18501. + yaffs_set_chunk_bit(dev, blk, c);
  18502. + bi->pages_in_use++;
  18503. +
  18504. + result = yaffs_rd_chunk_tags_nand(dev, chunk,
  18505. + chunk_data,
  18506. + NULL);
  18507. +
  18508. + oh = (struct yaffs_obj_hdr *)chunk_data;
  18509. +
  18510. + in = yaffs_find_by_number(dev, tags.obj_id);
  18511. + if (in && in->variant_type != oh->type) {
  18512. + /* This should not happen, but somehow
  18513. + * Wev'e ended up with an obj_id that
  18514. + * has been reused but not yet deleted,
  18515. + * and worse still it has changed type.
  18516. + * Delete the old object.
  18517. + */
  18518. +
  18519. + yaffs_del_obj(in);
  18520. + in = NULL;
  18521. + }
  18522. +
  18523. + in = yaffs_find_or_create_by_number(dev,
  18524. + tags.obj_id,
  18525. + oh->type);
  18526. +
  18527. + if (!in)
  18528. + alloc_failed = 1;
  18529. +
  18530. + if (in && oh->shadows_obj > 0) {
  18531. +
  18532. + struct yaffs_shadow_fixer *fixer;
  18533. + fixer =
  18534. + kmalloc(sizeof
  18535. + (struct yaffs_shadow_fixer),
  18536. + GFP_NOFS);
  18537. + if (fixer) {
  18538. + fixer->next = shadow_fixers;
  18539. + shadow_fixers = fixer;
  18540. + fixer->obj_id = tags.obj_id;
  18541. + fixer->shadowed_id =
  18542. + oh->shadows_obj;
  18543. + yaffs_trace(YAFFS_TRACE_SCAN,
  18544. + " Shadow fixer: %d shadows %d",
  18545. + fixer->obj_id,
  18546. + fixer->shadowed_id);
  18547. +
  18548. + }
  18549. +
  18550. + }
  18551. +
  18552. + if (in && in->valid) {
  18553. + /* We have already filled this one.
  18554. + * We have a duplicate and need to
  18555. + * resolve it. */
  18556. +
  18557. + unsigned existing_serial = in->serial;
  18558. + unsigned new_serial =
  18559. + tags.serial_number;
  18560. +
  18561. + if (((existing_serial + 1) & 3) ==
  18562. + new_serial) {
  18563. + /* Use new one - destroy the
  18564. + * exisiting one */
  18565. + yaffs_chunk_del(dev,
  18566. + in->hdr_chunk,
  18567. + 1, __LINE__);
  18568. + in->valid = 0;
  18569. + } else {
  18570. + /* Use existing - destroy
  18571. + * this one. */
  18572. + yaffs_chunk_del(dev, chunk, 1,
  18573. + __LINE__);
  18574. + }
  18575. + }
  18576. +
  18577. + if (in && !in->valid &&
  18578. + (tags.obj_id == YAFFS_OBJECTID_ROOT ||
  18579. + tags.obj_id ==
  18580. + YAFFS_OBJECTID_LOSTNFOUND)) {
  18581. + /* We only load some info, don't fiddle
  18582. + * with directory structure */
  18583. + in->valid = 1;
  18584. + in->variant_type = oh->type;
  18585. +
  18586. + in->yst_mode = oh->yst_mode;
  18587. + yaffs_load_attribs(in, oh);
  18588. + in->hdr_chunk = chunk;
  18589. + in->serial = tags.serial_number;
  18590. +
  18591. + } else if (in && !in->valid) {
  18592. + /* we need to load this info */
  18593. +
  18594. + in->valid = 1;
  18595. + in->variant_type = oh->type;
  18596. +
  18597. + in->yst_mode = oh->yst_mode;
  18598. + yaffs_load_attribs(in, oh);
  18599. + in->hdr_chunk = chunk;
  18600. + in->serial = tags.serial_number;
  18601. +
  18602. + yaffs_set_obj_name_from_oh(in, oh);
  18603. + in->dirty = 0;
  18604. +
  18605. + /* directory stuff...
  18606. + * hook up to parent
  18607. + */
  18608. +
  18609. + parent =
  18610. + yaffs_find_or_create_by_number
  18611. + (dev, oh->parent_obj_id,
  18612. + YAFFS_OBJECT_TYPE_DIRECTORY);
  18613. + if (!parent)
  18614. + alloc_failed = 1;
  18615. + if (parent && parent->variant_type ==
  18616. + YAFFS_OBJECT_TYPE_UNKNOWN) {
  18617. + /* Set up as a directory */
  18618. + parent->variant_type =
  18619. + YAFFS_OBJECT_TYPE_DIRECTORY;
  18620. + INIT_LIST_HEAD(&parent->
  18621. + variant.dir_variant.
  18622. + children);
  18623. + } else if (!parent ||
  18624. + parent->variant_type !=
  18625. + YAFFS_OBJECT_TYPE_DIRECTORY) {
  18626. + /* Hoosterman, a problem....
  18627. + * We're trying to use a
  18628. + * non-directory as a directory
  18629. + */
  18630. +
  18631. + yaffs_trace(YAFFS_TRACE_ERROR,
  18632. + "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
  18633. + );
  18634. + parent = dev->lost_n_found;
  18635. + }
  18636. +
  18637. + yaffs_add_obj_to_dir(parent, in);
  18638. +
  18639. + switch (in->variant_type) {
  18640. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  18641. + /* Todo got a problem */
  18642. + break;
  18643. + case YAFFS_OBJECT_TYPE_FILE:
  18644. + if (dev->param.
  18645. + use_header_file_size)
  18646. + in->variant.
  18647. + file_variant.file_size
  18648. + = yaffs_oh_to_size(oh);
  18649. + break;
  18650. + case YAFFS_OBJECT_TYPE_HARDLINK:
  18651. + in->variant.
  18652. + hardlink_variant.equiv_id =
  18653. + oh->equiv_id;
  18654. + list_add(&in->hard_links,
  18655. + &hard_list);
  18656. + break;
  18657. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  18658. + /* Do nothing */
  18659. + break;
  18660. + case YAFFS_OBJECT_TYPE_SPECIAL:
  18661. + /* Do nothing */
  18662. + break;
  18663. + case YAFFS_OBJECT_TYPE_SYMLINK:
  18664. + in->variant.symlink_variant.
  18665. + alias =
  18666. + yaffs_clone_str(oh->alias);
  18667. + if (!in->variant.
  18668. + symlink_variant.alias)
  18669. + alloc_failed = 1;
  18670. + break;
  18671. + }
  18672. + }
  18673. + }
  18674. + }
  18675. +
  18676. + if (state == YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  18677. + /* If we got this far while scanning,
  18678. + * then the block is fully allocated. */
  18679. + state = YAFFS_BLOCK_STATE_FULL;
  18680. + }
  18681. +
  18682. + if (state == YAFFS_BLOCK_STATE_ALLOCATING) {
  18683. + /* If the block was partially allocated then
  18684. + * treat it as fully allocated. */
  18685. + state = YAFFS_BLOCK_STATE_FULL;
  18686. + dev->alloc_block = -1;
  18687. + }
  18688. +
  18689. + bi->block_state = state;
  18690. +
  18691. + /* Now let's see if it was dirty */
  18692. + if (bi->pages_in_use == 0 &&
  18693. + !bi->has_shrink_hdr &&
  18694. + bi->block_state == YAFFS_BLOCK_STATE_FULL)
  18695. + yaffs_block_became_dirty(dev, blk);
  18696. + }
  18697. +
  18698. + /* Ok, we've done all the scanning.
  18699. + * Fix up the hard link chains.
  18700. + * We should now have scanned all the objects, now it's time to add
  18701. + * these hardlinks.
  18702. + */
  18703. +
  18704. + yaffs_link_fixup(dev, &hard_list);
  18705. +
  18706. + /*
  18707. + * Fix up any shadowed objects.
  18708. + * There should not be more than one of these.
  18709. + */
  18710. + {
  18711. + struct yaffs_shadow_fixer *fixer;
  18712. + struct yaffs_obj *obj;
  18713. +
  18714. + while (shadow_fixers) {
  18715. + fixer = shadow_fixers;
  18716. + shadow_fixers = fixer->next;
  18717. + /* Complete the rename transaction by deleting the
  18718. + * shadowed object then setting the object header
  18719. + to unshadowed.
  18720. + */
  18721. + obj = yaffs_find_by_number(dev, fixer->shadowed_id);
  18722. + if (obj)
  18723. + yaffs_del_obj(obj);
  18724. +
  18725. + obj = yaffs_find_by_number(dev, fixer->obj_id);
  18726. +
  18727. + if (obj)
  18728. + yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
  18729. +
  18730. + kfree(fixer);
  18731. + }
  18732. + }
  18733. +
  18734. + yaffs_release_temp_buffer(dev, chunk_data);
  18735. +
  18736. + if (alloc_failed)
  18737. + return YAFFS_FAIL;
  18738. +
  18739. + yaffs_trace(YAFFS_TRACE_SCAN, "yaffs1_scan ends");
  18740. +
  18741. + return YAFFS_OK;
  18742. +}
  18743. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs1.h linux-3.14.4/fs/yaffs2/yaffs_yaffs1.h
  18744. --- linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs1.h 1970-01-01 01:00:00.000000000 +0100
  18745. +++ linux-3.14.4/fs/yaffs2/yaffs_yaffs1.h 2014-05-14 12:41:23.992792475 +0200
  18746. @@ -0,0 +1,22 @@
  18747. +/*
  18748. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  18749. + *
  18750. + * Copyright (C) 2002-2011 Aleph One Ltd.
  18751. + * for Toby Churchill Ltd and Brightstar Engineering
  18752. + *
  18753. + * Created by Charles Manning <charles@aleph1.co.uk>
  18754. + *
  18755. + * This program is free software; you can redistribute it and/or modify
  18756. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  18757. + * published by the Free Software Foundation.
  18758. + *
  18759. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  18760. + */
  18761. +
  18762. +#ifndef __YAFFS_YAFFS1_H__
  18763. +#define __YAFFS_YAFFS1_H__
  18764. +
  18765. +#include "yaffs_guts.h"
  18766. +int yaffs1_scan(struct yaffs_dev *dev);
  18767. +
  18768. +#endif
  18769. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs2.c linux-3.14.4/fs/yaffs2/yaffs_yaffs2.c
  18770. --- linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs2.c 1970-01-01 01:00:00.000000000 +0100
  18771. +++ linux-3.14.4/fs/yaffs2/yaffs_yaffs2.c 2014-05-14 12:41:24.012792539 +0200
  18772. @@ -0,0 +1,1534 @@
  18773. +/*
  18774. + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  18775. + *
  18776. + * Copyright (C) 2002-2011 Aleph One Ltd.
  18777. + * for Toby Churchill Ltd and Brightstar Engineering
  18778. + *
  18779. + * Created by Charles Manning <charles@aleph1.co.uk>
  18780. + *
  18781. + * This program is free software; you can redistribute it and/or modify
  18782. + * it under the terms of the GNU General Public License version 2 as
  18783. + * published by the Free Software Foundation.
  18784. + */
  18785. +
  18786. +#include "yaffs_guts.h"
  18787. +#include "yaffs_trace.h"
  18788. +#include "yaffs_yaffs2.h"
  18789. +#include "yaffs_checkptrw.h"
  18790. +#include "yaffs_bitmap.h"
  18791. +#include "yaffs_nand.h"
  18792. +#include "yaffs_getblockinfo.h"
  18793. +#include "yaffs_verify.h"
  18794. +#include "yaffs_attribs.h"
  18795. +#include "yaffs_summary.h"
  18796. +
  18797. +/*
  18798. + * Checkpoints are really no benefit on very small partitions.
  18799. + *
  18800. + * To save space on small partitions don't bother with checkpoints unless
  18801. + * the partition is at least this big.
  18802. + */
  18803. +#define YAFFS_CHECKPOINT_MIN_BLOCKS 60
  18804. +#define YAFFS_SMALL_HOLE_THRESHOLD 4
  18805. +
  18806. +/*
  18807. + * Oldest Dirty Sequence Number handling.
  18808. + */
  18809. +
  18810. +/* yaffs_calc_oldest_dirty_seq()
  18811. + * yaffs2_find_oldest_dirty_seq()
  18812. + * Calculate the oldest dirty sequence number if we don't know it.
  18813. + */
  18814. +void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev)
  18815. +{
  18816. + int i;
  18817. + unsigned seq;
  18818. + unsigned block_no = 0;
  18819. + struct yaffs_block_info *b;
  18820. +
  18821. + if (!dev->param.is_yaffs2)
  18822. + return;
  18823. +
  18824. + /* Find the oldest dirty sequence number. */
  18825. + seq = dev->seq_number + 1;
  18826. + b = dev->block_info;
  18827. + for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
  18828. + if (b->block_state == YAFFS_BLOCK_STATE_FULL &&
  18829. + (b->pages_in_use - b->soft_del_pages) <
  18830. + dev->param.chunks_per_block &&
  18831. + b->seq_number < seq) {
  18832. + seq = b->seq_number;
  18833. + block_no = i;
  18834. + }
  18835. + b++;
  18836. + }
  18837. +
  18838. + if (block_no) {
  18839. + dev->oldest_dirty_seq = seq;
  18840. + dev->oldest_dirty_block = block_no;
  18841. + }
  18842. +}
  18843. +
  18844. +void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev)
  18845. +{
  18846. + if (!dev->param.is_yaffs2)
  18847. + return;
  18848. +
  18849. + if (!dev->oldest_dirty_seq)
  18850. + yaffs_calc_oldest_dirty_seq(dev);
  18851. +}
  18852. +
  18853. +/*
  18854. + * yaffs_clear_oldest_dirty_seq()
  18855. + * Called when a block is erased or marked bad. (ie. when its seq_number
  18856. + * becomes invalid). If the value matches the oldest then we clear
  18857. + * dev->oldest_dirty_seq to force its recomputation.
  18858. + */
  18859. +void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev,
  18860. + struct yaffs_block_info *bi)
  18861. +{
  18862. +
  18863. + if (!dev->param.is_yaffs2)
  18864. + return;
  18865. +
  18866. + if (!bi || bi->seq_number == dev->oldest_dirty_seq) {
  18867. + dev->oldest_dirty_seq = 0;
  18868. + dev->oldest_dirty_block = 0;
  18869. + }
  18870. +}
  18871. +
  18872. +/*
  18873. + * yaffs2_update_oldest_dirty_seq()
  18874. + * Update the oldest dirty sequence number whenever we dirty a block.
  18875. + * Only do this if the oldest_dirty_seq is actually being tracked.
  18876. + */
  18877. +void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no,
  18878. + struct yaffs_block_info *bi)
  18879. +{
  18880. + if (!dev->param.is_yaffs2)
  18881. + return;
  18882. +
  18883. + if (dev->oldest_dirty_seq) {
  18884. + if (dev->oldest_dirty_seq > bi->seq_number) {
  18885. + dev->oldest_dirty_seq = bi->seq_number;
  18886. + dev->oldest_dirty_block = block_no;
  18887. + }
  18888. + }
  18889. +}
  18890. +
  18891. +int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi)
  18892. +{
  18893. +
  18894. + if (!dev->param.is_yaffs2)
  18895. + return 1; /* disqualification only applies to yaffs2. */
  18896. +
  18897. + if (!bi->has_shrink_hdr)
  18898. + return 1; /* can gc */
  18899. +
  18900. + yaffs2_find_oldest_dirty_seq(dev);
  18901. +
  18902. + /* Can't do gc of this block if there are any blocks older than this
  18903. + * one that have discarded pages.
  18904. + */
  18905. + return (bi->seq_number <= dev->oldest_dirty_seq);
  18906. +}
  18907. +
  18908. +/*
  18909. + * yaffs2_find_refresh_block()
  18910. + * periodically finds the oldest full block by sequence number for refreshing.
  18911. + * Only for yaffs2.
  18912. + */
  18913. +u32 yaffs2_find_refresh_block(struct yaffs_dev *dev)
  18914. +{
  18915. + u32 b;
  18916. + u32 oldest = 0;
  18917. + u32 oldest_seq = 0;
  18918. + struct yaffs_block_info *bi;
  18919. +
  18920. + if (!dev->param.is_yaffs2)
  18921. + return oldest;
  18922. +
  18923. + /*
  18924. + * If refresh period < 10 then refreshing is disabled.
  18925. + */
  18926. + if (dev->param.refresh_period < 10)
  18927. + return oldest;
  18928. +
  18929. + /*
  18930. + * Fix broken values.
  18931. + */
  18932. + if (dev->refresh_skip > dev->param.refresh_period)
  18933. + dev->refresh_skip = dev->param.refresh_period;
  18934. +
  18935. + if (dev->refresh_skip > 0)
  18936. + return oldest;
  18937. +
  18938. + /*
  18939. + * Refresh skip is now zero.
  18940. + * We'll do a refresh this time around....
  18941. + * Update the refresh skip and find the oldest block.
  18942. + */
  18943. + dev->refresh_skip = dev->param.refresh_period;
  18944. + dev->refresh_count++;
  18945. + bi = dev->block_info;
  18946. + for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) {
  18947. +
  18948. + if (bi->block_state == YAFFS_BLOCK_STATE_FULL) {
  18949. +
  18950. + if (oldest < 1 || bi->seq_number < oldest_seq) {
  18951. + oldest = b;
  18952. + oldest_seq = bi->seq_number;
  18953. + }
  18954. + }
  18955. + bi++;
  18956. + }
  18957. +
  18958. + if (oldest > 0) {
  18959. + yaffs_trace(YAFFS_TRACE_GC,
  18960. + "GC refresh count %d selected block %d with seq_number %d",
  18961. + dev->refresh_count, oldest, oldest_seq);
  18962. + }
  18963. +
  18964. + return oldest;
  18965. +}
  18966. +
  18967. +int yaffs2_checkpt_required(struct yaffs_dev *dev)
  18968. +{
  18969. + int nblocks;
  18970. +
  18971. + if (!dev->param.is_yaffs2)
  18972. + return 0;
  18973. +
  18974. + nblocks = dev->internal_end_block - dev->internal_start_block + 1;
  18975. +
  18976. + return !dev->param.skip_checkpt_wr &&
  18977. + !dev->read_only && (nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS);
  18978. +}
  18979. +
  18980. +int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev)
  18981. +{
  18982. + int retval;
  18983. + int n_bytes = 0;
  18984. + int n_blocks;
  18985. + int dev_blocks;
  18986. +
  18987. + if (!dev->param.is_yaffs2)
  18988. + return 0;
  18989. +
  18990. + if (!dev->checkpoint_blocks_required && yaffs2_checkpt_required(dev)) {
  18991. + /* Not a valid value so recalculate */
  18992. + dev_blocks = dev->param.end_block - dev->param.start_block + 1;
  18993. + n_bytes += sizeof(struct yaffs_checkpt_validity);
  18994. + n_bytes += sizeof(struct yaffs_checkpt_dev);
  18995. + n_bytes += dev_blocks * sizeof(struct yaffs_block_info);
  18996. + n_bytes += dev_blocks * dev->chunk_bit_stride;
  18997. + n_bytes +=
  18998. + (sizeof(struct yaffs_checkpt_obj) + sizeof(u32)) *
  18999. + dev->n_obj;
  19000. + n_bytes += (dev->tnode_size + sizeof(u32)) * dev->n_tnodes;
  19001. + n_bytes += sizeof(struct yaffs_checkpt_validity);
  19002. + n_bytes += sizeof(u32); /* checksum */
  19003. +
  19004. + /* Round up and add 2 blocks to allow for some bad blocks,
  19005. + * so add 3 */
  19006. +
  19007. + n_blocks =
  19008. + (n_bytes /
  19009. + (dev->data_bytes_per_chunk *
  19010. + dev->param.chunks_per_block)) + 3;
  19011. +
  19012. + dev->checkpoint_blocks_required = n_blocks;
  19013. + }
  19014. +
  19015. + retval = dev->checkpoint_blocks_required - dev->blocks_in_checkpt;
  19016. + if (retval < 0)
  19017. + retval = 0;
  19018. + return retval;
  19019. +}
  19020. +
  19021. +/*--------------------- Checkpointing --------------------*/
  19022. +
  19023. +static int yaffs2_wr_checkpt_validity_marker(struct yaffs_dev *dev, int head)
  19024. +{
  19025. + struct yaffs_checkpt_validity cp;
  19026. +
  19027. + memset(&cp, 0, sizeof(cp));
  19028. +
  19029. + cp.struct_type = sizeof(cp);
  19030. + cp.magic = YAFFS_MAGIC;
  19031. + cp.version = YAFFS_CHECKPOINT_VERSION;
  19032. + cp.head = (head) ? 1 : 0;
  19033. +
  19034. + return (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)) ? 1 : 0;
  19035. +}
  19036. +
  19037. +static int yaffs2_rd_checkpt_validity_marker(struct yaffs_dev *dev, int head)
  19038. +{
  19039. + struct yaffs_checkpt_validity cp;
  19040. + int ok;
  19041. +
  19042. + ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
  19043. +
  19044. + if (ok)
  19045. + ok = (cp.struct_type == sizeof(cp)) &&
  19046. + (cp.magic == YAFFS_MAGIC) &&
  19047. + (cp.version == YAFFS_CHECKPOINT_VERSION) &&
  19048. + (cp.head == ((head) ? 1 : 0));
  19049. + return ok ? 1 : 0;
  19050. +}
  19051. +
  19052. +static void yaffs2_dev_to_checkpt_dev(struct yaffs_checkpt_dev *cp,
  19053. + struct yaffs_dev *dev)
  19054. +{
  19055. + cp->n_erased_blocks = dev->n_erased_blocks;
  19056. + cp->alloc_block = dev->alloc_block;
  19057. + cp->alloc_page = dev->alloc_page;
  19058. + cp->n_free_chunks = dev->n_free_chunks;
  19059. +
  19060. + cp->n_deleted_files = dev->n_deleted_files;
  19061. + cp->n_unlinked_files = dev->n_unlinked_files;
  19062. + cp->n_bg_deletions = dev->n_bg_deletions;
  19063. + cp->seq_number = dev->seq_number;
  19064. +
  19065. +}
  19066. +
  19067. +static void yaffs_checkpt_dev_to_dev(struct yaffs_dev *dev,
  19068. + struct yaffs_checkpt_dev *cp)
  19069. +{
  19070. + dev->n_erased_blocks = cp->n_erased_blocks;
  19071. + dev->alloc_block = cp->alloc_block;
  19072. + dev->alloc_page = cp->alloc_page;
  19073. + dev->n_free_chunks = cp->n_free_chunks;
  19074. +
  19075. + dev->n_deleted_files = cp->n_deleted_files;
  19076. + dev->n_unlinked_files = cp->n_unlinked_files;
  19077. + dev->n_bg_deletions = cp->n_bg_deletions;
  19078. + dev->seq_number = cp->seq_number;
  19079. +}
  19080. +
  19081. +static int yaffs2_wr_checkpt_dev(struct yaffs_dev *dev)
  19082. +{
  19083. + struct yaffs_checkpt_dev cp;
  19084. + u32 n_bytes;
  19085. + u32 n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
  19086. + int ok;
  19087. +
  19088. + /* Write device runtime values */
  19089. + yaffs2_dev_to_checkpt_dev(&cp, dev);
  19090. + cp.struct_type = sizeof(cp);
  19091. +
  19092. + ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
  19093. + if (!ok)
  19094. + return 0;
  19095. +
  19096. + /* Write block info */
  19097. + n_bytes = n_blocks * sizeof(struct yaffs_block_info);
  19098. + ok = (yaffs2_checkpt_wr(dev, dev->block_info, n_bytes) == n_bytes);
  19099. + if (!ok)
  19100. + return 0;
  19101. +
  19102. + /* Write chunk bits */
  19103. + n_bytes = n_blocks * dev->chunk_bit_stride;
  19104. + ok = (yaffs2_checkpt_wr(dev, dev->chunk_bits, n_bytes) == n_bytes);
  19105. +
  19106. + return ok ? 1 : 0;
  19107. +}
  19108. +
  19109. +static int yaffs2_rd_checkpt_dev(struct yaffs_dev *dev)
  19110. +{
  19111. + struct yaffs_checkpt_dev cp;
  19112. + u32 n_bytes;
  19113. + u32 n_blocks =
  19114. + (dev->internal_end_block - dev->internal_start_block + 1);
  19115. + int ok;
  19116. +
  19117. + ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
  19118. + if (!ok)
  19119. + return 0;
  19120. +
  19121. + if (cp.struct_type != sizeof(cp))
  19122. + return 0;
  19123. +
  19124. + yaffs_checkpt_dev_to_dev(dev, &cp);
  19125. +
  19126. + n_bytes = n_blocks * sizeof(struct yaffs_block_info);
  19127. +
  19128. + ok = (yaffs2_checkpt_rd(dev, dev->block_info, n_bytes) == n_bytes);
  19129. +
  19130. + if (!ok)
  19131. + return 0;
  19132. +
  19133. + n_bytes = n_blocks * dev->chunk_bit_stride;
  19134. +
  19135. + ok = (yaffs2_checkpt_rd(dev, dev->chunk_bits, n_bytes) == n_bytes);
  19136. +
  19137. + return ok ? 1 : 0;
  19138. +}
  19139. +
  19140. +static void yaffs2_obj_checkpt_obj(struct yaffs_checkpt_obj *cp,
  19141. + struct yaffs_obj *obj)
  19142. +{
  19143. + cp->obj_id = obj->obj_id;
  19144. + cp->parent_id = (obj->parent) ? obj->parent->obj_id : 0;
  19145. + cp->hdr_chunk = obj->hdr_chunk;
  19146. + cp->variant_type = obj->variant_type;
  19147. + cp->deleted = obj->deleted;
  19148. + cp->soft_del = obj->soft_del;
  19149. + cp->unlinked = obj->unlinked;
  19150. + cp->fake = obj->fake;
  19151. + cp->rename_allowed = obj->rename_allowed;
  19152. + cp->unlink_allowed = obj->unlink_allowed;
  19153. + cp->serial = obj->serial;
  19154. + cp->n_data_chunks = obj->n_data_chunks;
  19155. +
  19156. + if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
  19157. + cp->size_or_equiv_obj = obj->variant.file_variant.file_size;
  19158. + else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK)
  19159. + cp->size_or_equiv_obj = obj->variant.hardlink_variant.equiv_id;
  19160. +}
  19161. +
  19162. +static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj,
  19163. + struct yaffs_checkpt_obj *cp)
  19164. +{
  19165. + struct yaffs_obj *parent;
  19166. +
  19167. + if (obj->variant_type != cp->variant_type) {
  19168. + yaffs_trace(YAFFS_TRACE_ERROR,
  19169. + "Checkpoint read object %d type %d chunk %d does not match existing object type %d",
  19170. + cp->obj_id, cp->variant_type, cp->hdr_chunk,
  19171. + obj->variant_type);
  19172. + return 0;
  19173. + }
  19174. +
  19175. + obj->obj_id = cp->obj_id;
  19176. +
  19177. + if (cp->parent_id)
  19178. + parent = yaffs_find_or_create_by_number(obj->my_dev,
  19179. + cp->parent_id,
  19180. + YAFFS_OBJECT_TYPE_DIRECTORY);
  19181. + else
  19182. + parent = NULL;
  19183. +
  19184. + if (parent) {
  19185. + if (parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
  19186. + yaffs_trace(YAFFS_TRACE_ALWAYS,
  19187. + "Checkpoint read object %d parent %d type %d chunk %d Parent type, %d, not directory",
  19188. + cp->obj_id, cp->parent_id,
  19189. + cp->variant_type, cp->hdr_chunk,
  19190. + parent->variant_type);
  19191. + return 0;
  19192. + }
  19193. + yaffs_add_obj_to_dir(parent, obj);
  19194. + }
  19195. +
  19196. + obj->hdr_chunk = cp->hdr_chunk;
  19197. + obj->variant_type = cp->variant_type;
  19198. + obj->deleted = cp->deleted;
  19199. + obj->soft_del = cp->soft_del;
  19200. + obj->unlinked = cp->unlinked;
  19201. + obj->fake = cp->fake;
  19202. + obj->rename_allowed = cp->rename_allowed;
  19203. + obj->unlink_allowed = cp->unlink_allowed;
  19204. + obj->serial = cp->serial;
  19205. + obj->n_data_chunks = cp->n_data_chunks;
  19206. +
  19207. + if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
  19208. + obj->variant.file_variant.file_size = cp->size_or_equiv_obj;
  19209. + else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK)
  19210. + obj->variant.hardlink_variant.equiv_id = cp->size_or_equiv_obj;
  19211. +
  19212. + if (obj->hdr_chunk > 0)
  19213. + obj->lazy_loaded = 1;
  19214. + return 1;
  19215. +}
  19216. +
  19217. +static int yaffs2_checkpt_tnode_worker(struct yaffs_obj *in,
  19218. + struct yaffs_tnode *tn, u32 level,
  19219. + int chunk_offset)
  19220. +{
  19221. + int i;
  19222. + struct yaffs_dev *dev = in->my_dev;
  19223. + int ok = 1;
  19224. + u32 base_offset;
  19225. +
  19226. + if (!tn)
  19227. + return 1;
  19228. +
  19229. + if (level > 0) {
  19230. + for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {
  19231. + if (!tn->internal[i])
  19232. + continue;
  19233. + ok = yaffs2_checkpt_tnode_worker(in,
  19234. + tn->internal[i],
  19235. + level - 1,
  19236. + (chunk_offset <<
  19237. + YAFFS_TNODES_INTERNAL_BITS) + i);
  19238. + }
  19239. + return ok;
  19240. + }
  19241. +
  19242. + /* Level 0 tnode */
  19243. + base_offset = chunk_offset << YAFFS_TNODES_LEVEL0_BITS;
  19244. + ok = (yaffs2_checkpt_wr(dev, &base_offset, sizeof(base_offset)) ==
  19245. + sizeof(base_offset));
  19246. + if (ok)
  19247. + ok = (yaffs2_checkpt_wr(dev, tn, dev->tnode_size) ==
  19248. + dev->tnode_size);
  19249. +
  19250. + return ok;
  19251. +}
  19252. +
  19253. +static int yaffs2_wr_checkpt_tnodes(struct yaffs_obj *obj)
  19254. +{
  19255. + u32 end_marker = ~0;
  19256. + int ok = 1;
  19257. +
  19258. + if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
  19259. + return ok;
  19260. +
  19261. + ok = yaffs2_checkpt_tnode_worker(obj,
  19262. + obj->variant.file_variant.top,
  19263. + obj->variant.file_variant.
  19264. + top_level, 0);
  19265. + if (ok)
  19266. + ok = (yaffs2_checkpt_wr(obj->my_dev, &end_marker,
  19267. + sizeof(end_marker)) == sizeof(end_marker));
  19268. +
  19269. + return ok ? 1 : 0;
  19270. +}
  19271. +
  19272. +static int yaffs2_rd_checkpt_tnodes(struct yaffs_obj *obj)
  19273. +{
  19274. + u32 base_chunk;
  19275. + int ok = 1;
  19276. + struct yaffs_dev *dev = obj->my_dev;
  19277. + struct yaffs_file_var *file_stuct_ptr = &obj->variant.file_variant;
  19278. + struct yaffs_tnode *tn;
  19279. + int nread = 0;
  19280. +
  19281. + ok = (yaffs2_checkpt_rd(dev, &base_chunk, sizeof(base_chunk)) ==
  19282. + sizeof(base_chunk));
  19283. +
  19284. + while (ok && (~base_chunk)) {
  19285. + nread++;
  19286. + /* Read level 0 tnode */
  19287. +
  19288. + tn = yaffs_get_tnode(dev);
  19289. + if (tn)
  19290. + ok = (yaffs2_checkpt_rd(dev, tn, dev->tnode_size) ==
  19291. + dev->tnode_size);
  19292. + else
  19293. + ok = 0;
  19294. +
  19295. + if (tn && ok)
  19296. + ok = yaffs_add_find_tnode_0(dev,
  19297. + file_stuct_ptr,
  19298. + base_chunk, tn) ? 1 : 0;
  19299. +
  19300. + if (ok)
  19301. + ok = (yaffs2_checkpt_rd
  19302. + (dev, &base_chunk,
  19303. + sizeof(base_chunk)) == sizeof(base_chunk));
  19304. + }
  19305. +
  19306. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19307. + "Checkpoint read tnodes %d records, last %d. ok %d",
  19308. + nread, base_chunk, ok);
  19309. +
  19310. + return ok ? 1 : 0;
  19311. +}
  19312. +
  19313. +static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev)
  19314. +{
  19315. + struct yaffs_obj *obj;
  19316. + struct yaffs_checkpt_obj cp;
  19317. + int i;
  19318. + int ok = 1;
  19319. + struct list_head *lh;
  19320. +
  19321. + /* Iterate through the objects in each hash entry,
  19322. + * dumping them to the checkpointing stream.
  19323. + */
  19324. +
  19325. + for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) {
  19326. + list_for_each(lh, &dev->obj_bucket[i].list) {
  19327. + obj = list_entry(lh, struct yaffs_obj, hash_link);
  19328. + if (!obj->defered_free) {
  19329. + yaffs2_obj_checkpt_obj(&cp, obj);
  19330. + cp.struct_type = sizeof(cp);
  19331. +
  19332. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19333. + "Checkpoint write object %d parent %d type %d chunk %d obj addr %p",
  19334. + cp.obj_id, cp.parent_id,
  19335. + cp.variant_type, cp.hdr_chunk, obj);
  19336. +
  19337. + ok = (yaffs2_checkpt_wr(dev, &cp,
  19338. + sizeof(cp)) == sizeof(cp));
  19339. +
  19340. + if (ok &&
  19341. + obj->variant_type ==
  19342. + YAFFS_OBJECT_TYPE_FILE)
  19343. + ok = yaffs2_wr_checkpt_tnodes(obj);
  19344. + }
  19345. + }
  19346. + }
  19347. +
  19348. + /* Dump end of list */
  19349. + memset(&cp, 0xff, sizeof(struct yaffs_checkpt_obj));
  19350. + cp.struct_type = sizeof(cp);
  19351. +
  19352. + if (ok)
  19353. + ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
  19354. +
  19355. + return ok ? 1 : 0;
  19356. +}
  19357. +
  19358. +static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev)
  19359. +{
  19360. + struct yaffs_obj *obj;
  19361. + struct yaffs_checkpt_obj cp;
  19362. + int ok = 1;
  19363. + int done = 0;
  19364. + LIST_HEAD(hard_list);
  19365. +
  19366. +
  19367. + while (ok && !done) {
  19368. + ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
  19369. + if (cp.struct_type != sizeof(cp)) {
  19370. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19371. + "struct size %d instead of %d ok %d",
  19372. + cp.struct_type, (int)sizeof(cp), ok);
  19373. + ok = 0;
  19374. + }
  19375. +
  19376. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19377. + "Checkpoint read object %d parent %d type %d chunk %d ",
  19378. + cp.obj_id, cp.parent_id, cp.variant_type,
  19379. + cp.hdr_chunk);
  19380. +
  19381. + if (ok && cp.obj_id == ~0) {
  19382. + done = 1;
  19383. + } else if (ok) {
  19384. + obj =
  19385. + yaffs_find_or_create_by_number(dev, cp.obj_id,
  19386. + cp.variant_type);
  19387. + if (obj) {
  19388. + ok = yaffs2_checkpt_obj_to_obj(obj, &cp);
  19389. + if (!ok)
  19390. + break;
  19391. + if (obj->variant_type ==
  19392. + YAFFS_OBJECT_TYPE_FILE) {
  19393. + ok = yaffs2_rd_checkpt_tnodes(obj);
  19394. + } else if (obj->variant_type ==
  19395. + YAFFS_OBJECT_TYPE_HARDLINK) {
  19396. + list_add(&obj->hard_links, &hard_list);
  19397. + }
  19398. + } else {
  19399. + ok = 0;
  19400. + }
  19401. + }
  19402. + }
  19403. +
  19404. + if (ok)
  19405. + yaffs_link_fixup(dev, &hard_list);
  19406. +
  19407. + return ok ? 1 : 0;
  19408. +}
  19409. +
  19410. +static int yaffs2_wr_checkpt_sum(struct yaffs_dev *dev)
  19411. +{
  19412. + u32 checkpt_sum;
  19413. + int ok;
  19414. +
  19415. + yaffs2_get_checkpt_sum(dev, &checkpt_sum);
  19416. +
  19417. + ok = (yaffs2_checkpt_wr(dev, &checkpt_sum, sizeof(checkpt_sum)) ==
  19418. + sizeof(checkpt_sum));
  19419. +
  19420. + if (!ok)
  19421. + return 0;
  19422. +
  19423. + return 1;
  19424. +}
  19425. +
  19426. +static int yaffs2_rd_checkpt_sum(struct yaffs_dev *dev)
  19427. +{
  19428. + u32 checkpt_sum0;
  19429. + u32 checkpt_sum1;
  19430. + int ok;
  19431. +
  19432. + yaffs2_get_checkpt_sum(dev, &checkpt_sum0);
  19433. +
  19434. + ok = (yaffs2_checkpt_rd(dev, &checkpt_sum1, sizeof(checkpt_sum1)) ==
  19435. + sizeof(checkpt_sum1));
  19436. +
  19437. + if (!ok)
  19438. + return 0;
  19439. +
  19440. + if (checkpt_sum0 != checkpt_sum1)
  19441. + return 0;
  19442. +
  19443. + return 1;
  19444. +}
  19445. +
  19446. +static int yaffs2_wr_checkpt_data(struct yaffs_dev *dev)
  19447. +{
  19448. + int ok = 1;
  19449. +
  19450. + if (!yaffs2_checkpt_required(dev)) {
  19451. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19452. + "skipping checkpoint write");
  19453. + ok = 0;
  19454. + }
  19455. +
  19456. + if (ok)
  19457. + ok = yaffs2_checkpt_open(dev, 1);
  19458. +
  19459. + if (ok) {
  19460. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19461. + "write checkpoint validity");
  19462. + ok = yaffs2_wr_checkpt_validity_marker(dev, 1);
  19463. + }
  19464. + if (ok) {
  19465. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19466. + "write checkpoint device");
  19467. + ok = yaffs2_wr_checkpt_dev(dev);
  19468. + }
  19469. + if (ok) {
  19470. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19471. + "write checkpoint objects");
  19472. + ok = yaffs2_wr_checkpt_objs(dev);
  19473. + }
  19474. + if (ok) {
  19475. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19476. + "write checkpoint validity");
  19477. + ok = yaffs2_wr_checkpt_validity_marker(dev, 0);
  19478. + }
  19479. +
  19480. + if (ok)
  19481. + ok = yaffs2_wr_checkpt_sum(dev);
  19482. +
  19483. + if (!yaffs_checkpt_close(dev))
  19484. + ok = 0;
  19485. +
  19486. + if (ok)
  19487. + dev->is_checkpointed = 1;
  19488. + else
  19489. + dev->is_checkpointed = 0;
  19490. +
  19491. + return dev->is_checkpointed;
  19492. +}
  19493. +
  19494. +static int yaffs2_rd_checkpt_data(struct yaffs_dev *dev)
  19495. +{
  19496. + int ok = 1;
  19497. +
  19498. + if (!dev->param.is_yaffs2)
  19499. + ok = 0;
  19500. +
  19501. + if (ok && dev->param.skip_checkpt_rd) {
  19502. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19503. + "skipping checkpoint read");
  19504. + ok = 0;
  19505. + }
  19506. +
  19507. + if (ok)
  19508. + ok = yaffs2_checkpt_open(dev, 0); /* open for read */
  19509. +
  19510. + if (ok) {
  19511. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19512. + "read checkpoint validity");
  19513. + ok = yaffs2_rd_checkpt_validity_marker(dev, 1);
  19514. + }
  19515. + if (ok) {
  19516. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19517. + "read checkpoint device");
  19518. + ok = yaffs2_rd_checkpt_dev(dev);
  19519. + }
  19520. + if (ok) {
  19521. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19522. + "read checkpoint objects");
  19523. + ok = yaffs2_rd_checkpt_objs(dev);
  19524. + }
  19525. + if (ok) {
  19526. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19527. + "read checkpoint validity");
  19528. + ok = yaffs2_rd_checkpt_validity_marker(dev, 0);
  19529. + }
  19530. +
  19531. + if (ok) {
  19532. + ok = yaffs2_rd_checkpt_sum(dev);
  19533. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19534. + "read checkpoint checksum %d", ok);
  19535. + }
  19536. +
  19537. + if (!yaffs_checkpt_close(dev))
  19538. + ok = 0;
  19539. +
  19540. + if (ok)
  19541. + dev->is_checkpointed = 1;
  19542. + else
  19543. + dev->is_checkpointed = 0;
  19544. +
  19545. + return ok ? 1 : 0;
  19546. +}
  19547. +
  19548. +void yaffs2_checkpt_invalidate(struct yaffs_dev *dev)
  19549. +{
  19550. + if (dev->is_checkpointed || dev->blocks_in_checkpt > 0) {
  19551. + dev->is_checkpointed = 0;
  19552. + yaffs2_checkpt_invalidate_stream(dev);
  19553. + }
  19554. + if (dev->param.sb_dirty_fn)
  19555. + dev->param.sb_dirty_fn(dev);
  19556. +}
  19557. +
  19558. +int yaffs_checkpoint_save(struct yaffs_dev *dev)
  19559. +{
  19560. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19561. + "save entry: is_checkpointed %d",
  19562. + dev->is_checkpointed);
  19563. +
  19564. + yaffs_verify_objects(dev);
  19565. + yaffs_verify_blocks(dev);
  19566. + yaffs_verify_free_chunks(dev);
  19567. +
  19568. + if (!dev->is_checkpointed) {
  19569. + yaffs2_checkpt_invalidate(dev);
  19570. + yaffs2_wr_checkpt_data(dev);
  19571. + }
  19572. +
  19573. + yaffs_trace(YAFFS_TRACE_CHECKPOINT | YAFFS_TRACE_MOUNT,
  19574. + "save exit: is_checkpointed %d",
  19575. + dev->is_checkpointed);
  19576. +
  19577. + return dev->is_checkpointed;
  19578. +}
  19579. +
  19580. +int yaffs2_checkpt_restore(struct yaffs_dev *dev)
  19581. +{
  19582. + int retval;
  19583. +
  19584. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19585. + "restore entry: is_checkpointed %d",
  19586. + dev->is_checkpointed);
  19587. +
  19588. + retval = yaffs2_rd_checkpt_data(dev);
  19589. +
  19590. + if (dev->is_checkpointed) {
  19591. + yaffs_verify_objects(dev);
  19592. + yaffs_verify_blocks(dev);
  19593. + yaffs_verify_free_chunks(dev);
  19594. + }
  19595. +
  19596. + yaffs_trace(YAFFS_TRACE_CHECKPOINT,
  19597. + "restore exit: is_checkpointed %d",
  19598. + dev->is_checkpointed);
  19599. +
  19600. + return retval;
  19601. +}
  19602. +
  19603. +int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size)
  19604. +{
  19605. + /* if new_size > old_file_size.
  19606. + * We're going to be writing a hole.
  19607. + * If the hole is small then write zeros otherwise write a start
  19608. + * of hole marker.
  19609. + */
  19610. + loff_t old_file_size;
  19611. + loff_t increase;
  19612. + int small_hole;
  19613. + int result = YAFFS_OK;
  19614. + struct yaffs_dev *dev = NULL;
  19615. + u8 *local_buffer = NULL;
  19616. + int small_increase_ok = 0;
  19617. +
  19618. + if (!obj)
  19619. + return YAFFS_FAIL;
  19620. +
  19621. + if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
  19622. + return YAFFS_FAIL;
  19623. +
  19624. + dev = obj->my_dev;
  19625. +
  19626. + /* Bail out if not yaffs2 mode */
  19627. + if (!dev->param.is_yaffs2)
  19628. + return YAFFS_OK;
  19629. +
  19630. + old_file_size = obj->variant.file_variant.file_size;
  19631. +
  19632. + if (new_size <= old_file_size)
  19633. + return YAFFS_OK;
  19634. +
  19635. + increase = new_size - old_file_size;
  19636. +
  19637. + if (increase < YAFFS_SMALL_HOLE_THRESHOLD * dev->data_bytes_per_chunk &&
  19638. + yaffs_check_alloc_available(dev, YAFFS_SMALL_HOLE_THRESHOLD + 1))
  19639. + small_hole = 1;
  19640. + else
  19641. + small_hole = 0;
  19642. +
  19643. + if (small_hole)
  19644. + local_buffer = yaffs_get_temp_buffer(dev);
  19645. +
  19646. + if (local_buffer) {
  19647. + /* fill hole with zero bytes */
  19648. + loff_t pos = old_file_size;
  19649. + int this_write;
  19650. + int written;
  19651. + memset(local_buffer, 0, dev->data_bytes_per_chunk);
  19652. + small_increase_ok = 1;
  19653. +
  19654. + while (increase > 0 && small_increase_ok) {
  19655. + this_write = increase;
  19656. + if (this_write > dev->data_bytes_per_chunk)
  19657. + this_write = dev->data_bytes_per_chunk;
  19658. + written =
  19659. + yaffs_do_file_wr(obj, local_buffer, pos, this_write,
  19660. + 0);
  19661. + if (written == this_write) {
  19662. + pos += this_write;
  19663. + increase -= this_write;
  19664. + } else {
  19665. + small_increase_ok = 0;
  19666. + }
  19667. + }
  19668. +
  19669. + yaffs_release_temp_buffer(dev, local_buffer);
  19670. +
  19671. + /* If out of space then reverse any chunks we've added */
  19672. + if (!small_increase_ok)
  19673. + yaffs_resize_file_down(obj, old_file_size);
  19674. + }
  19675. +
  19676. + if (!small_increase_ok &&
  19677. + obj->parent &&
  19678. + obj->parent->obj_id != YAFFS_OBJECTID_UNLINKED &&
  19679. + obj->parent->obj_id != YAFFS_OBJECTID_DELETED) {
  19680. + /* Write a hole start header with the old file size */
  19681. + yaffs_update_oh(obj, NULL, 0, 1, 0, NULL);
  19682. + }
  19683. +
  19684. + return result;
  19685. +}
  19686. +
  19687. +struct yaffs_block_index {
  19688. + int seq;
  19689. + int block;
  19690. +};
  19691. +
  19692. +static int yaffs2_ybicmp(const void *a, const void *b)
  19693. +{
  19694. + int aseq = ((struct yaffs_block_index *)a)->seq;
  19695. + int bseq = ((struct yaffs_block_index *)b)->seq;
  19696. + int ablock = ((struct yaffs_block_index *)a)->block;
  19697. + int bblock = ((struct yaffs_block_index *)b)->block;
  19698. +
  19699. + if (aseq == bseq)
  19700. + return ablock - bblock;
  19701. +
  19702. + return aseq - bseq;
  19703. +}
  19704. +
  19705. +static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
  19706. + struct yaffs_block_info *bi,
  19707. + int blk, int chunk_in_block,
  19708. + int *found_chunks,
  19709. + u8 *chunk_data,
  19710. + struct list_head *hard_list,
  19711. + int summary_available)
  19712. +{
  19713. + struct yaffs_obj_hdr *oh;
  19714. + struct yaffs_obj *in;
  19715. + struct yaffs_obj *parent;
  19716. + int equiv_id;
  19717. + loff_t file_size;
  19718. + int is_shrink;
  19719. + int is_unlinked;
  19720. + struct yaffs_ext_tags tags;
  19721. + int result;
  19722. + int alloc_failed = 0;
  19723. + int chunk = blk * dev->param.chunks_per_block + chunk_in_block;
  19724. + struct yaffs_file_var *file_var;
  19725. + struct yaffs_hardlink_var *hl_var;
  19726. + struct yaffs_symlink_var *sl_var;
  19727. +
  19728. + if (summary_available) {
  19729. + result = yaffs_summary_fetch(dev, &tags, chunk_in_block);
  19730. + tags.seq_number = bi->seq_number;
  19731. + }
  19732. +
  19733. + if (!summary_available || tags.obj_id == 0) {
  19734. + result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
  19735. + dev->tags_used++;
  19736. + } else {
  19737. + dev->summary_used++;
  19738. + }
  19739. +
  19740. + /* Let's have a good look at this chunk... */
  19741. +
  19742. + if (!tags.chunk_used) {
  19743. + /* An unassigned chunk in the block.
  19744. + * If there are used chunks after this one, then
  19745. + * it is a chunk that was skipped due to failing
  19746. + * the erased check. Just skip it so that it can
  19747. + * be deleted.
  19748. + * But, more typically, We get here when this is
  19749. + * an unallocated chunk and his means that
  19750. + * either the block is empty or this is the one
  19751. + * being allocated from
  19752. + */
  19753. +
  19754. + if (*found_chunks) {
  19755. + /* This is a chunk that was skipped due
  19756. + * to failing the erased check */
  19757. + } else if (chunk_in_block == 0) {
  19758. + /* We're looking at the first chunk in
  19759. + * the block so the block is unused */
  19760. + bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
  19761. + dev->n_erased_blocks++;
  19762. + } else {
  19763. + if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
  19764. + bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) {
  19765. + if (dev->seq_number == bi->seq_number) {
  19766. + /* Allocating from this block*/
  19767. + yaffs_trace(YAFFS_TRACE_SCAN,
  19768. + " Allocating from %d %d",
  19769. + blk, chunk_in_block);
  19770. +
  19771. + bi->block_state =
  19772. + YAFFS_BLOCK_STATE_ALLOCATING;
  19773. + dev->alloc_block = blk;
  19774. + dev->alloc_page = chunk_in_block;
  19775. + dev->alloc_block_finder = blk;
  19776. + } else {
  19777. + /* This is a partially written block
  19778. + * that is not the current
  19779. + * allocation block.
  19780. + */
  19781. + yaffs_trace(YAFFS_TRACE_SCAN,
  19782. + "Partially written block %d detected. gc will fix this.",
  19783. + blk);
  19784. + }
  19785. + }
  19786. + }
  19787. +
  19788. + dev->n_free_chunks++;
  19789. +
  19790. + } else if (tags.ecc_result ==
  19791. + YAFFS_ECC_RESULT_UNFIXED) {
  19792. + yaffs_trace(YAFFS_TRACE_SCAN,
  19793. + " Unfixed ECC in chunk(%d:%d), chunk ignored",
  19794. + blk, chunk_in_block);
  19795. + dev->n_free_chunks++;
  19796. + } else if (tags.obj_id > YAFFS_MAX_OBJECT_ID ||
  19797. + tags.chunk_id > YAFFS_MAX_CHUNK_ID ||
  19798. + tags.obj_id == YAFFS_OBJECTID_SUMMARY ||
  19799. + (tags.chunk_id > 0 &&
  19800. + tags.n_bytes > dev->data_bytes_per_chunk) ||
  19801. + tags.seq_number != bi->seq_number) {
  19802. + yaffs_trace(YAFFS_TRACE_SCAN,
  19803. + "Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored",
  19804. + blk, chunk_in_block, tags.obj_id,
  19805. + tags.chunk_id, tags.n_bytes);
  19806. + dev->n_free_chunks++;
  19807. + } else if (tags.chunk_id > 0) {
  19808. + /* chunk_id > 0 so it is a data chunk... */
  19809. + loff_t endpos;
  19810. + loff_t chunk_base = (tags.chunk_id - 1) *
  19811. + dev->data_bytes_per_chunk;
  19812. +
  19813. + *found_chunks = 1;
  19814. +
  19815. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  19816. + bi->pages_in_use++;
  19817. +
  19818. + in = yaffs_find_or_create_by_number(dev,
  19819. + tags.obj_id,
  19820. + YAFFS_OBJECT_TYPE_FILE);
  19821. + if (!in)
  19822. + /* Out of memory */
  19823. + alloc_failed = 1;
  19824. +
  19825. + if (in &&
  19826. + in->variant_type == YAFFS_OBJECT_TYPE_FILE &&
  19827. + chunk_base < in->variant.file_variant.shrink_size) {
  19828. + /* This has not been invalidated by
  19829. + * a resize */
  19830. + if (!yaffs_put_chunk_in_file(in, tags.chunk_id,
  19831. + chunk, -1))
  19832. + alloc_failed = 1;
  19833. +
  19834. + /* File size is calculated by looking at
  19835. + * the data chunks if we have not
  19836. + * seen an object header yet.
  19837. + * Stop this practice once we find an
  19838. + * object header.
  19839. + */
  19840. + endpos = chunk_base + tags.n_bytes;
  19841. +
  19842. + if (!in->valid &&
  19843. + in->variant.file_variant.scanned_size < endpos) {
  19844. + in->variant.file_variant.
  19845. + scanned_size = endpos;
  19846. + in->variant.file_variant.
  19847. + file_size = endpos;
  19848. + }
  19849. + } else if (in) {
  19850. + /* This chunk has been invalidated by a
  19851. + * resize, or a past file deletion
  19852. + * so delete the chunk*/
  19853. + yaffs_chunk_del(dev, chunk, 1, __LINE__);
  19854. + }
  19855. + } else {
  19856. + /* chunk_id == 0, so it is an ObjectHeader.
  19857. + * Thus, we read in the object header and make
  19858. + * the object
  19859. + */
  19860. + *found_chunks = 1;
  19861. +
  19862. + yaffs_set_chunk_bit(dev, blk, chunk_in_block);
  19863. + bi->pages_in_use++;
  19864. +
  19865. + oh = NULL;
  19866. + in = NULL;
  19867. +
  19868. + if (tags.extra_available) {
  19869. + in = yaffs_find_or_create_by_number(dev,
  19870. + tags.obj_id,
  19871. + tags.extra_obj_type);
  19872. + if (!in)
  19873. + alloc_failed = 1;
  19874. + }
  19875. +
  19876. + if (!in ||
  19877. + (!in->valid && dev->param.disable_lazy_load) ||
  19878. + tags.extra_shadows ||
  19879. + (!in->valid && (tags.obj_id == YAFFS_OBJECTID_ROOT ||
  19880. + tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND))) {
  19881. +
  19882. + /* If we don't have valid info then we
  19883. + * need to read the chunk
  19884. + * TODO In future we can probably defer
  19885. + * reading the chunk and living with
  19886. + * invalid data until needed.
  19887. + */
  19888. +
  19889. + result = yaffs_rd_chunk_tags_nand(dev,
  19890. + chunk,
  19891. + chunk_data,
  19892. + NULL);
  19893. +
  19894. + oh = (struct yaffs_obj_hdr *)chunk_data;
  19895. +
  19896. + if (dev->param.inband_tags) {
  19897. + /* Fix up the header if they got
  19898. + * corrupted by inband tags */
  19899. + oh->shadows_obj =
  19900. + oh->inband_shadowed_obj_id;
  19901. + oh->is_shrink =
  19902. + oh->inband_is_shrink;
  19903. + }
  19904. +
  19905. + if (!in) {
  19906. + in = yaffs_find_or_create_by_number(dev,
  19907. + tags.obj_id, oh->type);
  19908. + if (!in)
  19909. + alloc_failed = 1;
  19910. + }
  19911. + }
  19912. +
  19913. + if (!in) {
  19914. + /* TODO Hoosterman we have a problem! */
  19915. + yaffs_trace(YAFFS_TRACE_ERROR,
  19916. + "yaffs tragedy: Could not make object for object %d at chunk %d during scan",
  19917. + tags.obj_id, chunk);
  19918. + return YAFFS_FAIL;
  19919. + }
  19920. +
  19921. + if (in->valid) {
  19922. + /* We have already filled this one.
  19923. + * We have a duplicate that will be
  19924. + * discarded, but we first have to suck
  19925. + * out resize info if it is a file.
  19926. + */
  19927. + if ((in->variant_type == YAFFS_OBJECT_TYPE_FILE) &&
  19928. + ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) ||
  19929. + (tags.extra_available &&
  19930. + tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
  19931. + )) {
  19932. + loff_t this_size = (oh) ?
  19933. + yaffs_oh_to_size(oh) :
  19934. + tags.extra_file_size;
  19935. + u32 parent_obj_id = (oh) ?
  19936. + oh->parent_obj_id :
  19937. + tags.extra_parent_id;
  19938. +
  19939. + is_shrink = (oh) ?
  19940. + oh->is_shrink :
  19941. + tags.extra_is_shrink;
  19942. +
  19943. + /* If it is deleted (unlinked
  19944. + * at start also means deleted)
  19945. + * we treat the file size as
  19946. + * being zeroed at this point.
  19947. + */
  19948. + if (parent_obj_id == YAFFS_OBJECTID_DELETED ||
  19949. + parent_obj_id == YAFFS_OBJECTID_UNLINKED) {
  19950. + this_size = 0;
  19951. + is_shrink = 1;
  19952. + }
  19953. +
  19954. + if (is_shrink &&
  19955. + in->variant.file_variant.shrink_size >
  19956. + this_size)
  19957. + in->variant.file_variant.shrink_size =
  19958. + this_size;
  19959. +
  19960. + if (is_shrink)
  19961. + bi->has_shrink_hdr = 1;
  19962. + }
  19963. + /* Use existing - destroy this one. */
  19964. + yaffs_chunk_del(dev, chunk, 1, __LINE__);
  19965. + }
  19966. +
  19967. + if (!in->valid && in->variant_type !=
  19968. + (oh ? oh->type : tags.extra_obj_type)) {
  19969. + yaffs_trace(YAFFS_TRACE_ERROR,
  19970. + "yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan",
  19971. + oh ? oh->type : tags.extra_obj_type,
  19972. + in->variant_type, tags.obj_id,
  19973. + chunk);
  19974. + in = yaffs_retype_obj(in, oh ? oh->type : tags.extra_obj_type);
  19975. + }
  19976. +
  19977. + if (!in->valid &&
  19978. + (tags.obj_id == YAFFS_OBJECTID_ROOT ||
  19979. + tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND)) {
  19980. + /* We only load some info, don't fiddle
  19981. + * with directory structure */
  19982. + in->valid = 1;
  19983. +
  19984. + if (oh) {
  19985. + in->yst_mode = oh->yst_mode;
  19986. + yaffs_load_attribs(in, oh);
  19987. + in->lazy_loaded = 0;
  19988. + } else {
  19989. + in->lazy_loaded = 1;
  19990. + }
  19991. + in->hdr_chunk = chunk;
  19992. +
  19993. + } else if (!in->valid) {
  19994. + /* we need to load this info */
  19995. + in->valid = 1;
  19996. + in->hdr_chunk = chunk;
  19997. + if (oh) {
  19998. + in->variant_type = oh->type;
  19999. + in->yst_mode = oh->yst_mode;
  20000. + yaffs_load_attribs(in, oh);
  20001. +
  20002. + if (oh->shadows_obj > 0)
  20003. + yaffs_handle_shadowed_obj(dev,
  20004. + oh->shadows_obj, 1);
  20005. +
  20006. + yaffs_set_obj_name_from_oh(in, oh);
  20007. + parent = yaffs_find_or_create_by_number(dev,
  20008. + oh->parent_obj_id,
  20009. + YAFFS_OBJECT_TYPE_DIRECTORY);
  20010. + file_size = yaffs_oh_to_size(oh);
  20011. + is_shrink = oh->is_shrink;
  20012. + equiv_id = oh->equiv_id;
  20013. + } else {
  20014. + in->variant_type = tags.extra_obj_type;
  20015. + parent = yaffs_find_or_create_by_number(dev,
  20016. + tags.extra_parent_id,
  20017. + YAFFS_OBJECT_TYPE_DIRECTORY);
  20018. + file_size = tags.extra_file_size;
  20019. + is_shrink = tags.extra_is_shrink;
  20020. + equiv_id = tags.extra_equiv_id;
  20021. + in->lazy_loaded = 1;
  20022. + }
  20023. + in->dirty = 0;
  20024. +
  20025. + if (!parent)
  20026. + alloc_failed = 1;
  20027. +
  20028. + /* directory stuff...
  20029. + * hook up to parent
  20030. + */
  20031. +
  20032. + if (parent &&
  20033. + parent->variant_type == YAFFS_OBJECT_TYPE_UNKNOWN) {
  20034. + /* Set up as a directory */
  20035. + parent->variant_type =
  20036. + YAFFS_OBJECT_TYPE_DIRECTORY;
  20037. + INIT_LIST_HEAD(&parent->
  20038. + variant.dir_variant.children);
  20039. + } else if (!parent ||
  20040. + parent->variant_type !=
  20041. + YAFFS_OBJECT_TYPE_DIRECTORY) {
  20042. + /* Hoosterman, another problem....
  20043. + * Trying to use a non-directory as a directory
  20044. + */
  20045. +
  20046. + yaffs_trace(YAFFS_TRACE_ERROR,
  20047. + "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
  20048. + );
  20049. + parent = dev->lost_n_found;
  20050. + }
  20051. + yaffs_add_obj_to_dir(parent, in);
  20052. +
  20053. + is_unlinked = (parent == dev->del_dir) ||
  20054. + (parent == dev->unlinked_dir);
  20055. +
  20056. + if (is_shrink)
  20057. + /* Mark the block */
  20058. + bi->has_shrink_hdr = 1;
  20059. +
  20060. + /* Note re hardlinks.
  20061. + * Since we might scan a hardlink before its equivalent
  20062. + * object is scanned we put them all in a list.
  20063. + * After scanning is complete, we should have all the
  20064. + * objects, so we run through this list and fix up all
  20065. + * the chains.
  20066. + */
  20067. +
  20068. + switch (in->variant_type) {
  20069. + case YAFFS_OBJECT_TYPE_UNKNOWN:
  20070. + /* Todo got a problem */
  20071. + break;
  20072. + case YAFFS_OBJECT_TYPE_FILE:
  20073. + file_var = &in->variant.file_variant;
  20074. + if (file_var->scanned_size < file_size) {
  20075. + /* This covers the case where the file
  20076. + * size is greater than the data held.
  20077. + * This will happen if the file is
  20078. + * resized to be larger than its
  20079. + * current data extents.
  20080. + */
  20081. + file_var->file_size = file_size;
  20082. + file_var->scanned_size = file_size;
  20083. + }
  20084. +
  20085. + if (file_var->shrink_size > file_size)
  20086. + file_var->shrink_size = file_size;
  20087. +
  20088. + break;
  20089. + case YAFFS_OBJECT_TYPE_HARDLINK:
  20090. + hl_var = &in->variant.hardlink_variant;
  20091. + if (!is_unlinked) {
  20092. + hl_var->equiv_id = equiv_id;
  20093. + list_add(&in->hard_links, hard_list);
  20094. + }
  20095. + break;
  20096. + case YAFFS_OBJECT_TYPE_DIRECTORY:
  20097. + /* Do nothing */
  20098. + break;
  20099. + case YAFFS_OBJECT_TYPE_SPECIAL:
  20100. + /* Do nothing */
  20101. + break;
  20102. + case YAFFS_OBJECT_TYPE_SYMLINK:
  20103. + sl_var = &in->variant.symlink_variant;
  20104. + if (oh) {
  20105. + sl_var->alias =
  20106. + yaffs_clone_str(oh->alias);
  20107. + if (!sl_var->alias)
  20108. + alloc_failed = 1;
  20109. + }
  20110. + break;
  20111. + }
  20112. + }
  20113. + }
  20114. + return alloc_failed ? YAFFS_FAIL : YAFFS_OK;
  20115. +}
  20116. +
  20117. +int yaffs2_scan_backwards(struct yaffs_dev *dev)
  20118. +{
  20119. + int blk;
  20120. + int block_iter;
  20121. + int start_iter;
  20122. + int end_iter;
  20123. + int n_to_scan = 0;
  20124. + enum yaffs_block_state state;
  20125. + int c;
  20126. + int deleted;
  20127. + LIST_HEAD(hard_list);
  20128. + struct yaffs_block_info *bi;
  20129. + u32 seq_number;
  20130. + int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
  20131. + u8 *chunk_data;
  20132. + int found_chunks;
  20133. + int alloc_failed = 0;
  20134. + struct yaffs_block_index *block_index = NULL;
  20135. + int alt_block_index = 0;
  20136. + int summary_available;
  20137. +
  20138. + yaffs_trace(YAFFS_TRACE_SCAN,
  20139. + "yaffs2_scan_backwards starts intstartblk %d intendblk %d...",
  20140. + dev->internal_start_block, dev->internal_end_block);
  20141. +
  20142. + dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
  20143. +
  20144. + block_index =
  20145. + kmalloc(n_blocks * sizeof(struct yaffs_block_index), GFP_NOFS);
  20146. +
  20147. + if (!block_index) {
  20148. + block_index =
  20149. + vmalloc(n_blocks * sizeof(struct yaffs_block_index));
  20150. + alt_block_index = 1;
  20151. + }
  20152. +
  20153. + if (!block_index) {
  20154. + yaffs_trace(YAFFS_TRACE_SCAN,
  20155. + "yaffs2_scan_backwards() could not allocate block index!"
  20156. + );
  20157. + return YAFFS_FAIL;
  20158. + }
  20159. +
  20160. + dev->blocks_in_checkpt = 0;
  20161. +
  20162. + chunk_data = yaffs_get_temp_buffer(dev);
  20163. +
  20164. + /* Scan all the blocks to determine their state */
  20165. + bi = dev->block_info;
  20166. + for (blk = dev->internal_start_block; blk <= dev->internal_end_block;
  20167. + blk++) {
  20168. + yaffs_clear_chunk_bits(dev, blk);
  20169. + bi->pages_in_use = 0;
  20170. + bi->soft_del_pages = 0;
  20171. +
  20172. + yaffs_query_init_block_state(dev, blk, &state, &seq_number);
  20173. +
  20174. + bi->block_state = state;
  20175. + bi->seq_number = seq_number;
  20176. +
  20177. + if (bi->seq_number == YAFFS_SEQUENCE_CHECKPOINT_DATA)
  20178. + bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
  20179. + if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK)
  20180. + bi->block_state = YAFFS_BLOCK_STATE_DEAD;
  20181. +
  20182. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG,
  20183. + "Block scanning block %d state %d seq %d",
  20184. + blk, bi->block_state, seq_number);
  20185. +
  20186. + if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) {
  20187. + dev->blocks_in_checkpt++;
  20188. +
  20189. + } else if (bi->block_state == YAFFS_BLOCK_STATE_DEAD) {
  20190. + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
  20191. + "block %d is bad", blk);
  20192. + } else if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
  20193. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty ");
  20194. + dev->n_erased_blocks++;
  20195. + dev->n_free_chunks += dev->param.chunks_per_block;
  20196. + } else if (bi->block_state ==
  20197. + YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  20198. + /* Determine the highest sequence number */
  20199. + if (seq_number >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
  20200. + seq_number < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
  20201. + block_index[n_to_scan].seq = seq_number;
  20202. + block_index[n_to_scan].block = blk;
  20203. + n_to_scan++;
  20204. + if (seq_number >= dev->seq_number)
  20205. + dev->seq_number = seq_number;
  20206. + } else {
  20207. + /* TODO: Nasty sequence number! */
  20208. + yaffs_trace(YAFFS_TRACE_SCAN,
  20209. + "Block scanning block %d has bad sequence number %d",
  20210. + blk, seq_number);
  20211. + }
  20212. + }
  20213. + bi++;
  20214. + }
  20215. +
  20216. + yaffs_trace(YAFFS_TRACE_ALWAYS, "%d blocks to be sorted...", n_to_scan);
  20217. +
  20218. + cond_resched();
  20219. +
  20220. + /* Sort the blocks by sequence number */
  20221. + sort(block_index, n_to_scan, sizeof(struct yaffs_block_index),
  20222. + yaffs2_ybicmp, NULL);
  20223. +
  20224. + cond_resched();
  20225. +
  20226. + yaffs_trace(YAFFS_TRACE_SCAN, "...done");
  20227. +
  20228. + /* Now scan the blocks looking at the data. */
  20229. + start_iter = 0;
  20230. + end_iter = n_to_scan - 1;
  20231. + yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "%d blocks to scan", n_to_scan);
  20232. +
  20233. + /* For each block.... backwards */
  20234. + for (block_iter = end_iter;
  20235. + !alloc_failed && block_iter >= start_iter;
  20236. + block_iter--) {
  20237. + /* Cooperative multitasking! This loop can run for so
  20238. + long that watchdog timers expire. */
  20239. + cond_resched();
  20240. +
  20241. + /* get the block to scan in the correct order */
  20242. + blk = block_index[block_iter].block;
  20243. + bi = yaffs_get_block_info(dev, blk);
  20244. + deleted = 0;
  20245. +
  20246. + summary_available = yaffs_summary_read(dev, dev->sum_tags, blk);
  20247. +
  20248. + /* For each chunk in each block that needs scanning.... */
  20249. + found_chunks = 0;
  20250. + if (summary_available)
  20251. + c = dev->chunks_per_summary - 1;
  20252. + else
  20253. + c = dev->param.chunks_per_block - 1;
  20254. +
  20255. + for (/* c is already initialised */;
  20256. + !alloc_failed && c >= 0 &&
  20257. + (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
  20258. + bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING);
  20259. + c--) {
  20260. + /* Scan backwards...
  20261. + * Read the tags and decide what to do
  20262. + */
  20263. + if (yaffs2_scan_chunk(dev, bi, blk, c,
  20264. + &found_chunks, chunk_data,
  20265. + &hard_list, summary_available) ==
  20266. + YAFFS_FAIL)
  20267. + alloc_failed = 1;
  20268. + }
  20269. +
  20270. + if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN) {
  20271. + /* If we got this far while scanning, then the block
  20272. + * is fully allocated. */
  20273. + bi->block_state = YAFFS_BLOCK_STATE_FULL;
  20274. + }
  20275. +
  20276. + /* Now let's see if it was dirty */
  20277. + if (bi->pages_in_use == 0 &&
  20278. + !bi->has_shrink_hdr &&
  20279. + bi->block_state == YAFFS_BLOCK_STATE_FULL) {
  20280. + yaffs_block_became_dirty(dev, blk);
  20281. + }
  20282. + }
  20283. +
  20284. + yaffs_skip_rest_of_block(dev);
  20285. +
  20286. + if (alt_block_index)
  20287. + vfree(block_index);
  20288. + else
  20289. + kfree(block_index);
  20290. +
  20291. + /* Ok, we've done all the scanning.
  20292. + * Fix up the hard link chains.
  20293. + * We have scanned all the objects, now it's time to add these
  20294. + * hardlinks.
  20295. + */
  20296. + yaffs_link_fixup(dev, &hard_list);
  20297. +
  20298. + yaffs_release_temp_buffer(dev, chunk_data);
  20299. +
  20300. + if (alloc_failed)
  20301. + return YAFFS_FAIL;
  20302. +
  20303. + yaffs_trace(YAFFS_TRACE_SCAN, "yaffs2_scan_backwards ends");
  20304. +
  20305. + return YAFFS_OK;
  20306. +}
  20307. diff -Nur linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs2.h linux-3.14.4/fs/yaffs2/yaffs_yaffs2.h
  20308. --- linux-3.14.4.orig/fs/yaffs2/yaffs_yaffs2.h 1970-01-01 01:00:00.000000000 +0100
  20309. +++ linux-3.14.4/fs/yaffs2/yaffs_yaffs2.h 2014-05-14 12:41:24.012792539 +0200
  20310. @@ -0,0 +1,39 @@
  20311. +/*
  20312. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  20313. + *
  20314. + * Copyright (C) 2002-2011 Aleph One Ltd.
  20315. + * for Toby Churchill Ltd and Brightstar Engineering
  20316. + *
  20317. + * Created by Charles Manning <charles@aleph1.co.uk>
  20318. + *
  20319. + * This program is free software; you can redistribute it and/or modify
  20320. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  20321. + * published by the Free Software Foundation.
  20322. + *
  20323. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  20324. + */
  20325. +
  20326. +#ifndef __YAFFS_YAFFS2_H__
  20327. +#define __YAFFS_YAFFS2_H__
  20328. +
  20329. +#include "yaffs_guts.h"
  20330. +
  20331. +void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev);
  20332. +void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev);
  20333. +void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev,
  20334. + struct yaffs_block_info *bi);
  20335. +void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no,
  20336. + struct yaffs_block_info *bi);
  20337. +int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi);
  20338. +u32 yaffs2_find_refresh_block(struct yaffs_dev *dev);
  20339. +int yaffs2_checkpt_required(struct yaffs_dev *dev);
  20340. +int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev);
  20341. +
  20342. +void yaffs2_checkpt_invalidate(struct yaffs_dev *dev);
  20343. +int yaffs2_checkpt_save(struct yaffs_dev *dev);
  20344. +int yaffs2_checkpt_restore(struct yaffs_dev *dev);
  20345. +
  20346. +int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size);
  20347. +int yaffs2_scan_backwards(struct yaffs_dev *dev);
  20348. +
  20349. +#endif
  20350. diff -Nur linux-3.14.4.orig/fs/yaffs2/yportenv.h linux-3.14.4/fs/yaffs2/yportenv.h
  20351. --- linux-3.14.4.orig/fs/yaffs2/yportenv.h 1970-01-01 01:00:00.000000000 +0100
  20352. +++ linux-3.14.4/fs/yaffs2/yportenv.h 2014-05-14 12:41:24.012792539 +0200
  20353. @@ -0,0 +1,85 @@
  20354. +/*
  20355. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
  20356. + *
  20357. + * Copyright (C) 2002-2011 Aleph One Ltd.
  20358. + * for Toby Churchill Ltd and Brightstar Engineering
  20359. + *
  20360. + * Created by Charles Manning <charles@aleph1.co.uk>
  20361. + *
  20362. + * This program is free software; you can redistribute it and/or modify
  20363. + * it under the terms of the GNU Lesser General Public License version 2.1 as
  20364. + * published by the Free Software Foundation.
  20365. + *
  20366. + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  20367. + */
  20368. +
  20369. +#ifndef __YPORTENV_H__
  20370. +#define __YPORTENV_H__
  20371. +
  20372. +/*
  20373. + * Define the MTD version in terms of Linux Kernel versions
  20374. + * This allows yaffs to be used independantly of the kernel
  20375. + * as well as with it.
  20376. + */
  20377. +
  20378. +#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
  20379. +
  20380. +#ifdef YAFFS_OUT_OF_TREE
  20381. +#include "moduleconfig.h"
  20382. +#endif
  20383. +
  20384. +#include <linux/version.h>
  20385. +#define MTD_VERSION_CODE LINUX_VERSION_CODE
  20386. +
  20387. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
  20388. +#include <linux/config.h>
  20389. +#endif
  20390. +#include <linux/version.h>
  20391. +#include <linux/kernel.h>
  20392. +#include <linux/mm.h>
  20393. +#include <linux/sched.h>
  20394. +#include <linux/string.h>
  20395. +#include <linux/slab.h>
  20396. +#include <linux/vmalloc.h>
  20397. +#include <linux/xattr.h>
  20398. +#include <linux/list.h>
  20399. +#include <linux/types.h>
  20400. +#include <linux/fs.h>
  20401. +#include <linux/stat.h>
  20402. +#include <linux/sort.h>
  20403. +#include <linux/bitops.h>
  20404. +
  20405. +/* These type wrappings are used to support Unicode names in WinCE. */
  20406. +#define YCHAR char
  20407. +#define YUCHAR unsigned char
  20408. +#define _Y(x) x
  20409. +
  20410. +#define YAFFS_LOSTNFOUND_NAME "lost+found"
  20411. +#define YAFFS_LOSTNFOUND_PREFIX "obj"
  20412. +
  20413. +
  20414. +#define YAFFS_ROOT_MODE 0755
  20415. +#define YAFFS_LOSTNFOUND_MODE 0700
  20416. +
  20417. +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
  20418. +#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
  20419. +#define Y_TIME_CONVERT(x) (x).tv_sec
  20420. +#else
  20421. +#define Y_CURRENT_TIME CURRENT_TIME
  20422. +#define Y_TIME_CONVERT(x) (x)
  20423. +#endif
  20424. +
  20425. +#define compile_time_assertion(assertion) \
  20426. + ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; })
  20427. +
  20428. +
  20429. +#define yaffs_printf(msk, fmt, ...) \
  20430. + printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__)
  20431. +
  20432. +#define yaffs_trace(msk, fmt, ...) do { \
  20433. + if (yaffs_trace_mask & (msk)) \
  20434. + printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__); \
  20435. +} while (0)
  20436. +
  20437. +
  20438. +#endif