linux-2.6.24: fix kernel oops upon driver unload for hipox machine
[openembedded.git] / recipes / linux / linux-2.6.24 / squashfs-lzma-2.6.24.patch
1 diff -urN linux-2.6.23/fs/Kconfig linux-2.6.23.sqlzma/fs/Kconfig\r
2 --- linux-2.6.23/fs/Kconfig     2007-10-09 16:31:38.000000000 -0400\r
3 +++ linux-2.6.23.sqlzma/fs/Kconfig      2007-10-14 13:19:21.000000000 -0400\r
4 @@ -1364,6 +1364,72 @@\r
5  \r
6           If unsure, say N.\r
7  \r
8 +config SQUASHFS\r
9 +       tristate "SquashFS 3.2 - Squashed file system support"\r
10 +       select ZLIB_INFLATE\r
11 +       help\r
12 +         Saying Y here includes support for SquashFS 3.2 (a Compressed Read-\r
13 +         Only File System).  Squashfs is a highly compressed read-only\r
14 +         filesystem for Linux.  It uses zlib and/or LZMA compression to compress\r
15 +         both files, inodes and directories.  Inodes in the system are very\r
16 +         small and all blocks are packed to minimise data overhead. Block sizes\r
17 +         greater than 4K are supported up to a maximum of 64K.  SquashFS 3.2\r
18 +         supports 64 bit filesystems and files (larger than 4GB), full uid/gid\r
19 +         information, hard links and timestamps.\r
20 +\r
21 +         Squashfs is intended for general read-only filesystem use, for archival\r
22 +         use (i.e. in cases where a .tar.gz file may be used), and in embedded\r
23 +         systems where low overhead is needed.  Further information and\r
24 +         filesystem tools are available from http://squashfs.sourceforge.net.\r
25 +\r
26 +         If you want to compile this as a module ( = code which can be\r
27 +         inserted in and removed from the running kernel whenever you want),\r
28 +         say M here and read <file:Documentation/modules.txt>.  The module\r
29 +         will be called squashfs.  Note that the root file system (the one\r
30 +         containing the directory /) cannot be compiled as a module.\r
31 +\r
32 +         If unsure, say N.\r
33 +\r
34 +config SQUASHFS_EMBEDDED\r
35 +\r
36 +       bool "Additional options for memory-constrained systems" \r
37 +       depends on SQUASHFS\r
38 +       default n\r
39 +       help\r
40 +         Saying Y here allows you to specify cache sizes and how Squashfs\r
41 +         allocates memory.  This is only intended for memory constrained\r
42 +         systems.\r
43 +\r
44 +         If unsure, say N.\r
45 +\r
46 +config SQUASHFS_FRAGMENT_CACHE_SIZE\r
47 +       int "Number of fragments cached" if SQUASHFS_EMBEDDED\r
48 +       depends on SQUASHFS\r
49 +       default "3"\r
50 +       help\r
51 +         By default SquashFS caches the last 3 fragments read from\r
52 +         the filesystem.  Increasing this amount may mean SquashFS\r
53 +         has to re-read fragments less often from disk, at the expense\r
54 +         of extra system memory.  Decreasing this amount will mean\r
55 +         SquashFS uses less memory at the expense of extra reads from disk.\r
56 +\r
57 +         Note there must be at least one cached fragment.  Anything\r
58 +         much more than three will probably not make much difference.\r
59 +\r
60 +config SQUASHFS_VMALLOC\r
61 +       bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED\r
62 +       depends on SQUASHFS\r
63 +       default n\r
64 +       help\r
65 +         By default SquashFS uses kmalloc to obtain fragment cache memory.\r
66 +         Kmalloc memory is the standard kernel allocator, but it can fail\r
67 +         on memory constrained systems.  Because of the way Vmalloc works,\r
68 +         Vmalloc can succeed when kmalloc fails.  Specifying this option\r
69 +         will make SquashFS always use Vmalloc to allocate the\r
70 +         fragment cache memory.\r
71 +\r
72 +         If unsure, say N.\r
73 +\r
74  config VXFS_FS\r
75         tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"\r
76         depends on BLOCK\r
77 diff -urN linux-2.6.23/fs/Makefile linux-2.6.23.sqlzma/fs/Makefile\r
78 --- linux-2.6.23/fs/Makefile    2007-10-09 16:31:38.000000000 -0400\r
79 +++ linux-2.6.23.sqlzma/fs/Makefile     2007-10-14 10:24:31.000000000 -0400\r
80 @@ -72,6 +72,7 @@\r
81  obj-$(CONFIG_JBD2)             += jbd2/\r
82  obj-$(CONFIG_EXT2_FS)          += ext2/\r
83  obj-$(CONFIG_CRAMFS)           += cramfs/\r
84 +obj-$(CONFIG_SQUASHFS)         += squashfs/\r
85  obj-y                          += ramfs/\r
86  obj-$(CONFIG_HUGETLBFS)                += hugetlbfs/\r
87  obj-$(CONFIG_CODA_FS)          += coda/\r
88 diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.c linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c\r
89 --- linux-2.6.23/fs/squashfs/LzmaDecode.c       1969-12-31 19:00:00.000000000 -0500\r
90 +++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.c        2007-10-14 12:44:42.000000000 -0400\r
91 @@ -0,0 +1,584 @@\r
92 +/*\r
93 +  LzmaDecode.c\r
94 +  LZMA Decoder (optimized for Speed version)\r
95 +  \r
96 +  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)\r
97 +  http://www.7-zip.org/\r
98 +\r
99 +  LZMA SDK is licensed under two licenses:\r
100 +  1) GNU Lesser General Public License (GNU LGPL)\r
101 +  2) Common Public License (CPL)\r
102 +  It means that you can select one of these two licenses and \r
103 +  follow rules of that license.\r
104 +\r
105 +  SPECIAL EXCEPTION:\r
106 +  Igor Pavlov, as the author of this Code, expressly permits you to \r
107 +  statically or dynamically link your Code (or bind by name) to the \r
108 +  interfaces of this file without subjecting your linked Code to the \r
109 +  terms of the CPL or GNU LGPL. Any modifications or additions \r
110 +  to this file, however, are subject to the LGPL or CPL terms.\r
111 +*/\r
112 +\r
113 +#include "LzmaDecode.h"\r
114 +\r
115 +#define kNumTopBits 24\r
116 +#define kTopValue ((UInt32)1 << kNumTopBits)\r
117 +\r
118 +#define kNumBitModelTotalBits 11\r
119 +#define kBitModelTotal (1 << kNumBitModelTotalBits)\r
120 +#define kNumMoveBits 5\r
121 +\r
122 +#define RC_READ_BYTE (*Buffer++)\r
123 +\r
124 +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \\r
125 +  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}\r
126 +\r
127 +#ifdef _LZMA_IN_CB\r
128 +\r
129 +#define RC_TEST { if (Buffer == BufferLim) \\r
130 +  { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \\r
131 +  BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}\r
132 +\r
133 +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2\r
134 +\r
135 +#else\r
136 +\r
137 +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }\r
138 +\r
139 +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2\r
140\r
141 +#endif\r
142 +\r
143 +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }\r
144 +\r
145 +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)\r
146 +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;\r
147 +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;\r
148 +\r
149 +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \\r
150 +  { UpdateBit0(p); mi <<= 1; A0; } else \\r
151 +  { UpdateBit1(p); mi = (mi + mi) + 1; A1; } \r
152 +  \r
153 +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               \r
154 +\r
155 +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \\r
156 +  { int i = numLevels; res = 1; \\r
157 +  do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \\r
158 +  res -= (1 << numLevels); }\r
159 +\r
160 +\r
161 +#define kNumPosBitsMax 4\r
162 +#define kNumPosStatesMax (1 << kNumPosBitsMax)\r
163 +\r
164 +#define kLenNumLowBits 3\r
165 +#define kLenNumLowSymbols (1 << kLenNumLowBits)\r
166 +#define kLenNumMidBits 3\r
167 +#define kLenNumMidSymbols (1 << kLenNumMidBits)\r
168 +#define kLenNumHighBits 8\r
169 +#define kLenNumHighSymbols (1 << kLenNumHighBits)\r
170 +\r
171 +#define LenChoice 0\r
172 +#define LenChoice2 (LenChoice + 1)\r
173 +#define LenLow (LenChoice2 + 1)\r
174 +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))\r
175 +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))\r
176 +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) \r
177 +\r
178 +\r
179 +#define kNumStates 12\r
180 +#define kNumLitStates 7\r
181 +\r
182 +#define kStartPosModelIndex 4\r
183 +#define kEndPosModelIndex 14\r
184 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r
185 +\r
186 +#define kNumPosSlotBits 6\r
187 +#define kNumLenToPosStates 4\r
188 +\r
189 +#define kNumAlignBits 4\r
190 +#define kAlignTableSize (1 << kNumAlignBits)\r
191 +\r
192 +#define kMatchMinLen 2\r
193 +\r
194 +#define IsMatch 0\r
195 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))\r
196 +#define IsRepG0 (IsRep + kNumStates)\r
197 +#define IsRepG1 (IsRepG0 + kNumStates)\r
198 +#define IsRepG2 (IsRepG1 + kNumStates)\r
199 +#define IsRep0Long (IsRepG2 + kNumStates)\r
200 +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))\r
201 +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\r
202 +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)\r
203 +#define LenCoder (Align + kAlignTableSize)\r
204 +#define RepLenCoder (LenCoder + kNumLenProbs)\r
205 +#define Literal (RepLenCoder + kNumLenProbs)\r
206 +\r
207 +#if Literal != LZMA_BASE_SIZE\r
208 +StopCompilingDueBUG\r
209 +#endif\r
210 +\r
211 +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)\r
212 +{\r
213 +  unsigned char prop0;\r
214 +  if (size < LZMA_PROPERTIES_SIZE)\r
215 +    return LZMA_RESULT_DATA_ERROR;\r
216 +  prop0 = propsData[0];\r
217 +  if (prop0 >= (9 * 5 * 5))\r
218 +    return LZMA_RESULT_DATA_ERROR;\r
219 +  {\r
220 +    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));\r
221 +    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);\r
222 +    propsRes->lc = prop0;\r
223 +    /*\r
224 +    unsigned char remainder = (unsigned char)(prop0 / 9);\r
225 +    propsRes->lc = prop0 % 9;\r
226 +    propsRes->pb = remainder / 5;\r
227 +    propsRes->lp = remainder % 5;\r
228 +    */\r
229 +  }\r
230 +\r
231 +  #ifdef _LZMA_OUT_READ\r
232 +  {\r
233 +    int i;\r
234 +    propsRes->DictionarySize = 0;\r
235 +    for (i = 0; i < 4; i++)\r
236 +      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);\r
237 +    if (propsRes->DictionarySize == 0)\r
238 +      propsRes->DictionarySize = 1;\r
239 +  }\r
240 +  #endif\r
241 +  return LZMA_RESULT_OK;\r
242 +}\r
243 +\r
244 +#define kLzmaStreamWasFinishedId (-1)\r
245 +\r
246 +int LzmaDecode(CLzmaDecoderState *vs,\r
247 +    #ifdef _LZMA_IN_CB\r
248 +    ILzmaInCallback *InCallback,\r
249 +    #else\r
250 +    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,\r
251 +    #endif\r
252 +    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)\r
253 +{\r
254 +  CProb *p = vs->Probs;\r
255 +  SizeT nowPos = 0;\r
256 +  Byte previousByte = 0;\r
257 +  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;\r
258 +  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;\r
259 +  int lc = vs->Properties.lc;\r
260 +\r
261 +  #ifdef _LZMA_OUT_READ\r
262 +  \r
263 +  UInt32 Range = vs->Range;\r
264 +  UInt32 Code = vs->Code;\r
265 +  #ifdef _LZMA_IN_CB\r
266 +  const Byte *Buffer = vs->Buffer;\r
267 +  const Byte *BufferLim = vs->BufferLim;\r
268 +  #else\r
269 +  const Byte *Buffer = inStream;\r
270 +  const Byte *BufferLim = inStream + inSize;\r
271 +  #endif\r
272 +  int state = vs->State;\r
273 +  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];\r
274 +  int len = vs->RemainLen;\r
275 +  UInt32 globalPos = vs->GlobalPos;\r
276 +  UInt32 distanceLimit = vs->DistanceLimit;\r
277 +\r
278 +  Byte *dictionary = vs->Dictionary;\r
279 +  UInt32 dictionarySize = vs->Properties.DictionarySize;\r
280 +  UInt32 dictionaryPos = vs->DictionaryPos;\r
281 +\r
282 +  Byte tempDictionary[4];\r
283 +\r
284 +  #ifndef _LZMA_IN_CB\r
285 +  *inSizeProcessed = 0;\r
286 +  #endif\r
287 +  *outSizeProcessed = 0;\r
288 +  if (len == kLzmaStreamWasFinishedId)\r
289 +    return LZMA_RESULT_OK;\r
290 +\r
291 +  if (dictionarySize == 0)\r
292 +  {\r
293 +    dictionary = tempDictionary;\r
294 +    dictionarySize = 1;\r
295 +    tempDictionary[0] = vs->TempDictionary[0];\r
296 +  }\r
297 +\r
298 +  if (len == kLzmaNeedInitId)\r
299 +  {\r
300 +    {\r
301 +      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));\r
302 +      UInt32 i;\r
303 +      for (i = 0; i < numProbs; i++)\r
304 +        p[i] = kBitModelTotal >> 1; \r
305 +      rep0 = rep1 = rep2 = rep3 = 1;\r
306 +      state = 0;\r
307 +      globalPos = 0;\r
308 +      distanceLimit = 0;\r
309 +      dictionaryPos = 0;\r
310 +      dictionary[dictionarySize - 1] = 0;\r
311 +      #ifdef _LZMA_IN_CB\r
312 +      RC_INIT;\r
313 +      #else\r
314 +      RC_INIT(inStream, inSize);\r
315 +      #endif\r
316 +    }\r
317 +    len = 0;\r
318 +  }\r
319 +  while(len != 0 && nowPos < outSize)\r
320 +  {\r
321 +    UInt32 pos = dictionaryPos - rep0;\r
322 +    if (pos >= dictionarySize)\r
323 +      pos += dictionarySize;\r
324 +    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];\r
325 +    if (++dictionaryPos == dictionarySize)\r
326 +      dictionaryPos = 0;\r
327 +    len--;\r
328 +  }\r
329 +  if (dictionaryPos == 0)\r
330 +    previousByte = dictionary[dictionarySize - 1];\r
331 +  else\r
332 +    previousByte = dictionary[dictionaryPos - 1];\r
333 +\r
334 +  #else /* if !_LZMA_OUT_READ */\r
335 +\r
336 +  int state = 0;\r
337 +  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;\r
338 +  int len = 0;\r
339 +  const Byte *Buffer;\r
340 +  const Byte *BufferLim;\r
341 +  UInt32 Range;\r
342 +  UInt32 Code;\r
343 +\r
344 +  #ifndef _LZMA_IN_CB\r
345 +  *inSizeProcessed = 0;\r
346 +  #endif\r
347 +  *outSizeProcessed = 0;\r
348 +\r
349 +  {\r
350 +    UInt32 i;\r
351 +    UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));\r
352 +    for (i = 0; i < numProbs; i++)\r
353 +      p[i] = kBitModelTotal >> 1;\r
354 +  }\r
355 +  \r
356 +  #ifdef _LZMA_IN_CB\r
357 +  RC_INIT;\r
358 +  #else\r
359 +  RC_INIT(inStream, inSize);\r
360 +  #endif\r
361 +\r
362 +  #endif /* _LZMA_OUT_READ */\r
363 +\r
364 +  while(nowPos < outSize)\r
365 +  {\r
366 +    CProb *prob;\r
367 +    UInt32 bound;\r
368 +    int posState = (int)(\r
369 +        (nowPos \r
370 +        #ifdef _LZMA_OUT_READ\r
371 +        + globalPos\r
372 +        #endif\r
373 +        )\r
374 +        & posStateMask);\r
375 +\r
376 +    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;\r
377 +    IfBit0(prob)\r
378 +    {\r
379 +      int symbol = 1;\r
380 +      UpdateBit0(prob)\r
381 +      prob = p + Literal + (LZMA_LIT_SIZE * \r
382 +        (((\r
383 +        (nowPos \r
384 +        #ifdef _LZMA_OUT_READ\r
385 +        + globalPos\r
386 +        #endif\r
387 +        )\r
388 +        & literalPosMask) << lc) + (previousByte >> (8 - lc))));\r
389 +\r
390 +      if (state >= kNumLitStates)\r
391 +      {\r
392 +        int matchByte;\r
393 +        #ifdef _LZMA_OUT_READ\r
394 +        UInt32 pos = dictionaryPos - rep0;\r
395 +        if (pos >= dictionarySize)\r
396 +          pos += dictionarySize;\r
397 +        matchByte = dictionary[pos];\r
398 +        #else\r
399 +        matchByte = outStream[nowPos - rep0];\r
400 +        #endif\r
401 +        do\r
402 +        {\r
403 +          int bit;\r
404 +          CProb *probLit;\r
405 +          matchByte <<= 1;\r
406 +          bit = (matchByte & 0x100);\r
407 +          probLit = prob + 0x100 + bit + symbol;\r
408 +          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)\r
409 +        }\r
410 +        while (symbol < 0x100);\r
411 +      }\r
412 +      while (symbol < 0x100)\r
413 +      {\r
414 +        CProb *probLit = prob + symbol;\r
415 +        RC_GET_BIT(probLit, symbol)\r
416 +      }\r
417 +      previousByte = (Byte)symbol;\r
418 +\r
419 +      outStream[nowPos++] = previousByte;\r
420 +      #ifdef _LZMA_OUT_READ\r
421 +      if (distanceLimit < dictionarySize)\r
422 +        distanceLimit++;\r
423 +\r
424 +      dictionary[dictionaryPos] = previousByte;\r
425 +      if (++dictionaryPos == dictionarySize)\r
426 +        dictionaryPos = 0;\r
427 +      #endif\r
428 +      if (state < 4) state = 0;\r
429 +      else if (state < 10) state -= 3;\r
430 +      else state -= 6;\r
431 +    }\r
432 +    else             \r
433 +    {\r
434 +      UpdateBit1(prob);\r
435 +      prob = p + IsRep + state;\r
436 +      IfBit0(prob)\r
437 +      {\r
438 +        UpdateBit0(prob);\r
439 +        rep3 = rep2;\r
440 +        rep2 = rep1;\r
441 +        rep1 = rep0;\r
442 +        state = state < kNumLitStates ? 0 : 3;\r
443 +        prob = p + LenCoder;\r
444 +      }\r
445 +      else\r
446 +      {\r
447 +        UpdateBit1(prob);\r
448 +        prob = p + IsRepG0 + state;\r
449 +        IfBit0(prob)\r
450 +        {\r
451 +          UpdateBit0(prob);\r
452 +          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;\r
453 +          IfBit0(prob)\r
454 +          {\r
455 +            #ifdef _LZMA_OUT_READ\r
456 +            UInt32 pos;\r
457 +            #endif\r
458 +            UpdateBit0(prob);\r
459 +            \r
460 +            #ifdef _LZMA_OUT_READ\r
461 +            if (distanceLimit == 0)\r
462 +            #else\r
463 +            if (nowPos == 0)\r
464 +            #endif\r
465 +              return LZMA_RESULT_DATA_ERROR;\r
466 +            \r
467 +            state = state < kNumLitStates ? 9 : 11;\r
468 +            #ifdef _LZMA_OUT_READ\r
469 +            pos = dictionaryPos - rep0;\r
470 +            if (pos >= dictionarySize)\r
471 +              pos += dictionarySize;\r
472 +            previousByte = dictionary[pos];\r
473 +            dictionary[dictionaryPos] = previousByte;\r
474 +            if (++dictionaryPos == dictionarySize)\r
475 +              dictionaryPos = 0;\r
476 +            #else\r
477 +            previousByte = outStream[nowPos - rep0];\r
478 +            #endif\r
479 +            outStream[nowPos++] = previousByte;\r
480 +            #ifdef _LZMA_OUT_READ\r
481 +            if (distanceLimit < dictionarySize)\r
482 +              distanceLimit++;\r
483 +            #endif\r
484 +\r
485 +            continue;\r
486 +          }\r
487 +          else\r
488 +          {\r
489 +            UpdateBit1(prob);\r
490 +          }\r
491 +        }\r
492 +        else\r
493 +        {\r
494 +          UInt32 distance;\r
495 +          UpdateBit1(prob);\r
496 +          prob = p + IsRepG1 + state;\r
497 +          IfBit0(prob)\r
498 +          {\r
499 +            UpdateBit0(prob);\r
500 +            distance = rep1;\r
501 +          }\r
502 +          else \r
503 +          {\r
504 +            UpdateBit1(prob);\r
505 +            prob = p + IsRepG2 + state;\r
506 +            IfBit0(prob)\r
507 +            {\r
508 +              UpdateBit0(prob);\r
509 +              distance = rep2;\r
510 +            }\r
511 +            else\r
512 +            {\r
513 +              UpdateBit1(prob);\r
514 +              distance = rep3;\r
515 +              rep3 = rep2;\r
516 +            }\r
517 +            rep2 = rep1;\r
518 +          }\r
519 +          rep1 = rep0;\r
520 +          rep0 = distance;\r
521 +        }\r
522 +        state = state < kNumLitStates ? 8 : 11;\r
523 +        prob = p + RepLenCoder;\r
524 +      }\r
525 +      {\r
526 +        int numBits, offset;\r
527 +        CProb *probLen = prob + LenChoice;\r
528 +        IfBit0(probLen)\r
529 +        {\r
530 +          UpdateBit0(probLen);\r
531 +          probLen = prob + LenLow + (posState << kLenNumLowBits);\r
532 +          offset = 0;\r
533 +          numBits = kLenNumLowBits;\r
534 +        }\r
535 +        else\r
536 +        {\r
537 +          UpdateBit1(probLen);\r
538 +          probLen = prob + LenChoice2;\r
539 +          IfBit0(probLen)\r
540 +          {\r
541 +            UpdateBit0(probLen);\r
542 +            probLen = prob + LenMid + (posState << kLenNumMidBits);\r
543 +            offset = kLenNumLowSymbols;\r
544 +            numBits = kLenNumMidBits;\r
545 +          }\r
546 +          else\r
547 +          {\r
548 +            UpdateBit1(probLen);\r
549 +            probLen = prob + LenHigh;\r
550 +            offset = kLenNumLowSymbols + kLenNumMidSymbols;\r
551 +            numBits = kLenNumHighBits;\r
552 +          }\r
553 +        }\r
554 +        RangeDecoderBitTreeDecode(probLen, numBits, len);\r
555 +        len += offset;\r
556 +      }\r
557 +\r
558 +      if (state < 4)\r
559 +      {\r
560 +        int posSlot;\r
561 +        state += kNumLitStates;\r
562 +        prob = p + PosSlot +\r
563 +            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << \r
564 +            kNumPosSlotBits);\r
565 +        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);\r
566 +        if (posSlot >= kStartPosModelIndex)\r
567 +        {\r
568 +          int numDirectBits = ((posSlot >> 1) - 1);\r
569 +          rep0 = (2 | ((UInt32)posSlot & 1));\r
570 +          if (posSlot < kEndPosModelIndex)\r
571 +          {\r
572 +            rep0 <<= numDirectBits;\r
573 +            prob = p + SpecPos + rep0 - posSlot - 1;\r
574 +          }\r
575 +          else\r
576 +          {\r
577 +            numDirectBits -= kNumAlignBits;\r
578 +            do\r
579 +            {\r
580 +              RC_NORMALIZE\r
581 +              Range >>= 1;\r
582 +              rep0 <<= 1;\r
583 +              if (Code >= Range)\r
584 +              {\r
585 +                Code -= Range;\r
586 +                rep0 |= 1;\r
587 +              }\r
588 +            }\r
589 +            while (--numDirectBits != 0);\r
590 +            prob = p + Align;\r
591 +            rep0 <<= kNumAlignBits;\r
592 +            numDirectBits = kNumAlignBits;\r
593 +          }\r
594 +          {\r
595 +            int i = 1;\r
596 +            int mi = 1;\r
597 +            do\r
598 +            {\r
599 +              CProb *prob3 = prob + mi;\r
600 +              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);\r
601 +              i <<= 1;\r
602 +            }\r
603 +            while(--numDirectBits != 0);\r
604 +          }\r
605 +        }\r
606 +        else\r
607 +          rep0 = posSlot;\r
608 +        if (++rep0 == (UInt32)(0))\r
609 +        {\r
610 +          /* it's for stream version */\r
611 +          len = kLzmaStreamWasFinishedId;\r
612 +          break;\r
613 +        }\r
614 +      }\r
615 +\r
616 +      len += kMatchMinLen;\r
617 +      #ifdef _LZMA_OUT_READ\r
618 +      if (rep0 > distanceLimit) \r
619 +      #else\r
620 +      if (rep0 > nowPos)\r
621 +      #endif\r
622 +        return LZMA_RESULT_DATA_ERROR;\r
623 +\r
624 +      #ifdef _LZMA_OUT_READ\r
625 +      if (dictionarySize - distanceLimit > (UInt32)len)\r
626 +        distanceLimit += len;\r
627 +      else\r
628 +        distanceLimit = dictionarySize;\r
629 +      #endif\r
630 +\r
631 +      do\r
632 +      {\r
633 +        #ifdef _LZMA_OUT_READ\r
634 +        UInt32 pos = dictionaryPos - rep0;\r
635 +        if (pos >= dictionarySize)\r
636 +          pos += dictionarySize;\r
637 +        previousByte = dictionary[pos];\r
638 +        dictionary[dictionaryPos] = previousByte;\r
639 +        if (++dictionaryPos == dictionarySize)\r
640 +          dictionaryPos = 0;\r
641 +        #else\r
642 +        previousByte = outStream[nowPos - rep0];\r
643 +        #endif\r
644 +        len--;\r
645 +        outStream[nowPos++] = previousByte;\r
646 +      }\r
647 +      while(len != 0 && nowPos < outSize);\r
648 +    }\r
649 +  }\r
650 +  RC_NORMALIZE;\r
651 +\r
652 +  #ifdef _LZMA_OUT_READ\r
653 +  vs->Range = Range;\r
654 +  vs->Code = Code;\r
655 +  vs->DictionaryPos = dictionaryPos;\r
656 +  vs->GlobalPos = globalPos + (UInt32)nowPos;\r
657 +  vs->DistanceLimit = distanceLimit;\r
658 +  vs->Reps[0] = rep0;\r
659 +  vs->Reps[1] = rep1;\r
660 +  vs->Reps[2] = rep2;\r
661 +  vs->Reps[3] = rep3;\r
662 +  vs->State = state;\r
663 +  vs->RemainLen = len;\r
664 +  vs->TempDictionary[0] = tempDictionary[0];\r
665 +  #endif\r
666 +\r
667 +  #ifdef _LZMA_IN_CB\r
668 +  vs->Buffer = Buffer;\r
669 +  vs->BufferLim = BufferLim;\r
670 +  #else\r
671 +  *inSizeProcessed = (SizeT)(Buffer - inStream);\r
672 +  #endif\r
673 +  *outSizeProcessed = nowPos;\r
674 +  return LZMA_RESULT_OK;\r
675 +}\r
676 diff -urN linux-2.6.23/fs/squashfs/LzmaDecode.h linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h\r
677 --- linux-2.6.23/fs/squashfs/LzmaDecode.h       1969-12-31 19:00:00.000000000 -0500\r
678 +++ linux-2.6.23.sqlzma/fs/squashfs/LzmaDecode.h        2007-10-14 12:44:42.000000000 -0400\r
679 @@ -0,0 +1,113 @@\r
680 +/* \r
681 +  LzmaDecode.h\r
682 +  LZMA Decoder interface\r
683 +\r
684 +  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)\r
685 +  http://www.7-zip.org/\r
686 +\r
687 +  LZMA SDK is licensed under two licenses:\r
688 +  1) GNU Lesser General Public License (GNU LGPL)\r
689 +  2) Common Public License (CPL)\r
690 +  It means that you can select one of these two licenses and \r
691 +  follow rules of that license.\r
692 +\r
693 +  SPECIAL EXCEPTION:\r
694 +  Igor Pavlov, as the author of this code, expressly permits you to \r
695 +  statically or dynamically link your code (or bind by name) to the \r
696 +  interfaces of this file without subjecting your linked code to the \r
697 +  terms of the CPL or GNU LGPL. Any modifications or additions \r
698 +  to this file, however, are subject to the LGPL or CPL terms.\r
699 +*/\r
700 +\r
701 +#ifndef __LZMADECODE_H\r
702 +#define __LZMADECODE_H\r
703 +\r
704 +#include "LzmaTypes.h"\r
705 +\r
706 +/* #define _LZMA_IN_CB */\r
707 +/* Use callback for input data */\r
708 +\r
709 +/* #define _LZMA_OUT_READ */\r
710 +/* Use read function for output data */\r
711 +\r
712 +/* #define _LZMA_PROB32 */\r
713 +/* It can increase speed on some 32-bit CPUs, \r
714 +   but memory usage will be doubled in that case */\r
715 +\r
716 +/* #define _LZMA_LOC_OPT */\r
717 +/* Enable local speed optimizations inside code */\r
718 +\r
719 +#ifdef _LZMA_PROB32\r
720 +#define CProb UInt32\r
721 +#else\r
722 +#define CProb UInt16\r
723 +#endif\r
724 +\r
725 +#define LZMA_RESULT_OK 0\r
726 +#define LZMA_RESULT_DATA_ERROR 1\r
727 +\r
728 +#ifdef _LZMA_IN_CB\r
729 +typedef struct _ILzmaInCallback\r
730 +{\r
731 +  int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);\r
732 +} ILzmaInCallback;\r
733 +#endif\r
734 +\r
735 +#define LZMA_BASE_SIZE 1846\r
736 +#define LZMA_LIT_SIZE 768\r
737 +\r
738 +#define LZMA_PROPERTIES_SIZE 5\r
739 +\r
740 +typedef struct _CLzmaProperties\r
741 +{\r
742 +  int lc;\r
743 +  int lp;\r
744 +  int pb;\r
745 +  #ifdef _LZMA_OUT_READ\r
746 +  UInt32 DictionarySize;\r
747 +  #endif\r
748 +}CLzmaProperties;\r
749 +\r
750 +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);\r
751 +\r
752 +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))\r
753 +\r
754 +#define kLzmaNeedInitId (-2)\r
755 +\r
756 +typedef struct _CLzmaDecoderState\r
757 +{\r
758 +  CLzmaProperties Properties;\r
759 +  CProb *Probs;\r
760 +\r
761 +  #ifdef _LZMA_IN_CB\r
762 +  const unsigned char *Buffer;\r
763 +  const unsigned char *BufferLim;\r
764 +  #endif\r
765 +\r
766 +  #ifdef _LZMA_OUT_READ\r
767 +  unsigned char *Dictionary;\r
768 +  UInt32 Range;\r
769 +  UInt32 Code;\r
770 +  UInt32 DictionaryPos;\r
771 +  UInt32 GlobalPos;\r
772 +  UInt32 DistanceLimit;\r
773 +  UInt32 Reps[4];\r
774 +  int State;\r
775 +  int RemainLen;\r
776 +  unsigned char TempDictionary[4];\r
777 +  #endif\r
778 +} CLzmaDecoderState;\r
779 +\r
780 +#ifdef _LZMA_OUT_READ\r
781 +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }\r
782 +#endif\r
783 +\r
784 +int LzmaDecode(CLzmaDecoderState *vs,\r
785 +    #ifdef _LZMA_IN_CB\r
786 +    ILzmaInCallback *inCallback,\r
787 +    #else\r
788 +    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,\r
789 +    #endif\r
790 +    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);\r
791 +\r
792 +#endif\r
793 diff -urN linux-2.6.23/fs/squashfs/LzmaTypes.h linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h\r
794 --- linux-2.6.23/fs/squashfs/LzmaTypes.h        1969-12-31 19:00:00.000000000 -0500\r
795 +++ linux-2.6.23.sqlzma/fs/squashfs/LzmaTypes.h 2007-10-14 13:00:30.000000000 -0400\r
796 @@ -0,0 +1,45 @@\r
797 +/* \r
798 +LzmaTypes.h \r
799 +\r
800 +Types for LZMA Decoder\r
801 +\r
802 +This file written and distributed to public domain by Igor Pavlov.\r
803 +This file is part of LZMA SDK 4.40 (2006-05-01)\r
804 +*/\r
805 +\r
806 +#ifndef __LZMATYPES_H\r
807 +#define __LZMATYPES_H\r
808 +\r
809 +#ifndef _7ZIP_BYTE_DEFINED\r
810 +#define _7ZIP_BYTE_DEFINED\r
811 +typedef unsigned char Byte;\r
812 +#endif \r
813 +\r
814 +#ifndef _7ZIP_UINT16_DEFINED\r
815 +#define _7ZIP_UINT16_DEFINED\r
816 +typedef unsigned short UInt16;\r
817 +#endif \r
818 +\r
819 +#ifndef _7ZIP_UINT32_DEFINED\r
820 +#define _7ZIP_UINT32_DEFINED\r
821 +#ifdef _LZMA_UINT32_IS_ULONG\r
822 +typedef unsigned long UInt32;\r
823 +#else\r
824 +typedef unsigned int UInt32;\r
825 +#endif\r
826 +#endif \r
827 +\r
828 +/* #define _LZMA_SYSTEM_SIZE_T */\r
829 +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */\r
830 +\r
831 +#ifndef _7ZIP_SIZET_DEFINED\r
832 +#define _7ZIP_SIZET_DEFINED\r
833 +#ifdef _LZMA_SYSTEM_SIZE_T\r
834 +#include <stddef.h>\r
835 +typedef size_t SizeT;\r
836 +#else\r
837 +typedef UInt32 SizeT;\r
838 +#endif\r
839 +#endif\r
840 +\r
841 +#endif\r
842 diff -urN linux-2.6.23/fs/squashfs/Makefile linux-2.6.23.sqlzma/fs/squashfs/Makefile\r
843 --- linux-2.6.23/fs/squashfs/Makefile   1969-12-31 19:00:00.000000000 -0500\r
844 +++ linux-2.6.23.sqlzma/fs/squashfs/Makefile    2007-10-14 12:56:24.000000000 -0400\r
845 @@ -0,0 +1,18 @@\r
846 +\r
847 +# Copyright (C) 2006 Junjiro Okajima\r
848 +# Copyright (C) 2006 Tomas Matejicek, slax.org\r
849 +\r
850 +# LICENSE follows the described one in lzma.txt.\r
851 +\r
852 +# $Id: Makefile,v 1.3 2006/11/27 03:54:58 jro Exp $\r
853 +\r
854 +#\r
855 +# Makefile for the linux squashfs routines.\r
856 +#\r
857 +\r
858 +obj-$(CONFIG_SQUASHFS) += unlzma.o sqlzma.o squashfs.o\r
859 +unlzma-y += module.o\r
860 +sqlzma-y += uncomp.o\r
861 +squashfs-y += inode.o\r
862 +squashfs-y += squashfs2_0.o\r
863 +\r
864 diff -urN linux-2.6.23/fs/squashfs/inode.c linux-2.6.23.sqlzma/fs/squashfs/inode.c\r
865 --- linux-2.6.23/fs/squashfs/inode.c    1969-12-31 19:00:00.000000000 -0500\r
866 +++ linux-2.6.23.sqlzma/fs/squashfs/inode.c     2007-10-14 10:29:23.000000000 -0400\r
867 @@ -0,0 +1,2430 @@\r
868 +/*\r
869 + * Squashfs - a compressed read only filesystem for Linux\r
870 + *\r
871 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
872 + * Phillip Lougher <phillip@lougher.org.uk>\r
873 + *\r
874 + * This program is free software; you can redistribute it and/or\r
875 + * modify it under the terms of the GNU General Public License\r
876 + * as published by the Free Software Foundation; either version 2,\r
877 + * or (at your option) any later version.\r
878 + *\r
879 + * This program is distributed in the hope that it will be useful,\r
880 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
881 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
882 + * GNU General Public License for more details.\r
883 + *\r
884 + * You should have received a copy of the GNU General Public License\r
885 + * along with this program; if not, write to the Free Software\r
886 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
887 + *\r
888 + * inode.c\r
889 + */\r
890 +\r
891 +#include <linux/squashfs_fs.h>\r
892 +#include <linux/module.h>\r
893 +#include <linux/zlib.h>\r
894 +#include <linux/fs.h>\r
895 +#include <linux/squashfs_fs_sb.h>\r
896 +#include <linux/squashfs_fs_i.h>\r
897 +#include <linux/buffer_head.h>\r
898 +#include <linux/vfs.h>\r
899 +#include <linux/vmalloc.h>\r
900 +#include <linux/smp_lock.h>\r
901 +#include <linux/sched.h>\r
902 +#include <linux/exportfs.h>\r
903 +\r
904 +#include "squashfs.h"\r
905 +#include "sqlzma.h"\r
906 +#include "sqmagic.h"\r
907 +\r
908 +#undef KeepPreemptive\r
909 +#if defined(CONFIG_PREEMPT) && !defined(UnsquashNoPreempt)\r
910 +#define KeepPreemptive\r
911 +#endif\r
912 +\r
913 +struct sqlzma {\r
914 +#ifdef KeepPreemptive\r
915 +       struct mutex mtx;\r
916 +#endif\r
917 +       unsigned char read_data[SQUASHFS_FILE_MAX_SIZE];\r
918 +       struct sqlzma_un un;\r
919 +};\r
920 +static DEFINE_PER_CPU(struct sqlzma *, sqlzma);\r
921 +\r
922 +#define dpri(fmt, args...) /* printk("%s:%d: " fmt, __func__, __LINE__, ##args) */\r
923 +#define dpri_un(un)    dpri("un{%d, {%d %p}, {%d %p}, {%d %p}}\n", \\r
924 +                            (un)->un_lzma, (un)->un_a[0].sz, (un)->un_a[0].buf, \\r
925 +                            (un)->un_a[1].sz, (un)->un_a[1].buf, \\r
926 +                            (un)->un_a[2].sz, (un)->un_a[2].buf)\r
927 +\r
928 +static void vfs_read_inode(struct inode *i);\r
929 +static struct dentry *squashfs_get_parent(struct dentry *child);\r
930 +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);\r
931 +static int squashfs_statfs(struct dentry *, struct kstatfs *);\r
932 +static int squashfs_symlink_readpage(struct file *file, struct page *page);\r
933 +static long long read_blocklist(struct inode *inode, int index,\r
934 +                               int readahead_blks, char *block_list,\r
935 +                               unsigned short **block_p, unsigned int *bsize);\r
936 +static int squashfs_readpage(struct file *file, struct page *page);\r
937 +static int squashfs_readpage4K(struct file *file, struct page *page);\r
938 +static int squashfs_readdir(struct file *, void *, filldir_t);\r
939 +static struct dentry *squashfs_lookup(struct inode *, struct dentry *,\r
940 +                               struct nameidata *);\r
941 +static int squashfs_remount(struct super_block *s, int *flags, char *data);\r
942 +static void squashfs_put_super(struct super_block *);\r
943 +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,\r
944 +                               struct vfsmount *);\r
945 +static struct inode *squashfs_alloc_inode(struct super_block *sb);\r
946 +static void squashfs_destroy_inode(struct inode *inode);\r
947 +static int init_inodecache(void);\r
948 +static void destroy_inodecache(void);\r
949 +\r
950 +static struct file_system_type squashfs_fs_type = {\r
951 +       .owner = THIS_MODULE,\r
952 +       .name = "squashfs",\r
953 +       .get_sb = squashfs_get_sb,\r
954 +       .kill_sb = kill_block_super,\r
955 +       .fs_flags = FS_REQUIRES_DEV\r
956 +};\r
957 +\r
958 +static const unsigned char squashfs_filetype_table[] = {\r
959 +       DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK\r
960 +};\r
961 +\r
962 +static struct super_operations squashfs_super_ops = {\r
963 +       .alloc_inode = squashfs_alloc_inode,\r
964 +       .destroy_inode = squashfs_destroy_inode,\r
965 +       .statfs = squashfs_statfs,\r
966 +       .put_super = squashfs_put_super,\r
967 +       .remount_fs = squashfs_remount\r
968 +};\r
969 +\r
970 +static struct super_operations squashfs_export_super_ops = {\r
971 +       .alloc_inode = squashfs_alloc_inode,\r
972 +       .destroy_inode = squashfs_destroy_inode,\r
973 +       .statfs = squashfs_statfs,\r
974 +       .put_super = squashfs_put_super,\r
975 +       .read_inode = vfs_read_inode\r
976 +};\r
977 +\r
978 +static struct export_operations squashfs_export_ops = {\r
979 +       .get_parent = squashfs_get_parent\r
980 +};\r
981 +\r
982 +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {\r
983 +       .readpage = squashfs_symlink_readpage\r
984 +};\r
985 +\r
986 +SQSH_EXTERN const struct address_space_operations squashfs_aops = {\r
987 +       .readpage = squashfs_readpage\r
988 +};\r
989 +\r
990 +SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {\r
991 +       .readpage = squashfs_readpage4K\r
992 +};\r
993 +\r
994 +static const struct file_operations squashfs_dir_ops = {\r
995 +       .read = generic_read_dir,\r
996 +       .readdir = squashfs_readdir\r
997 +};\r
998 +\r
999 +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {\r
1000 +       .lookup = squashfs_lookup\r
1001 +};\r
1002 +\r
1003 +\r
1004 +static struct buffer_head *get_block_length(struct super_block *s,\r
1005 +                               int *cur_index, int *offset, int *c_byte)\r
1006 +{\r
1007 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1008 +       unsigned short temp;\r
1009 +       struct buffer_head *bh;\r
1010 +\r
1011 +       if (!(bh = sb_bread(s, *cur_index)))\r
1012 +               goto out;\r
1013 +\r
1014 +       if (msblk->devblksize - *offset == 1) {\r
1015 +               if (msblk->swap)\r
1016 +                       ((unsigned char *) &temp)[1] = *((unsigned char *)\r
1017 +                               (bh->b_data + *offset));\r
1018 +               else\r
1019 +                       ((unsigned char *) &temp)[0] = *((unsigned char *)\r
1020 +                               (bh->b_data + *offset));\r
1021 +               brelse(bh);\r
1022 +               if (!(bh = sb_bread(s, ++(*cur_index))))\r
1023 +                       goto out;\r
1024 +               if (msblk->swap)\r
1025 +                       ((unsigned char *) &temp)[0] = *((unsigned char *)\r
1026 +                               bh->b_data); \r
1027 +               else\r
1028 +                       ((unsigned char *) &temp)[1] = *((unsigned char *)\r
1029 +                               bh->b_data); \r
1030 +               *c_byte = temp;\r
1031 +               *offset = 1;\r
1032 +       } else {\r
1033 +               if (msblk->swap) {\r
1034 +                       ((unsigned char *) &temp)[1] = *((unsigned char *)\r
1035 +                               (bh->b_data + *offset));\r
1036 +                       ((unsigned char *) &temp)[0] = *((unsigned char *)\r
1037 +                               (bh->b_data + *offset + 1)); \r
1038 +               } else {\r
1039 +                       ((unsigned char *) &temp)[0] = *((unsigned char *)\r
1040 +                               (bh->b_data + *offset));\r
1041 +                       ((unsigned char *) &temp)[1] = *((unsigned char *)\r
1042 +                               (bh->b_data + *offset + 1)); \r
1043 +               }\r
1044 +               *c_byte = temp;\r
1045 +               *offset += 2;\r
1046 +       }\r
1047 +\r
1048 +       if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {\r
1049 +               if (*offset == msblk->devblksize) {\r
1050 +                       brelse(bh);\r
1051 +                       if (!(bh = sb_bread(s, ++(*cur_index))))\r
1052 +                               goto out;\r
1053 +                       *offset = 0;\r
1054 +               }\r
1055 +               if (*((unsigned char *) (bh->b_data + *offset)) !=\r
1056 +                                               SQUASHFS_MARKER_BYTE) {\r
1057 +                       ERROR("Metadata block marker corrupt @ %x\n",\r
1058 +                                               *cur_index);\r
1059 +                       brelse(bh);\r
1060 +                       goto out;\r
1061 +               }\r
1062 +               (*offset)++;\r
1063 +       }\r
1064 +       return bh;\r
1065 +\r
1066 +out:\r
1067 +       return NULL;\r
1068 +}\r
1069 +\r
1070 +\r
1071 +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,\r
1072 +                       long long index, unsigned int length,\r
1073 +                       long long *next_index, int srclength)\r
1074 +{\r
1075 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1076 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
1077 +       struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>\r
1078 +                       msblk->devblksize_log2) + 2];\r
1079 +       unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);\r
1080 +       unsigned int cur_index = index >> msblk->devblksize_log2;\r
1081 +       int bytes, avail_bytes, b = 0, k = 0;\r
1082 +       unsigned int compressed;\r
1083 +       unsigned int c_byte = length;\r
1084 +\r
1085 +       if (c_byte) {\r
1086 +               bytes = msblk->devblksize - offset;\r
1087 +               compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);\r
1088 +               c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);\r
1089 +\r
1090 +               TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed\r
1091 +                                       ? "" : "un", (unsigned int) c_byte, srclength);\r
1092 +\r
1093 +               if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)\r
1094 +                       goto read_failure;\r
1095 +\r
1096 +               if (!(bh[0] = sb_getblk(s, cur_index)))\r
1097 +                       goto block_release;\r
1098 +\r
1099 +               for (b = 1; bytes < c_byte; b++) {\r
1100 +                       if (!(bh[b] = sb_getblk(s, ++cur_index)))\r
1101 +                               goto block_release;\r
1102 +                       bytes += msblk->devblksize;\r
1103 +               }\r
1104 +               ll_rw_block(READ, b, bh);\r
1105 +       } else {\r
1106 +               if (index < 0 || (index + 2) > sblk->bytes_used)\r
1107 +                       goto read_failure;\r
1108 +\r
1109 +               if (!(bh[0] = get_block_length(s, &cur_index, &offset,\r
1110 +                                                               &c_byte)))\r
1111 +                       goto read_failure;\r
1112 +\r
1113 +               bytes = msblk->devblksize - offset;\r
1114 +               compressed = SQUASHFS_COMPRESSED(c_byte);\r
1115 +               c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);\r
1116 +\r
1117 +               TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed\r
1118 +                                       ? "" : "un", (unsigned int) c_byte);\r
1119 +\r
1120 +               if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)\r
1121 +                       goto read_failure;\r
1122 +\r
1123 +               for (b = 1; bytes < c_byte; b++) {\r
1124 +                       if (!(bh[b] = sb_getblk(s, ++cur_index)))\r
1125 +                               goto block_release;\r
1126 +                       bytes += msblk->devblksize;\r
1127 +               }\r
1128 +               ll_rw_block(READ, b - 1, bh + 1);\r
1129 +       }\r
1130 +\r
1131 +       if (compressed) {\r
1132 +               int zlib_err = Z_STREAM_END;\r
1133 +               int rest, start;\r
1134 +               enum {Src, Dst};\r
1135 +               struct sized_buf sbuf[2];\r
1136 +               struct sqlzma *percpu;\r
1137 +\r
1138 +               /*\r
1139 +               * uncompress block\r
1140 +               */\r
1141 +               for (k = 0; k < b; k++) {\r
1142 +                       wait_on_buffer(bh[k]);\r
1143 +                       if (!buffer_uptodate(bh[k]))\r
1144 +                               goto block_release;\r
1145 +               }\r
1146 +\r
1147 +               avail_bytes = 0;\r
1148 +               for (k = 0; !avail_bytes && k < b; k++) {\r
1149 +                       avail_bytes = msblk->devblksize - offset;\r
1150 +                       if (c_byte < avail_bytes)\r
1151 +                               avail_bytes = c_byte;\r
1152 +                       if (avail_bytes)\r
1153 +                               break;\r
1154 +                       offset = 0;\r
1155 +                       brelse(bh[k]);\r
1156 +               }\r
1157 +               bytes = 0;\r
1158 +               if (!avail_bytes)\r
1159 +                       goto block_release; // nothing to be process\r
1160 +\r
1161 +               start = k;\r
1162 +               /* it disables preemption */\r
1163 +               percpu = get_cpu_var(sqlzma);\r
1164 +#ifdef KeepPreemptive\r
1165 +               put_cpu_var(sqlzma);\r
1166 +               mutex_lock(&percpu->mtx);\r
1167 +#endif\r
1168 +\r
1169 +               for (; k < b; k++) {\r
1170 +                       memcpy(percpu->read_data + bytes, bh[k]->b_data + offset,\r
1171 +                              avail_bytes);\r
1172 +                       bytes += avail_bytes;\r
1173 +                       offset = 0;\r
1174 +                       brelse(bh[k]);\r
1175 +                       avail_bytes = msblk->devblksize - offset;\r
1176 +                       rest = c_byte - bytes;\r
1177 +                       if (rest < avail_bytes)\r
1178 +                               avail_bytes = rest;\r
1179 +               }\r
1180 +\r
1181 +               sbuf[Src].buf = percpu->read_data;\r
1182 +               sbuf[Src].sz = bytes;\r
1183 +               sbuf[Dst].buf = buffer;\r
1184 +               sbuf[Dst].sz = srclength;\r
1185 +               dpri_un(&percpu->un);\r
1186 +               dpri("src %d %p, dst %d %p\n", sbuf[Src].sz, sbuf[Src].buf,\r
1187 +                    sbuf[Dst].sz, sbuf[Dst].buf);\r
1188 +               zlib_err = sqlzma_un(&percpu->un, sbuf + Src, sbuf + Dst);\r
1189 +               bytes = percpu->un.un_reslen;\r
1190 +\r
1191 +#ifdef KeepPreemptive\r
1192 +               mutex_unlock(&percpu->mtx);\r
1193 +#else\r
1194 +               put_cpu_var(sqlzma);\r
1195 +#endif\r
1196 +               if (unlikely(zlib_err)) {\r
1197 +                       dpri("zlib_err %d\n", zlib_err);\r
1198 +                       goto release_mutex;\r
1199 +               }\r
1200 +       } else {\r
1201 +               int i;\r
1202 +\r
1203 +               for(i = 0; i < b; i++) {\r
1204 +                       wait_on_buffer(bh[i]);\r
1205 +                       if(!buffer_uptodate(bh[i]))\r
1206 +                               goto block_release;\r
1207 +               }\r
1208 +\r
1209 +               for (bytes = 0; k < b; k++) {\r
1210 +                       avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?\r
1211 +                                       msblk->devblksize - offset :\r
1212 +                                       c_byte - bytes;\r
1213 +                       memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);\r
1214 +                       bytes += avail_bytes;\r
1215 +                       offset = 0;\r
1216 +                       brelse(bh[k]);\r
1217 +               }\r
1218 +       }\r
1219 +\r
1220 +       if (next_index)\r
1221 +               *next_index = index + c_byte + (length ? 0 :\r
1222 +                               (SQUASHFS_CHECK_DATA(msblk->sblk.flags)\r
1223 +                                ? 3 : 2));\r
1224 +       return bytes;\r
1225 +\r
1226 +release_mutex:\r
1227 +       //mutex_unlock(&msblk->read_data_mutex);\r
1228 +\r
1229 +block_release:\r
1230 +       for (; k < b; k++)\r
1231 +               brelse(bh[k]);\r
1232 +\r
1233 +read_failure:\r
1234 +       ERROR("sb_bread failed reading block 0x%x\n", cur_index);\r
1235 +       return 0;\r
1236 +}\r
1237 +\r
1238 +\r
1239 +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,\r
1240 +                               long long block, unsigned int offset,\r
1241 +                               int length, long long *next_block,\r
1242 +                               unsigned int *next_offset)\r
1243 +{\r
1244 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1245 +       int n, i, bytes, return_length = length;\r
1246 +       long long next_index;\r
1247 +\r
1248 +       TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);\r
1249 +\r
1250 +       while ( 1 ) {\r
1251 +               for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) \r
1252 +                       if (msblk->block_cache[i].block == block)\r
1253 +                               break; \r
1254 +               \r
1255 +               mutex_lock(&msblk->block_cache_mutex);\r
1256 +\r
1257 +               if (i == SQUASHFS_CACHED_BLKS) {\r
1258 +                       /* read inode header block */\r
1259 +                       for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;\r
1260 +                                       n ; n --, i = (i + 1) %\r
1261 +                                       SQUASHFS_CACHED_BLKS)\r
1262 +                               if (msblk->block_cache[i].block !=\r
1263 +                                                       SQUASHFS_USED_BLK)\r
1264 +                                       break;\r
1265 +\r
1266 +                       if (n == 0) {\r
1267 +                               wait_queue_t wait;\r
1268 +\r
1269 +                               init_waitqueue_entry(&wait, current);\r
1270 +                               add_wait_queue(&msblk->waitq, &wait);\r
1271 +                               set_current_state(TASK_UNINTERRUPTIBLE);\r
1272 +                               mutex_unlock(&msblk->block_cache_mutex);\r
1273 +                               schedule();\r
1274 +                               set_current_state(TASK_RUNNING);\r
1275 +                               remove_wait_queue(&msblk->waitq, &wait);\r
1276 +                               continue;\r
1277 +                       }\r
1278 +                       msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;\r
1279 +\r
1280 +                       if (msblk->block_cache[i].block ==\r
1281 +                                                       SQUASHFS_INVALID_BLK) {\r
1282 +                               if (!(msblk->block_cache[i].data =\r
1283 +                                               kmalloc(SQUASHFS_METADATA_SIZE,\r
1284 +                                               GFP_KERNEL))) {\r
1285 +                                       ERROR("Failed to allocate cache"\r
1286 +                                                       "block\n");\r
1287 +                                       mutex_unlock(&msblk->block_cache_mutex);\r
1288 +                                       goto out;\r
1289 +                               }\r
1290 +                       }\r
1291 +       \r
1292 +                       msblk->block_cache[i].block = SQUASHFS_USED_BLK;\r
1293 +                       mutex_unlock(&msblk->block_cache_mutex);\r
1294 +\r
1295 +                       msblk->block_cache[i].length = squashfs_read_data(s,\r
1296 +                               msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);\r
1297 +                       if (msblk->block_cache[i].length == 0) {\r
1298 +                               ERROR("Unable to read cache block [%llx:%x]\n",\r
1299 +                                               block, offset);\r
1300 +                               mutex_lock(&msblk->block_cache_mutex);\r
1301 +                               msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;\r
1302 +                               kfree(msblk->block_cache[i].data);\r
1303 +                               wake_up(&msblk->waitq);\r
1304 +                               mutex_unlock(&msblk->block_cache_mutex);\r
1305 +                               goto out;\r
1306 +                       }\r
1307 +\r
1308 +                       mutex_lock(&msblk->block_cache_mutex);\r
1309 +                       wake_up(&msblk->waitq);\r
1310 +                       msblk->block_cache[i].block = block;\r
1311 +                       msblk->block_cache[i].next_index = next_index;\r
1312 +                       TRACE("Read cache block [%llx:%x]\n", block, offset);\r
1313 +               }\r
1314 +\r
1315 +               if (msblk->block_cache[i].block != block) {\r
1316 +                       mutex_unlock(&msblk->block_cache_mutex);\r
1317 +                       continue;\r
1318 +               }\r
1319 +\r
1320 +               bytes = msblk->block_cache[i].length - offset;\r
1321 +\r
1322 +               if (bytes < 1) {\r
1323 +                       mutex_unlock(&msblk->block_cache_mutex);\r
1324 +                       goto out;\r
1325 +               } else if (bytes >= length) {\r
1326 +                       if (buffer)\r
1327 +                               memcpy(buffer, msblk->block_cache[i].data +\r
1328 +                                               offset, length);\r
1329 +                       if (msblk->block_cache[i].length - offset == length) {\r
1330 +                               *next_block = msblk->block_cache[i].next_index;\r
1331 +                               *next_offset = 0;\r
1332 +                       } else {\r
1333 +                               *next_block = block;\r
1334 +                               *next_offset = offset + length;\r
1335 +                       }\r
1336 +                       mutex_unlock(&msblk->block_cache_mutex);\r
1337 +                       goto finish;\r
1338 +               } else {\r
1339 +                       if (buffer) {\r
1340 +                               memcpy(buffer, msblk->block_cache[i].data +\r
1341 +                                               offset, bytes);\r
1342 +                               buffer += bytes;\r
1343 +                       }\r
1344 +                       block = msblk->block_cache[i].next_index;\r
1345 +                       mutex_unlock(&msblk->block_cache_mutex);\r
1346 +                       length -= bytes;\r
1347 +                       offset = 0;\r
1348 +               }\r
1349 +       }\r
1350 +\r
1351 +finish:\r
1352 +       return return_length;\r
1353 +out:\r
1354 +       return 0;\r
1355 +}\r
1356 +\r
1357 +\r
1358 +static int get_fragment_location(struct super_block *s, unsigned int fragment,\r
1359 +                               long long *fragment_start_block,\r
1360 +                               unsigned int *fragment_size)\r
1361 +{\r
1362 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1363 +       long long start_block =\r
1364 +               msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];\r
1365 +       int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);\r
1366 +       struct squashfs_fragment_entry fragment_entry;\r
1367 +\r
1368 +       if (msblk->swap) {\r
1369 +               struct squashfs_fragment_entry sfragment_entry;\r
1370 +\r
1371 +               if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,\r
1372 +                                       start_block, offset,\r
1373 +                                       sizeof(sfragment_entry), &start_block,\r
1374 +                                       &offset))\r
1375 +                       goto out;\r
1376 +               SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);\r
1377 +       } else\r
1378 +               if (!squashfs_get_cached_block(s, (char *) &fragment_entry,\r
1379 +                                       start_block, offset,\r
1380 +                                       sizeof(fragment_entry), &start_block,\r
1381 +                                       &offset))\r
1382 +                       goto out;\r
1383 +\r
1384 +       *fragment_start_block = fragment_entry.start_block;\r
1385 +       *fragment_size = fragment_entry.size;\r
1386 +\r
1387 +       return 1;\r
1388 +\r
1389 +out:\r
1390 +       return 0;\r
1391 +}\r
1392 +\r
1393 +\r
1394 +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct\r
1395 +                                       squashfs_fragment_cache *fragment)\r
1396 +{\r
1397 +       mutex_lock(&msblk->fragment_mutex);\r
1398 +       fragment->locked --;\r
1399 +       wake_up(&msblk->fragment_wait_queue);\r
1400 +       mutex_unlock(&msblk->fragment_mutex);\r
1401 +}\r
1402 +\r
1403 +\r
1404 +SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block\r
1405 +                                       *s, long long start_block,\r
1406 +                                       int length)\r
1407 +{\r
1408 +       int i, n;\r
1409 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1410 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
1411 +\r
1412 +       while ( 1 ) {\r
1413 +               mutex_lock(&msblk->fragment_mutex);\r
1414 +\r
1415 +               for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&\r
1416 +                               msblk->fragment[i].block != start_block; i++);\r
1417 +\r
1418 +               if (i == SQUASHFS_CACHED_FRAGMENTS) {\r
1419 +                       for (i = msblk->next_fragment, n =\r
1420 +                               SQUASHFS_CACHED_FRAGMENTS; n &&\r
1421 +                               msblk->fragment[i].locked; n--, i = (i + 1) %\r
1422 +                               SQUASHFS_CACHED_FRAGMENTS);\r
1423 +\r
1424 +                       if (n == 0) {\r
1425 +                               wait_queue_t wait;\r
1426 +\r
1427 +                               init_waitqueue_entry(&wait, current);\r
1428 +                               add_wait_queue(&msblk->fragment_wait_queue,\r
1429 +                                                                       &wait);\r
1430 +                               set_current_state(TASK_UNINTERRUPTIBLE);\r
1431 +                               mutex_unlock(&msblk->fragment_mutex);\r
1432 +                               schedule();\r
1433 +                               set_current_state(TASK_RUNNING);\r
1434 +                               remove_wait_queue(&msblk->fragment_wait_queue,\r
1435 +                                                                       &wait);\r
1436 +                               continue;\r
1437 +                       }\r
1438 +                       msblk->next_fragment = (msblk->next_fragment + 1) %\r
1439 +                               SQUASHFS_CACHED_FRAGMENTS;\r
1440 +                       \r
1441 +                       if (msblk->fragment[i].data == NULL)\r
1442 +                               if (!(msblk->fragment[i].data = SQUASHFS_ALLOC\r
1443 +                                               (SQUASHFS_FILE_MAX_SIZE))) {\r
1444 +                                       ERROR("Failed to allocate fragment "\r
1445 +                                                       "cache block\n");\r
1446 +                                       mutex_unlock(&msblk->fragment_mutex);\r
1447 +                                       goto out;\r
1448 +                               }\r
1449 +\r
1450 +                       msblk->fragment[i].block = SQUASHFS_INVALID_BLK;\r
1451 +                       msblk->fragment[i].locked = 1;\r
1452 +                       mutex_unlock(&msblk->fragment_mutex);\r
1453 +\r
1454 +                       if (!(msblk->fragment[i].length = squashfs_read_data(s,\r
1455 +                                               msblk->fragment[i].data,\r
1456 +                                               start_block, length, NULL, sblk->block_size))) {\r
1457 +                               ERROR("Unable to read fragment cache block "\r
1458 +                                                       "[%llx]\n", start_block);\r
1459 +                               msblk->fragment[i].locked = 0;\r
1460 +                               smp_mb();\r
1461 +                               goto out;\r
1462 +                       }\r
1463 +\r
1464 +                       mutex_lock(&msblk->fragment_mutex);\r
1465 +                       msblk->fragment[i].block = start_block;\r
1466 +                       TRACE("New fragment %d, start block %lld, locked %d\n",\r
1467 +                                               i, msblk->fragment[i].block,\r
1468 +                                               msblk->fragment[i].locked);\r
1469 +                       mutex_unlock(&msblk->fragment_mutex);\r
1470 +                       break;\r
1471 +               }\r
1472 +\r
1473 +               msblk->fragment[i].locked++;\r
1474 +               mutex_unlock(&msblk->fragment_mutex);\r
1475 +               TRACE("Got fragment %d, start block %lld, locked %d\n", i,\r
1476 +                                               msblk->fragment[i].block,\r
1477 +                                               msblk->fragment[i].locked);\r
1478 +               break;\r
1479 +       }\r
1480 +\r
1481 +       return &msblk->fragment[i];\r
1482 +\r
1483 +out:\r
1484 +       return NULL;\r
1485 +}\r
1486 +\r
1487 +\r
1488 +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,\r
1489 +               struct squashfs_base_inode_header *inodeb)\r
1490 +{\r
1491 +       i->i_ino = inodeb->inode_number;\r
1492 +       i->i_mtime.tv_sec = inodeb->mtime;\r
1493 +       i->i_atime.tv_sec = inodeb->mtime;\r
1494 +       i->i_ctime.tv_sec = inodeb->mtime;\r
1495 +       i->i_uid = msblk->uid[inodeb->uid];\r
1496 +       i->i_mode = inodeb->mode;\r
1497 +       i->i_size = 0;\r
1498 +       if (inodeb->guid == SQUASHFS_GUIDS)\r
1499 +               i->i_gid = i->i_uid;\r
1500 +       else\r
1501 +               i->i_gid = msblk->guid[inodeb->guid];\r
1502 +}\r
1503 +\r
1504 +\r
1505 +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)\r
1506 +{\r
1507 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1508 +       long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];\r
1509 +       int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);\r
1510 +       squashfs_inode_t inode;\r
1511 +\r
1512 +       TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);\r
1513 +\r
1514 +       if (msblk->swap) {\r
1515 +               squashfs_inode_t sinode;\r
1516 +\r
1517 +               if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,\r
1518 +                                       sizeof(sinode), &start, &offset))\r
1519 +                       goto out;\r
1520 +               SQUASHFS_SWAP_INODE_T((&inode), &sinode);\r
1521 +       } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,\r
1522 +                                       sizeof(inode), &start, &offset))\r
1523 +                       goto out;\r
1524 +\r
1525 +       TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);\r
1526 +\r
1527 +       return inode;\r
1528 +\r
1529 +out:\r
1530 +       return SQUASHFS_INVALID_BLK;\r
1531 +}\r
1532 +       \r
1533 +\r
1534 +static void vfs_read_inode(struct inode *i)\r
1535 +{\r
1536 +       struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
1537 +       squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);\r
1538 +\r
1539 +       TRACE("Entered vfs_read_inode\n");\r
1540 +\r
1541 +       if(inode != SQUASHFS_INVALID_BLK)\r
1542 +               (msblk->read_inode)(i, inode);\r
1543 +}\r
1544 +\r
1545 +\r
1546 +static struct dentry *squashfs_get_parent(struct dentry *child)\r
1547 +{\r
1548 +       struct inode *i = child->d_inode;\r
1549 +       struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);\r
1550 +       struct dentry *rv;\r
1551 +\r
1552 +       TRACE("Entered squashfs_get_parent\n");\r
1553 +\r
1554 +       if(parent == NULL) {\r
1555 +               rv = ERR_PTR(-EACCES);\r
1556 +               goto out;\r
1557 +       }\r
1558 +\r
1559 +       rv = d_alloc_anon(parent);\r
1560 +       if(rv == NULL)\r
1561 +               rv = ERR_PTR(-ENOMEM);\r
1562 +\r
1563 +out:\r
1564 +       return rv;\r
1565 +}\r
1566 +\r
1567 +       \r
1568 +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)\r
1569 +{\r
1570 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1571 +       struct inode *i = iget_locked(s, inode_number);\r
1572 +\r
1573 +       TRACE("Entered squashfs_iget\n");\r
1574 +\r
1575 +       if(i && (i->i_state & I_NEW)) {\r
1576 +               (msblk->read_inode)(i, inode);\r
1577 +               unlock_new_inode(i);\r
1578 +       }\r
1579 +\r
1580 +       return i;\r
1581 +}\r
1582 +\r
1583 +\r
1584 +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)\r
1585 +{\r
1586 +       struct super_block *s = i->i_sb;\r
1587 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1588 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
1589 +       long long block = SQUASHFS_INODE_BLK(inode) +\r
1590 +               sblk->inode_table_start;\r
1591 +       unsigned int offset = SQUASHFS_INODE_OFFSET(inode);\r
1592 +       long long next_block;\r
1593 +       unsigned int next_offset;\r
1594 +       union squashfs_inode_header id, sid;\r
1595 +       struct squashfs_base_inode_header *inodeb = &id.base,\r
1596 +                                         *sinodeb = &sid.base;\r
1597 +\r
1598 +       TRACE("Entered squashfs_read_inode\n");\r
1599 +\r
1600 +       if (msblk->swap) {\r
1601 +               if (!squashfs_get_cached_block(s, (char *) sinodeb, block,\r
1602 +                                       offset, sizeof(*sinodeb), &next_block,\r
1603 +                                       &next_offset))\r
1604 +                       goto failed_read;\r
1605 +               SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,\r
1606 +                                       sizeof(*sinodeb));\r
1607 +       } else\r
1608 +               if (!squashfs_get_cached_block(s, (char *) inodeb, block,\r
1609 +                                       offset, sizeof(*inodeb), &next_block,\r
1610 +                                       &next_offset))\r
1611 +                       goto failed_read;\r
1612 +\r
1613 +       squashfs_new_inode(msblk, i, inodeb);\r
1614 +\r
1615 +       switch(inodeb->inode_type) {\r
1616 +               case SQUASHFS_FILE_TYPE: {\r
1617 +                       unsigned int frag_size;\r
1618 +                       long long frag_blk;\r
1619 +                       struct squashfs_reg_inode_header *inodep = &id.reg;\r
1620 +                       struct squashfs_reg_inode_header *sinodep = &sid.reg;\r
1621 +                               \r
1622 +                       if (msblk->swap) {\r
1623 +                               if (!squashfs_get_cached_block(s, (char *)\r
1624 +                                               sinodep, block, offset,\r
1625 +                                               sizeof(*sinodep), &next_block,\r
1626 +                                               &next_offset))\r
1627 +                                       goto failed_read;\r
1628 +                               SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);\r
1629 +                       } else\r
1630 +                               if (!squashfs_get_cached_block(s, (char *)\r
1631 +                                               inodep, block, offset,\r
1632 +                                               sizeof(*inodep), &next_block,\r
1633 +                                               &next_offset))\r
1634 +                                       goto failed_read;\r
1635 +\r
1636 +                       frag_blk = SQUASHFS_INVALID_BLK;\r
1637 +                       if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
1638 +                                       !get_fragment_location(s,\r
1639 +                                       inodep->fragment, &frag_blk, &frag_size))\r
1640 +                               goto failed_read;\r
1641 +                               \r
1642 +                       i->i_nlink = 1;\r
1643 +                       i->i_size = inodep->file_size;\r
1644 +                       i->i_fop = &generic_ro_fops;\r
1645 +                       i->i_mode |= S_IFREG;\r
1646 +                       i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
1647 +                       SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
1648 +                       SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
1649 +                       SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
1650 +                       SQUASHFS_I(i)->start_block = inodep->start_block;\r
1651 +                       SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
1652 +                       SQUASHFS_I(i)->offset = next_offset;\r
1653 +                       if (sblk->block_size > 4096)\r
1654 +                               i->i_data.a_ops = &squashfs_aops;\r
1655 +                       else\r
1656 +                               i->i_data.a_ops = &squashfs_aops_4K;\r
1657 +\r
1658 +                       TRACE("File inode %x:%x, start_block %llx, "\r
1659 +                                       "block_list_start %llx, offset %x\n",\r
1660 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
1661 +                                       inodep->start_block, next_block,\r
1662 +                                       next_offset);\r
1663 +                       break;\r
1664 +               }\r
1665 +               case SQUASHFS_LREG_TYPE: {\r
1666 +                       unsigned int frag_size;\r
1667 +                       long long frag_blk;\r
1668 +                       struct squashfs_lreg_inode_header *inodep = &id.lreg;\r
1669 +                       struct squashfs_lreg_inode_header *sinodep = &sid.lreg;\r
1670 +                               \r
1671 +                       if (msblk->swap) {\r
1672 +                               if (!squashfs_get_cached_block(s, (char *)\r
1673 +                                               sinodep, block, offset,\r
1674 +                                               sizeof(*sinodep), &next_block,\r
1675 +                                               &next_offset))\r
1676 +                                       goto failed_read;\r
1677 +                               SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);\r
1678 +                       } else\r
1679 +                               if (!squashfs_get_cached_block(s, (char *)\r
1680 +                                               inodep, block, offset,\r
1681 +                                               sizeof(*inodep), &next_block,\r
1682 +                                               &next_offset))\r
1683 +                                       goto failed_read;\r
1684 +\r
1685 +                       frag_blk = SQUASHFS_INVALID_BLK;\r
1686 +                       if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
1687 +                                       !get_fragment_location(s,\r
1688 +                                       inodep->fragment, &frag_blk, &frag_size))\r
1689 +                               goto failed_read;\r
1690 +                               \r
1691 +                       i->i_nlink = inodep->nlink;\r
1692 +                       i->i_size = inodep->file_size;\r
1693 +                       i->i_fop = &generic_ro_fops;\r
1694 +                       i->i_mode |= S_IFREG;\r
1695 +                       i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
1696 +                       SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
1697 +                       SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
1698 +                       SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
1699 +                       SQUASHFS_I(i)->start_block = inodep->start_block;\r
1700 +                       SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
1701 +                       SQUASHFS_I(i)->offset = next_offset;\r
1702 +                       if (sblk->block_size > 4096)\r
1703 +                               i->i_data.a_ops = &squashfs_aops;\r
1704 +                       else\r
1705 +                               i->i_data.a_ops = &squashfs_aops_4K;\r
1706 +\r
1707 +                       TRACE("File inode %x:%x, start_block %llx, "\r
1708 +                                       "block_list_start %llx, offset %x\n",\r
1709 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
1710 +                                       inodep->start_block, next_block,\r
1711 +                                       next_offset);\r
1712 +                       break;\r
1713 +               }\r
1714 +               case SQUASHFS_DIR_TYPE: {\r
1715 +                       struct squashfs_dir_inode_header *inodep = &id.dir;\r
1716 +                       struct squashfs_dir_inode_header *sinodep = &sid.dir;\r
1717 +\r
1718 +                       if (msblk->swap) {\r
1719 +                               if (!squashfs_get_cached_block(s, (char *)\r
1720 +                                               sinodep, block, offset,\r
1721 +                                               sizeof(*sinodep), &next_block,\r
1722 +                                               &next_offset))\r
1723 +                                       goto failed_read;\r
1724 +                               SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);\r
1725 +                       } else\r
1726 +                               if (!squashfs_get_cached_block(s, (char *)\r
1727 +                                               inodep, block, offset,\r
1728 +                                               sizeof(*inodep), &next_block,\r
1729 +                                               &next_offset))\r
1730 +                                       goto failed_read;\r
1731 +\r
1732 +                       i->i_nlink = inodep->nlink;\r
1733 +                       i->i_size = inodep->file_size;\r
1734 +                       i->i_op = &squashfs_dir_inode_ops;\r
1735 +                       i->i_fop = &squashfs_dir_ops;\r
1736 +                       i->i_mode |= S_IFDIR;\r
1737 +                       SQUASHFS_I(i)->start_block = inodep->start_block;\r
1738 +                       SQUASHFS_I(i)->offset = inodep->offset;\r
1739 +                       SQUASHFS_I(i)->u.s2.directory_index_count = 0;\r
1740 +                       SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;\r
1741 +\r
1742 +                       TRACE("Directory inode %x:%x, start_block %x, offset "\r
1743 +                                       "%x\n", SQUASHFS_INODE_BLK(inode),\r
1744 +                                       offset, inodep->start_block,\r
1745 +                                       inodep->offset);\r
1746 +                       break;\r
1747 +               }\r
1748 +               case SQUASHFS_LDIR_TYPE: {\r
1749 +                       struct squashfs_ldir_inode_header *inodep = &id.ldir;\r
1750 +                       struct squashfs_ldir_inode_header *sinodep = &sid.ldir;\r
1751 +\r
1752 +                       if (msblk->swap) {\r
1753 +                               if (!squashfs_get_cached_block(s, (char *)\r
1754 +                                               sinodep, block, offset,\r
1755 +                                               sizeof(*sinodep), &next_block,\r
1756 +                                               &next_offset))\r
1757 +                                       goto failed_read;\r
1758 +                               SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,\r
1759 +                                               sinodep);\r
1760 +                       } else\r
1761 +                               if (!squashfs_get_cached_block(s, (char *)\r
1762 +                                               inodep, block, offset,\r
1763 +                                               sizeof(*inodep), &next_block,\r
1764 +                                               &next_offset))\r
1765 +                                       goto failed_read;\r
1766 +\r
1767 +                       i->i_nlink = inodep->nlink;\r
1768 +                       i->i_size = inodep->file_size;\r
1769 +                       i->i_op = &squashfs_dir_inode_ops;\r
1770 +                       i->i_fop = &squashfs_dir_ops;\r
1771 +                       i->i_mode |= S_IFDIR;\r
1772 +                       SQUASHFS_I(i)->start_block = inodep->start_block;\r
1773 +                       SQUASHFS_I(i)->offset = inodep->offset;\r
1774 +                       SQUASHFS_I(i)->u.s2.directory_index_start = next_block;\r
1775 +                       SQUASHFS_I(i)->u.s2.directory_index_offset =\r
1776 +                                                               next_offset;\r
1777 +                       SQUASHFS_I(i)->u.s2.directory_index_count =\r
1778 +                                                               inodep->i_count;\r
1779 +                       SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;\r
1780 +\r
1781 +                       TRACE("Long directory inode %x:%x, start_block %x, "\r
1782 +                                       "offset %x\n",\r
1783 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
1784 +                                       inodep->start_block, inodep->offset);\r
1785 +                       break;\r
1786 +               }\r
1787 +               case SQUASHFS_SYMLINK_TYPE: {\r
1788 +                       struct squashfs_symlink_inode_header *inodep =\r
1789 +                                                               &id.symlink;\r
1790 +                       struct squashfs_symlink_inode_header *sinodep =\r
1791 +                                                               &sid.symlink;\r
1792 +       \r
1793 +                       if (msblk->swap) {\r
1794 +                               if (!squashfs_get_cached_block(s, (char *)\r
1795 +                                               sinodep, block, offset,\r
1796 +                                               sizeof(*sinodep), &next_block,\r
1797 +                                               &next_offset))\r
1798 +                                       goto failed_read;\r
1799 +                               SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,\r
1800 +                                                               sinodep);\r
1801 +                       } else\r
1802 +                               if (!squashfs_get_cached_block(s, (char *)\r
1803 +                                               inodep, block, offset,\r
1804 +                                               sizeof(*inodep), &next_block,\r
1805 +                                               &next_offset))\r
1806 +                                       goto failed_read;\r
1807 +\r
1808 +                       i->i_nlink = inodep->nlink;\r
1809 +                       i->i_size = inodep->symlink_size;\r
1810 +                       i->i_op = &page_symlink_inode_operations;\r
1811 +                       i->i_data.a_ops = &squashfs_symlink_aops;\r
1812 +                       i->i_mode |= S_IFLNK;\r
1813 +                       SQUASHFS_I(i)->start_block = next_block;\r
1814 +                       SQUASHFS_I(i)->offset = next_offset;\r
1815 +\r
1816 +                       TRACE("Symbolic link inode %x:%x, start_block %llx, "\r
1817 +                                       "offset %x\n",\r
1818 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
1819 +                                       next_block, next_offset);\r
1820 +                       break;\r
1821 +                }\r
1822 +                case SQUASHFS_BLKDEV_TYPE:\r
1823 +                case SQUASHFS_CHRDEV_TYPE: {\r
1824 +                       struct squashfs_dev_inode_header *inodep = &id.dev;\r
1825 +                       struct squashfs_dev_inode_header *sinodep = &sid.dev;\r
1826 +\r
1827 +                       if (msblk->swap) {\r
1828 +                               if (!squashfs_get_cached_block(s, (char *)\r
1829 +                                               sinodep, block, offset,\r
1830 +                                               sizeof(*sinodep), &next_block,\r
1831 +                                               &next_offset))\r
1832 +                                       goto failed_read;\r
1833 +                               SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);\r
1834 +                       } else  \r
1835 +                               if (!squashfs_get_cached_block(s, (char *)\r
1836 +                                               inodep, block, offset,\r
1837 +                                               sizeof(*inodep), &next_block,\r
1838 +                                               &next_offset))\r
1839 +                                       goto failed_read;\r
1840 +\r
1841 +                       i->i_nlink = inodep->nlink;\r
1842 +                       i->i_mode |= (inodeb->inode_type ==\r
1843 +                                       SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :\r
1844 +                                       S_IFBLK;\r
1845 +                       init_special_inode(i, i->i_mode,\r
1846 +                                       old_decode_dev(inodep->rdev));\r
1847 +\r
1848 +                       TRACE("Device inode %x:%x, rdev %x\n",\r
1849 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
1850 +                                       inodep->rdev);\r
1851 +                       break;\r
1852 +                }\r
1853 +                case SQUASHFS_FIFO_TYPE:\r
1854 +                case SQUASHFS_SOCKET_TYPE: {\r
1855 +                       struct squashfs_ipc_inode_header *inodep = &id.ipc;\r
1856 +                       struct squashfs_ipc_inode_header *sinodep = &sid.ipc;\r
1857 +\r
1858 +                       if (msblk->swap) {\r
1859 +                               if (!squashfs_get_cached_block(s, (char *)\r
1860 +                                               sinodep, block, offset,\r
1861 +                                               sizeof(*sinodep), &next_block,\r
1862 +                                               &next_offset))\r
1863 +                                       goto failed_read;\r
1864 +                               SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);\r
1865 +                       } else  \r
1866 +                               if (!squashfs_get_cached_block(s, (char *)\r
1867 +                                               inodep, block, offset,\r
1868 +                                               sizeof(*inodep), &next_block,\r
1869 +                                               &next_offset))\r
1870 +                                       goto failed_read;\r
1871 +\r
1872 +                       i->i_nlink = inodep->nlink;\r
1873 +                       i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)\r
1874 +                                                       ? S_IFIFO : S_IFSOCK;\r
1875 +                       init_special_inode(i, i->i_mode, 0);\r
1876 +                       break;\r
1877 +                }\r
1878 +                default:\r
1879 +                       ERROR("Unknown inode type %d in squashfs_iget!\n",\r
1880 +                                       inodeb->inode_type);\r
1881 +                       goto failed_read1;\r
1882 +       }\r
1883 +       \r
1884 +       return 1;\r
1885 +\r
1886 +failed_read:\r
1887 +       ERROR("Unable to read inode [%llx:%x]\n", block, offset);\r
1888 +\r
1889 +failed_read1:\r
1890 +       make_bad_inode(i);\r
1891 +       return 0;\r
1892 +}\r
1893 +\r
1894 +\r
1895 +static int read_inode_lookup_table(struct super_block *s)\r
1896 +{\r
1897 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1898 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
1899 +       unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);\r
1900 +\r
1901 +       TRACE("In read_inode_lookup_table, length %d\n", length);\r
1902 +\r
1903 +       /* Allocate inode lookup table */\r
1904 +       if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {\r
1905 +               ERROR("Failed to allocate inode lookup table\n");\r
1906 +               return 0;\r
1907 +       }\r
1908 +   \r
1909 +       if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,\r
1910 +                       sblk->lookup_table_start, length |\r
1911 +                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {\r
1912 +               ERROR("unable to read inode lookup table\n");\r
1913 +               return 0;\r
1914 +       }\r
1915 +\r
1916 +       if (msblk->swap) {\r
1917 +               int i;\r
1918 +               long long block;\r
1919 +\r
1920 +               for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {\r
1921 +                       SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),\r
1922 +                                               &msblk->inode_lookup_table[i], 1);\r
1923 +                       msblk->inode_lookup_table[i] = block;\r
1924 +               }\r
1925 +       }\r
1926 +\r
1927 +       return 1;\r
1928 +}\r
1929 +\r
1930 +\r
1931 +static int read_fragment_index_table(struct super_block *s)\r
1932 +{\r
1933 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
1934 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
1935 +       unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);\r
1936 +\r
1937 +       if(length == 0)\r
1938 +               return 1;\r
1939 +\r
1940 +       /* Allocate fragment index table */\r
1941 +       if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {\r
1942 +               ERROR("Failed to allocate fragment index table\n");\r
1943 +               return 0;\r
1944 +       }\r
1945 +   \r
1946 +       if (!squashfs_read_data(s, (char *) msblk->fragment_index,\r
1947 +                       sblk->fragment_table_start, length |\r
1948 +                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {\r
1949 +               ERROR("unable to read fragment index table\n");\r
1950 +               return 0;\r
1951 +       }\r
1952 +\r
1953 +       if (msblk->swap) {\r
1954 +               int i;\r
1955 +               long long fragment;\r
1956 +\r
1957 +               for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {\r
1958 +                       SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),\r
1959 +                                               &msblk->fragment_index[i], 1);\r
1960 +                       msblk->fragment_index[i] = fragment;\r
1961 +               }\r
1962 +       }\r
1963 +\r
1964 +       return 1;\r
1965 +}\r
1966 +\r
1967 +\r
1968 +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)\r
1969 +{\r
1970 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
1971 +\r
1972 +       msblk->read_inode = squashfs_read_inode;\r
1973 +       msblk->read_blocklist = read_blocklist;\r
1974 +       msblk->read_fragment_index_table = read_fragment_index_table;\r
1975 +\r
1976 +       if (sblk->s_major == 1) {\r
1977 +               if (!squashfs_1_0_supported(msblk)) {\r
1978 +                       SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "\r
1979 +                               "are unsupported\n");\r
1980 +                       SERROR("Please recompile with "\r
1981 +                               "Squashfs 1.0 support enabled\n");\r
1982 +                       return 0;\r
1983 +               }\r
1984 +       } else if (sblk->s_major == 2) {\r
1985 +               if (!squashfs_2_0_supported(msblk)) {\r
1986 +                       SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "\r
1987 +                               "are unsupported\n");\r
1988 +                       SERROR("Please recompile with "\r
1989 +                               "Squashfs 2.0 support enabled\n");\r
1990 +                       return 0;\r
1991 +               }\r
1992 +       } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >\r
1993 +                       SQUASHFS_MINOR) {\r
1994 +               SERROR("Major/Minor mismatch, trying to mount newer %d.%d "\r
1995 +                               "filesystem\n", sblk->s_major, sblk->s_minor);\r
1996 +               SERROR("Please update your kernel\n");\r
1997 +               return 0;\r
1998 +       }\r
1999 +\r
2000 +       return 1;\r
2001 +}\r
2002 +\r
2003 +\r
2004 +static int squashfs_fill_super(struct super_block *s, void *data, int silent)\r
2005 +{\r
2006 +       struct squashfs_sb_info *msblk;\r
2007 +       struct squashfs_super_block *sblk;\r
2008 +       int i, err;\r
2009 +       char b[BDEVNAME_SIZE];\r
2010 +       struct inode *root;\r
2011 +       void *label;\r
2012 +\r
2013 +       TRACE("Entered squashfs_read_superblock\n");\r
2014 +\r
2015 +       err = -ENOMEM;\r
2016 +       if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),\r
2017 +                                               GFP_KERNEL))) {\r
2018 +               ERROR("Failed to allocate superblock\n");\r
2019 +               goto failure;\r
2020 +       }\r
2021 +       label = &&out_fsinfo;\r
2022 +       memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));\r
2023 +       msblk = s->s_fs_info;\r
2024 +       sblk = &msblk->sblk;\r
2025 +       \r
2026 +       msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);\r
2027 +       msblk->devblksize_log2 = ffz(~msblk->devblksize);\r
2028 +\r
2029 +       //mutex_init(&msblk->read_data_mutex);\r
2030 +       mutex_init(&msblk->read_page_mutex);\r
2031 +       mutex_init(&msblk->block_cache_mutex);\r
2032 +       mutex_init(&msblk->fragment_mutex);\r
2033 +       mutex_init(&msblk->meta_index_mutex);\r
2034 +       \r
2035 +       init_waitqueue_head(&msblk->waitq);\r
2036 +       init_waitqueue_head(&msblk->fragment_wait_queue);\r
2037 +\r
2038 +       err = -EINVAL;\r
2039 +       sblk->bytes_used = sizeof(struct squashfs_super_block);\r
2040 +       if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,\r
2041 +                                       sizeof(struct squashfs_super_block) |\r
2042 +                                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {\r
2043 +               SERROR("unable to read superblock\n");\r
2044 +               goto *label;\r
2045 +       }\r
2046 +\r
2047 +       /* Check it is a SQUASHFS superblock */\r
2048 +       s->s_magic = sblk->s_magic;\r
2049 +       msblk->swap = 0;\r
2050 +       dpri("magic 0x%x\n", sblk->s_magic);\r
2051 +       switch (sblk->s_magic) {\r
2052 +               struct squashfs_super_block ssblk;\r
2053 +\r
2054 +       case SQUASHFS_MAGIC_SWAP:\r
2055 +               /*FALLTHROUGH*/\r
2056 +       case SQUASHFS_MAGIC_LZMA_SWAP:\r
2057 +               WARNING("Mounting a different endian SQUASHFS "\r
2058 +                       "filesystem on %s\n", bdevname(s->s_bdev, b));\r
2059 +\r
2060 +               SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);\r
2061 +               memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));\r
2062 +               msblk->swap = 1;\r
2063 +               /*FALLTHROUGH*/\r
2064 +       case SQUASHFS_MAGIC:\r
2065 +       case SQUASHFS_MAGIC_LZMA:\r
2066 +               break;\r
2067 +       default:\r
2068 +               SERROR("Can't find a SQUASHFS superblock on %s\n",\r
2069 +                      bdevname(s->s_bdev, b));\r
2070 +               goto *label;\r
2071 +       }\r
2072 +\r
2073 +       {\r
2074 +               struct sqlzma *p;\r
2075 +               dpri("block_size %d\n", sblk->block_size);\r
2076 +               BUG_ON(sblk->block_size > sizeof(p->read_data));\r
2077 +       }\r
2078 +\r
2079 +       /* Check the MAJOR & MINOR versions */\r
2080 +       err = -EINVAL;\r
2081 +       if(!supported_squashfs_filesystem(msblk, silent))\r
2082 +               goto *label;\r
2083 +\r
2084 +       /* Check the filesystem does not extend beyond the end of the\r
2085 +          block device */\r
2086 +       if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))\r
2087 +               goto *label;\r
2088 +\r
2089 +       /* Check the root inode for sanity */\r
2090 +       if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)\r
2091 +               goto *label;\r
2092 +\r
2093 +       TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));\r
2094 +       TRACE("Inodes are %scompressed\n",\r
2095 +                                       SQUASHFS_UNCOMPRESSED_INODES\r
2096 +                                       (sblk->flags) ? "un" : "");\r
2097 +       TRACE("Data is %scompressed\n",\r
2098 +                                       SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)\r
2099 +                                       ? "un" : "");\r
2100 +       TRACE("Check data is %s present in the filesystem\n",\r
2101 +                                       SQUASHFS_CHECK_DATA(sblk->flags) ?\r
2102 +                                       "" : "not");\r
2103 +       TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);\r
2104 +       TRACE("Block size %d\n", sblk->block_size);\r
2105 +       TRACE("Number of inodes %d\n", sblk->inodes);\r
2106 +       if (sblk->s_major > 1)\r
2107 +               TRACE("Number of fragments %d\n", sblk->fragments);\r
2108 +       TRACE("Number of uids %d\n", sblk->no_uids);\r
2109 +       TRACE("Number of gids %d\n", sblk->no_guids);\r
2110 +       TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);\r
2111 +       TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);\r
2112 +       if (sblk->s_major > 1)\r
2113 +               TRACE("sblk->fragment_table_start %llx\n",\r
2114 +                                       sblk->fragment_table_start);\r
2115 +       TRACE("sblk->uid_start %llx\n", sblk->uid_start);\r
2116 +\r
2117 +       s->s_flags |= MS_RDONLY;\r
2118 +       s->s_op = &squashfs_super_ops;\r
2119 +\r
2120 +       /* Init inode_table block pointer array */\r
2121 +       err = -ENOMEM;\r
2122 +       if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *\r
2123 +                                       SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {\r
2124 +               ERROR("Failed to allocate block cache\n");\r
2125 +               goto *label;\r
2126 +       }\r
2127 +       label = &&out_block_cache;\r
2128 +\r
2129 +       for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)\r
2130 +               msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;\r
2131 +\r
2132 +       msblk->next_cache = 0;\r
2133 +\r
2134 +       /* Allocate read_page block */\r
2135 +       if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {\r
2136 +               ERROR("Failed to allocate read_page block\n");\r
2137 +               goto *label;\r
2138 +       }\r
2139 +       label = &&out_read_page;\r
2140 +\r
2141 +       /* Allocate uid and gid tables */\r
2142 +       if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *\r
2143 +                                       sizeof(unsigned int), GFP_KERNEL))) {\r
2144 +               ERROR("Failed to allocate uid/gid table\n");\r
2145 +               goto *label;\r
2146 +       }\r
2147 +       label = &&out_uid;\r
2148 +       msblk->guid = msblk->uid + sblk->no_uids;\r
2149 +   \r
2150 +       dpri("swap %d\n", msblk->swap);\r
2151 +       err = -EINVAL;\r
2152 +       if (msblk->swap) {\r
2153 +               unsigned int suid[sblk->no_uids + sblk->no_guids];\r
2154 +\r
2155 +               if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,\r
2156 +                                       ((sblk->no_uids + sblk->no_guids) *\r
2157 +                                        sizeof(unsigned int)) |\r
2158 +                                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {\r
2159 +                       ERROR("unable to read uid/gid table\n");\r
2160 +                       goto *label;\r
2161 +               }\r
2162 +\r
2163 +               SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +\r
2164 +                       sblk->no_guids), (sizeof(unsigned int) * 8));\r
2165 +       } else\r
2166 +               if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,\r
2167 +                                       ((sblk->no_uids + sblk->no_guids) *\r
2168 +                                        sizeof(unsigned int)) |\r
2169 +                                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {\r
2170 +                       ERROR("unable to read uid/gid table\n");\r
2171 +                       goto *label;\r
2172 +               }\r
2173 +\r
2174 +\r
2175 +       if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))\r
2176 +               goto allocate_root;\r
2177 +\r
2178 +       err = -ENOMEM;\r
2179 +       if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *\r
2180 +                               SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {\r
2181 +               ERROR("Failed to allocate fragment block cache\n");\r
2182 +               goto *label;\r
2183 +       }\r
2184 +       label = &&out_fragment;\r
2185 +\r
2186 +       for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {\r
2187 +               msblk->fragment[i].locked = 0;\r
2188 +               msblk->fragment[i].block = SQUASHFS_INVALID_BLK;\r
2189 +               msblk->fragment[i].data = NULL;\r
2190 +       }\r
2191 +\r
2192 +       msblk->next_fragment = 0;\r
2193 +\r
2194 +       /* Allocate and read fragment index table */\r
2195 +       if (msblk->read_fragment_index_table(s) == 0)\r
2196 +               goto *label;\r
2197 +\r
2198 +       if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)\r
2199 +               goto allocate_root;\r
2200 +\r
2201 +       /* Allocate and read inode lookup table */\r
2202 +       if (read_inode_lookup_table(s) == 0)\r
2203 +               goto failed_mount;\r
2204 +\r
2205 +       s->s_op = &squashfs_export_super_ops;\r
2206 +       s->s_export_op = &squashfs_export_ops;\r
2207 +\r
2208 +allocate_root:\r
2209 +       dpri("alloate_root\n");\r
2210 +       root = new_inode(s);\r
2211 +       if ((msblk->read_inode)(root, sblk->root_inode) == 0) {\r
2212 +               iput(root);\r
2213 +               goto failed_mount;\r
2214 +       }\r
2215 +       insert_inode_hash(root);\r
2216 +\r
2217 +       if ((s->s_root = d_alloc_root(root)) == NULL) {\r
2218 +               ERROR("Root inode create failed\n");\r
2219 +               iput(root);\r
2220 +               goto failed_mount;\r
2221 +       }\r
2222 +\r
2223 +       TRACE("Leaving squashfs_read_super\n");\r
2224 +       return 0;\r
2225 +\r
2226 +failed_mount:\r
2227 +       kfree(msblk->inode_lookup_table);\r
2228 +       kfree(msblk->fragment_index);\r
2229 +       kfree(msblk->fragment_index_2);\r
2230 + out_fragment:\r
2231 +       kfree(msblk->fragment);\r
2232 + out_uid:\r
2233 +       kfree(msblk->uid);\r
2234 + out_read_page:\r
2235 +       kfree(msblk->read_page);\r
2236 + out_block_cache:\r
2237 +       kfree(msblk->block_cache);\r
2238 + out_fsinfo:\r
2239 +       kfree(s->s_fs_info);\r
2240 +       s->s_fs_info = NULL;\r
2241 + failure:\r
2242 +       return err;\r
2243 +}\r
2244 +\r
2245 +\r
2246 +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)\r
2247 +{\r
2248 +       struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;\r
2249 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
2250 +\r
2251 +       TRACE("Entered squashfs_statfs\n");\r
2252 +\r
2253 +       buf->f_type = sblk->s_magic;\r
2254 +       buf->f_bsize = sblk->block_size;\r
2255 +       buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;\r
2256 +       buf->f_bfree = buf->f_bavail = 0;\r
2257 +       buf->f_files = sblk->inodes;\r
2258 +       buf->f_ffree = 0;\r
2259 +       buf->f_namelen = SQUASHFS_NAME_LEN;\r
2260 +\r
2261 +       return 0;\r
2262 +}\r
2263 +\r
2264 +\r
2265 +static int squashfs_symlink_readpage(struct file *file, struct page *page)\r
2266 +{\r
2267 +       struct inode *inode = page->mapping->host;\r
2268 +       int index = page->index << PAGE_CACHE_SHIFT, length, bytes;\r
2269 +       long long block = SQUASHFS_I(inode)->start_block;\r
2270 +       int offset = SQUASHFS_I(inode)->offset;\r
2271 +       void *pageaddr = kmap(page);\r
2272 +\r
2273 +       TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "\r
2274 +                               "%llx, offset %x\n", page->index,\r
2275 +                               SQUASHFS_I(inode)->start_block,\r
2276 +                               SQUASHFS_I(inode)->offset);\r
2277 +\r
2278 +       for (length = 0; length < index; length += bytes) {\r
2279 +               if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,\r
2280 +                               block, offset, PAGE_CACHE_SIZE, &block,\r
2281 +                               &offset))) {\r
2282 +                       ERROR("Unable to read symbolic link [%llx:%x]\n", block,\r
2283 +                                       offset);\r
2284 +                       goto skip_read;\r
2285 +               }\r
2286 +       }\r
2287 +\r
2288 +       if (length != index) {\r
2289 +               ERROR("(squashfs_symlink_readpage) length != index\n");\r
2290 +               bytes = 0;\r
2291 +               goto skip_read;\r
2292 +       }\r
2293 +\r
2294 +       bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :\r
2295 +                                       i_size_read(inode) - length;\r
2296 +\r
2297 +       if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,\r
2298 +                                       offset, bytes, &block, &offset)))\r
2299 +               ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);\r
2300 +\r
2301 +skip_read:\r
2302 +       memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
2303 +       kunmap(page);\r
2304 +       flush_dcache_page(page);\r
2305 +       SetPageUptodate(page);\r
2306 +       unlock_page(page);\r
2307 +\r
2308 +       return 0;\r
2309 +}\r
2310 +\r
2311 +\r
2312 +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)\r
2313 +{\r
2314 +       struct meta_index *meta = NULL;\r
2315 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
2316 +       int i;\r
2317 +\r
2318 +       mutex_lock(&msblk->meta_index_mutex);\r
2319 +\r
2320 +       TRACE("locate_meta_index: index %d, offset %d\n", index, offset);\r
2321 +\r
2322 +       if(msblk->meta_index == NULL)\r
2323 +               goto not_allocated;\r
2324 +\r
2325 +       for (i = 0; i < SQUASHFS_META_NUMBER; i ++)\r
2326 +               if (msblk->meta_index[i].inode_number == inode->i_ino &&\r
2327 +                               msblk->meta_index[i].offset >= offset &&\r
2328 +                               msblk->meta_index[i].offset <= index &&\r
2329 +                               msblk->meta_index[i].locked == 0) {\r
2330 +                       TRACE("locate_meta_index: entry %d, offset %d\n", i,\r
2331 +                                       msblk->meta_index[i].offset);\r
2332 +                       meta = &msblk->meta_index[i];\r
2333 +                       offset = meta->offset;\r
2334 +               }\r
2335 +\r
2336 +       if (meta)\r
2337 +               meta->locked = 1;\r
2338 +\r
2339 +not_allocated:\r
2340 +       mutex_unlock(&msblk->meta_index_mutex);\r
2341 +\r
2342 +       return meta;\r
2343 +}\r
2344 +\r
2345 +\r
2346 +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)\r
2347 +{\r
2348 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
2349 +       struct meta_index *meta = NULL;\r
2350 +       int i;\r
2351 +\r
2352 +       mutex_lock(&msblk->meta_index_mutex);\r
2353 +\r
2354 +       TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);\r
2355 +\r
2356 +       if(msblk->meta_index == NULL) {\r
2357 +               if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *\r
2358 +                                       SQUASHFS_META_NUMBER, GFP_KERNEL))) {\r
2359 +                       ERROR("Failed to allocate meta_index\n");\r
2360 +                       goto failed;\r
2361 +               }\r
2362 +               for(i = 0; i < SQUASHFS_META_NUMBER; i++) {\r
2363 +                       msblk->meta_index[i].inode_number = 0;\r
2364 +                       msblk->meta_index[i].locked = 0;\r
2365 +               }\r
2366 +               msblk->next_meta_index = 0;\r
2367 +       }\r
2368 +\r
2369 +       for(i = SQUASHFS_META_NUMBER; i &&\r
2370 +                       msblk->meta_index[msblk->next_meta_index].locked; i --)\r
2371 +               msblk->next_meta_index = (msblk->next_meta_index + 1) %\r
2372 +                       SQUASHFS_META_NUMBER;\r
2373 +\r
2374 +       if(i == 0) {\r
2375 +               TRACE("empty_meta_index: failed!\n");\r
2376 +               goto failed;\r
2377 +       }\r
2378 +\r
2379 +       TRACE("empty_meta_index: returned meta entry %d, %p\n",\r
2380 +                       msblk->next_meta_index,\r
2381 +                       &msblk->meta_index[msblk->next_meta_index]);\r
2382 +\r
2383 +       meta = &msblk->meta_index[msblk->next_meta_index];\r
2384 +       msblk->next_meta_index = (msblk->next_meta_index + 1) %\r
2385 +                       SQUASHFS_META_NUMBER;\r
2386 +\r
2387 +       meta->inode_number = inode->i_ino;\r
2388 +       meta->offset = offset;\r
2389 +       meta->skip = skip;\r
2390 +       meta->entries = 0;\r
2391 +       meta->locked = 1;\r
2392 +\r
2393 +failed:\r
2394 +       mutex_unlock(&msblk->meta_index_mutex);\r
2395 +       return meta;\r
2396 +}\r
2397 +\r
2398 +\r
2399 +void release_meta_index(struct inode *inode, struct meta_index *meta)\r
2400 +{\r
2401 +       meta->locked = 0;\r
2402 +       smp_mb();\r
2403 +}\r
2404 +\r
2405 +\r
2406 +static int read_block_index(struct super_block *s, int blocks, char *block_list,\r
2407 +               long long *start_block, int *offset)\r
2408 +{\r
2409 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
2410 +       unsigned int *block_listp;\r
2411 +       int block = 0;\r
2412 +       \r
2413 +       if (msblk->swap) {\r
2414 +               char sblock_list[blocks << 2];\r
2415 +\r
2416 +               if (!squashfs_get_cached_block(s, sblock_list, *start_block,\r
2417 +                               *offset, blocks << 2, start_block, offset)) {\r
2418 +                       ERROR("Unable to read block list [%llx:%x]\n",\r
2419 +                               *start_block, *offset);\r
2420 +                       goto failure;\r
2421 +               }\r
2422 +               SQUASHFS_SWAP_INTS(((unsigned int *)block_list),\r
2423 +                               ((unsigned int *)sblock_list), blocks);\r
2424 +       } else\r
2425 +               if (!squashfs_get_cached_block(s, block_list, *start_block,\r
2426 +                               *offset, blocks << 2, start_block, offset)) {\r
2427 +                       ERROR("Unable to read block list [%llx:%x]\n",\r
2428 +                               *start_block, *offset);\r
2429 +                       goto failure;\r
2430 +               }\r
2431 +\r
2432 +       for (block_listp = (unsigned int *) block_list; blocks;\r
2433 +                               block_listp++, blocks --)\r
2434 +               block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);\r
2435 +\r
2436 +       return block;\r
2437 +\r
2438 +failure:\r
2439 +       return -1;\r
2440 +}\r
2441 +\r
2442 +\r
2443 +#define SIZE 256\r
2444 +\r
2445 +static inline int calculate_skip(int blocks) {\r
2446 +       int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);\r
2447 +       return skip >= 7 ? 7 : skip + 1;\r
2448 +}\r
2449 +\r
2450 +\r
2451 +static int get_meta_index(struct inode *inode, int index,\r
2452 +               long long *index_block, int *index_offset,\r
2453 +               long long *data_block, char *block_list)\r
2454 +{\r
2455 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
2456 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
2457 +       int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);\r
2458 +       int offset = 0;\r
2459 +       struct meta_index *meta;\r
2460 +       struct meta_entry *meta_entry;\r
2461 +       long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;\r
2462 +       int cur_offset = SQUASHFS_I(inode)->offset;\r
2463 +       long long cur_data_block = SQUASHFS_I(inode)->start_block;\r
2464 +       int i;\r
2465\r
2466 +       index /= SQUASHFS_META_INDEXES * skip;\r
2467 +\r
2468 +       while ( offset < index ) {\r
2469 +               meta = locate_meta_index(inode, index, offset + 1);\r
2470 +\r
2471 +               if (meta == NULL) {\r
2472 +                       if ((meta = empty_meta_index(inode, offset + 1,\r
2473 +                                                       skip)) == NULL)\r
2474 +                               goto all_done;\r
2475 +               } else {\r
2476 +                       if(meta->entries == 0)\r
2477 +                               goto failed;\r
2478 +                       offset = index < meta->offset + meta->entries ? index :\r
2479 +                               meta->offset + meta->entries - 1;\r
2480 +                       meta_entry = &meta->meta_entry[offset - meta->offset];\r
2481 +                       cur_index_block = meta_entry->index_block + sblk->inode_table_start;\r
2482 +                       cur_offset = meta_entry->offset;\r
2483 +                       cur_data_block = meta_entry->data_block;\r
2484 +                       TRACE("get_meta_index: offset %d, meta->offset %d, "\r
2485 +                               "meta->entries %d\n", offset, meta->offset,\r
2486 +                               meta->entries);\r
2487 +                       TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"\r
2488 +                               " data_block 0x%llx\n", cur_index_block,\r
2489 +                               cur_offset, cur_data_block);\r
2490 +               }\r
2491 +\r
2492 +               for (i = meta->offset + meta->entries; i <= index &&\r
2493 +                               i < meta->offset + SQUASHFS_META_ENTRIES; i++) {\r
2494 +                       int blocks = skip * SQUASHFS_META_INDEXES;\r
2495 +\r
2496 +                       while (blocks) {\r
2497 +                               int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :\r
2498 +                                       blocks;\r
2499 +                               int res = read_block_index(inode->i_sb, block,\r
2500 +                                       block_list, &cur_index_block,\r
2501 +                                       &cur_offset);\r
2502 +\r
2503 +                               if (res == -1)\r
2504 +                                       goto failed;\r
2505 +\r
2506 +                               cur_data_block += res;\r
2507 +                               blocks -= block;\r
2508 +                       }\r
2509 +\r
2510 +                       meta_entry = &meta->meta_entry[i - meta->offset];\r
2511 +                       meta_entry->index_block = cur_index_block - sblk->inode_table_start;\r
2512 +                       meta_entry->offset = cur_offset;\r
2513 +                       meta_entry->data_block = cur_data_block;\r
2514 +                       meta->entries ++;\r
2515 +                       offset ++;\r
2516 +               }\r
2517 +\r
2518 +               TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",\r
2519 +                               meta->offset, meta->entries);\r
2520 +\r
2521 +               release_meta_index(inode, meta);\r
2522 +       }\r
2523 +\r
2524 +all_done:\r
2525 +       *index_block = cur_index_block;\r
2526 +       *index_offset = cur_offset;\r
2527 +       *data_block = cur_data_block;\r
2528 +\r
2529 +       return offset * SQUASHFS_META_INDEXES * skip;\r
2530 +\r
2531 +failed:\r
2532 +       release_meta_index(inode, meta);\r
2533 +       return -1;\r
2534 +}\r
2535 +\r
2536 +\r
2537 +static long long read_blocklist(struct inode *inode, int index,\r
2538 +                               int readahead_blks, char *block_list,\r
2539 +                               unsigned short **block_p, unsigned int *bsize)\r
2540 +{\r
2541 +       long long block_ptr;\r
2542 +       int offset;\r
2543 +       long long block;\r
2544 +       int res = get_meta_index(inode, index, &block_ptr, &offset, &block,\r
2545 +               block_list);\r
2546 +\r
2547 +       TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"\r
2548 +                      " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,\r
2549 +                      block);\r
2550 +\r
2551 +       if(res == -1)\r
2552 +               goto failure;\r
2553 +\r
2554 +       index -= res;\r
2555 +\r
2556 +       while ( index ) {\r
2557 +               int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;\r
2558 +               int res = read_block_index(inode->i_sb, blocks, block_list,\r
2559 +                       &block_ptr, &offset);\r
2560 +               if (res == -1)\r
2561 +                       goto failure;\r
2562 +               block += res;\r
2563 +               index -= blocks;\r
2564 +       }\r
2565 +\r
2566 +       if (read_block_index(inode->i_sb, 1, block_list,\r
2567 +                       &block_ptr, &offset) == -1)\r
2568 +               goto failure;\r
2569 +       *bsize = *((unsigned int *) block_list);\r
2570 +\r
2571 +       return block;\r
2572 +\r
2573 +failure:\r
2574 +       return 0;\r
2575 +}\r
2576 +\r
2577 +\r
2578 +static int squashfs_readpage(struct file *file, struct page *page)\r
2579 +{\r
2580 +       struct inode *inode = page->mapping->host;\r
2581 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
2582 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
2583 +       unsigned char *block_list;\r
2584 +       long long block;\r
2585 +       unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;\r
2586 +       int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);\r
2587 +       void *pageaddr;\r
2588 +       struct squashfs_fragment_cache *fragment = NULL;\r
2589 +       char *data_ptr = msblk->read_page;\r
2590 +       \r
2591 +       int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;\r
2592 +       int start_index = page->index & ~mask;\r
2593 +       int end_index = start_index | mask;\r
2594 +\r
2595 +       TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",\r
2596 +                                       page->index,\r
2597 +                                       SQUASHFS_I(inode)->start_block);\r
2598 +\r
2599 +       if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {\r
2600 +               ERROR("Failed to allocate block_list\n");\r
2601 +               goto skip_read;\r
2602 +       }\r
2603 +\r
2604 +       if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>\r
2605 +                                       PAGE_CACHE_SHIFT))\r
2606 +               goto skip_read;\r
2607 +\r
2608 +       if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
2609 +                                       || index < (i_size_read(inode) >>\r
2610 +                                       sblk->block_log)) {\r
2611 +               if ((block = (msblk->read_blocklist)(inode, index, 1,\r
2612 +                                       block_list, NULL, &bsize)) == 0)\r
2613 +                       goto skip_read;\r
2614 +\r
2615 +               mutex_lock(&msblk->read_page_mutex);\r
2616 +               \r
2617 +               if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,\r
2618 +                                       block, bsize, NULL, sblk->block_size))) {\r
2619 +                       ERROR("Unable to read page, block %llx, size %x\n", block,\r
2620 +                                       bsize);\r
2621 +                       mutex_unlock(&msblk->read_page_mutex);\r
2622 +                       goto skip_read;\r
2623 +               }\r
2624 +       } else {\r
2625 +               if ((fragment = get_cached_fragment(inode->i_sb,\r
2626 +                                       SQUASHFS_I(inode)->\r
2627 +                                       u.s1.fragment_start_block,\r
2628 +                                       SQUASHFS_I(inode)->u.s1.fragment_size))\r
2629 +                                       == NULL) {\r
2630 +                       ERROR("Unable to read page, block %llx, size %x\n",\r
2631 +                                       SQUASHFS_I(inode)->\r
2632 +                                       u.s1.fragment_start_block,\r
2633 +                                       (int) SQUASHFS_I(inode)->\r
2634 +                                       u.s1.fragment_size);\r
2635 +                       goto skip_read;\r
2636 +               }\r
2637 +               bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +\r
2638 +                                       (i_size_read(inode) & (sblk->block_size\r
2639 +                                       - 1));\r
2640 +               byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;\r
2641 +               data_ptr = fragment->data;\r
2642 +       }\r
2643 +\r
2644 +       for (i = start_index; i <= end_index && byte_offset < bytes;\r
2645 +                                       i++, byte_offset += PAGE_CACHE_SIZE) {\r
2646 +               struct page *push_page;\r
2647 +               int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?\r
2648 +                                       PAGE_CACHE_SIZE : bytes - byte_offset;\r
2649 +\r
2650 +               TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",\r
2651 +                                       bytes, i, byte_offset, avail);\r
2652 +\r
2653 +               push_page = (i == page->index) ? page :\r
2654 +                       grab_cache_page_nowait(page->mapping, i);\r
2655 +\r
2656 +               if (!push_page)\r
2657 +                       continue;\r
2658 +\r
2659 +               if (PageUptodate(push_page))\r
2660 +                       goto skip_page;\r
2661 +\r
2662 +               pageaddr = kmap_atomic(push_page, KM_USER0);\r
2663 +               memcpy(pageaddr, data_ptr + byte_offset, avail);\r
2664 +               memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);\r
2665 +               kunmap_atomic(pageaddr, KM_USER0);\r
2666 +               flush_dcache_page(push_page);\r
2667 +               SetPageUptodate(push_page);\r
2668 +skip_page:\r
2669 +               unlock_page(push_page);\r
2670 +               if(i != page->index)\r
2671 +                       page_cache_release(push_page);\r
2672 +       }\r
2673 +\r
2674 +       if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
2675 +                                       || index < (i_size_read(inode) >>\r
2676 +                                       sblk->block_log))\r
2677 +               mutex_unlock(&msblk->read_page_mutex);\r
2678 +       else\r
2679 +               release_cached_fragment(msblk, fragment);\r
2680 +\r
2681 +       kfree(block_list);\r
2682 +       return 0;\r
2683 +\r
2684 +skip_read:\r
2685 +       pageaddr = kmap_atomic(page, KM_USER0);\r
2686 +       memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
2687 +       kunmap_atomic(pageaddr, KM_USER0);\r
2688 +       flush_dcache_page(page);\r
2689 +       SetPageUptodate(page);\r
2690 +       unlock_page(page);\r
2691 +\r
2692 +       kfree(block_list);\r
2693 +       return 0;\r
2694 +}\r
2695 +\r
2696 +\r
2697 +static int squashfs_readpage4K(struct file *file, struct page *page)\r
2698 +{\r
2699 +       struct inode *inode = page->mapping->host;\r
2700 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;\r
2701 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
2702 +       unsigned char *block_list;\r
2703 +       long long block;\r
2704 +       unsigned int bsize, bytes = 0;\r
2705 +       void *pageaddr;\r
2706 +       \r
2707 +       TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",\r
2708 +                                       page->index,\r
2709 +                                       SQUASHFS_I(inode)->start_block);\r
2710 +\r
2711 +       if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>\r
2712 +                                       PAGE_CACHE_SHIFT)) {\r
2713 +               block_list = NULL;\r
2714 +               goto skip_read;\r
2715 +       }\r
2716 +\r
2717 +       if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {\r
2718 +               ERROR("Failed to allocate block_list\n");\r
2719 +               goto skip_read;\r
2720 +       }\r
2721 +\r
2722 +       if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK\r
2723 +                                       || page->index < (i_size_read(inode) >>\r
2724 +                                       sblk->block_log)) {\r
2725 +               block = (msblk->read_blocklist)(inode, page->index, 1,\r
2726 +                                       block_list, NULL, &bsize);\r
2727 +               if(block == 0)\r
2728 +                       goto skip_read;\r
2729 +\r
2730 +               mutex_lock(&msblk->read_page_mutex);\r
2731 +               bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,\r
2732 +                                       bsize, NULL, sblk->block_size);\r
2733 +               if (bytes) {\r
2734 +                       pageaddr = kmap_atomic(page, KM_USER0);\r
2735 +                       memcpy(pageaddr, msblk->read_page, bytes);\r
2736 +                       kunmap_atomic(pageaddr, KM_USER0);\r
2737 +               } else\r
2738 +                       ERROR("Unable to read page, block %llx, size %x\n",\r
2739 +                                       block, bsize);\r
2740 +               mutex_unlock(&msblk->read_page_mutex);\r
2741 +       } else {\r
2742 +               struct squashfs_fragment_cache *fragment =\r
2743 +                       get_cached_fragment(inode->i_sb,\r
2744 +                                       SQUASHFS_I(inode)->\r
2745 +                                       u.s1.fragment_start_block,\r
2746 +                                       SQUASHFS_I(inode)-> u.s1.fragment_size);\r
2747 +               if (fragment) {\r
2748 +                       bytes = i_size_read(inode) & (sblk->block_size - 1);\r
2749 +                       pageaddr = kmap_atomic(page, KM_USER0);\r
2750 +                       memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->\r
2751 +                                       u.s1.fragment_offset, bytes);\r
2752 +                       kunmap_atomic(pageaddr, KM_USER0);\r
2753 +                       release_cached_fragment(msblk, fragment);\r
2754 +               } else\r
2755 +                       ERROR("Unable to read page, block %llx, size %x\n",\r
2756 +                                       SQUASHFS_I(inode)->\r
2757 +                                       u.s1.fragment_start_block, (int)\r
2758 +                                       SQUASHFS_I(inode)-> u.s1.fragment_size);\r
2759 +       }\r
2760 +\r
2761 +skip_read:\r
2762 +       pageaddr = kmap_atomic(page, KM_USER0);\r
2763 +       memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);\r
2764 +       kunmap_atomic(pageaddr, KM_USER0);\r
2765 +       flush_dcache_page(page);\r
2766 +       SetPageUptodate(page);\r
2767 +       unlock_page(page);\r
2768 +\r
2769 +       kfree(block_list);\r
2770 +       return 0;\r
2771 +}\r
2772 +\r
2773 +\r
2774 +static int get_dir_index_using_offset(struct super_block *s, long long \r
2775 +                               *next_block, unsigned int *next_offset,\r
2776 +                               long long index_start,\r
2777 +                               unsigned int index_offset, int i_count,\r
2778 +                               long long f_pos)\r
2779 +{\r
2780 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
2781 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
2782 +       int i, length = 0;\r
2783 +       struct squashfs_dir_index index;\r
2784 +\r
2785 +       TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",\r
2786 +                                       i_count, (unsigned int) f_pos);\r
2787 +\r
2788 +       f_pos =- 3;\r
2789 +       if (f_pos == 0)\r
2790 +               goto finish;\r
2791 +\r
2792 +       for (i = 0; i < i_count; i++) {\r
2793 +               if (msblk->swap) {\r
2794 +                       struct squashfs_dir_index sindex;\r
2795 +                       squashfs_get_cached_block(s, (char *) &sindex,\r
2796 +                                       index_start, index_offset,\r
2797 +                                       sizeof(sindex), &index_start,\r
2798 +                                       &index_offset);\r
2799 +                       SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);\r
2800 +               } else\r
2801 +                       squashfs_get_cached_block(s, (char *) &index,\r
2802 +                                       index_start, index_offset,\r
2803 +                                       sizeof(index), &index_start,\r
2804 +                                       &index_offset);\r
2805 +\r
2806 +               if (index.index > f_pos)\r
2807 +                       break;\r
2808 +\r
2809 +               squashfs_get_cached_block(s, NULL, index_start, index_offset,\r
2810 +                                       index.size + 1, &index_start,\r
2811 +                                       &index_offset);\r
2812 +\r
2813 +               length = index.index;\r
2814 +               *next_block = index.start_block + sblk->directory_table_start;\r
2815 +       }\r
2816 +\r
2817 +       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
2818 +\r
2819 +finish:\r
2820 +       return length + 3;\r
2821 +}\r
2822 +\r
2823 +\r
2824 +static int get_dir_index_using_name(struct super_block *s, long long\r
2825 +                               *next_block, unsigned int *next_offset,\r
2826 +                               long long index_start,\r
2827 +                               unsigned int index_offset, int i_count,\r
2828 +                               const char *name, int size)\r
2829 +{\r
2830 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
2831 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
2832 +       int i, length = 0;\r
2833 +       struct squashfs_dir_index *index;\r
2834 +       char *str;\r
2835 +\r
2836 +       TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);\r
2837 +\r
2838 +       if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +\r
2839 +               (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {\r
2840 +               ERROR("Failed to allocate squashfs_dir_index\n");\r
2841 +               goto failure;\r
2842 +       }\r
2843 +\r
2844 +       index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);\r
2845 +       strncpy(str, name, size);\r
2846 +       str[size] = '\0';\r
2847 +\r
2848 +       for (i = 0; i < i_count; i++) {\r
2849 +               if (msblk->swap) {\r
2850 +                       struct squashfs_dir_index sindex;\r
2851 +                       squashfs_get_cached_block(s, (char *) &sindex,\r
2852 +                                       index_start, index_offset,\r
2853 +                                       sizeof(sindex), &index_start,\r
2854 +                                       &index_offset);\r
2855 +                       SQUASHFS_SWAP_DIR_INDEX(index, &sindex);\r
2856 +               } else\r
2857 +                       squashfs_get_cached_block(s, (char *) index,\r
2858 +                                       index_start, index_offset,\r
2859 +                                       sizeof(struct squashfs_dir_index),\r
2860 +                                       &index_start, &index_offset);\r
2861 +\r
2862 +               squashfs_get_cached_block(s, index->name, index_start,\r
2863 +                                       index_offset, index->size + 1,\r
2864 +                                       &index_start, &index_offset);\r
2865 +\r
2866 +               index->name[index->size + 1] = '\0';\r
2867 +\r
2868 +               if (strcmp(index->name, str) > 0)\r
2869 +                       break;\r
2870 +\r
2871 +               length = index->index;\r
2872 +               *next_block = index->start_block + sblk->directory_table_start;\r
2873 +       }\r
2874 +\r
2875 +       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
2876 +       kfree(str);\r
2877 +failure:\r
2878 +       return length + 3;\r
2879 +}\r
2880 +\r
2881 +               \r
2882 +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)\r
2883 +{\r
2884 +       struct inode *i = file->f_dentry->d_inode;\r
2885 +       struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
2886 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
2887 +       long long next_block = SQUASHFS_I(i)->start_block +\r
2888 +               sblk->directory_table_start;\r
2889 +       int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
2890 +               dir_count;\r
2891 +       struct squashfs_dir_header dirh;\r
2892 +       struct squashfs_dir_entry *dire;\r
2893 +\r
2894 +       TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);\r
2895 +\r
2896 +       if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
2897 +               SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
2898 +               ERROR("Failed to allocate squashfs_dir_entry\n");\r
2899 +               goto finish;\r
2900 +       }\r
2901 +\r
2902 +       while(file->f_pos < 3) {\r
2903 +               char *name;\r
2904 +               int size, i_ino;\r
2905 +\r
2906 +               if(file->f_pos == 0) {\r
2907 +                       name = ".";\r
2908 +                       size = 1;\r
2909 +                       i_ino = i->i_ino;\r
2910 +               } else {\r
2911 +                       name = "..";\r
2912 +                       size = 2;\r
2913 +                       i_ino = SQUASHFS_I(i)->u.s2.parent_inode;\r
2914 +               }\r
2915 +               TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",\r
2916 +                               (unsigned int) dirent, name, size, (int)\r
2917 +                               file->f_pos, i_ino,\r
2918 +                               squashfs_filetype_table[1]);\r
2919 +\r
2920 +               if (filldir(dirent, name, size,\r
2921 +                               file->f_pos, i_ino,\r
2922 +                               squashfs_filetype_table[1]) < 0) {\r
2923 +                               TRACE("Filldir returned less than 0\n");\r
2924 +                               goto finish;\r
2925 +               }\r
2926 +               file->f_pos += size;\r
2927 +       }\r
2928 +\r
2929 +       length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,\r
2930 +                               SQUASHFS_I(i)->u.s2.directory_index_start,\r
2931 +                               SQUASHFS_I(i)->u.s2.directory_index_offset,\r
2932 +                               SQUASHFS_I(i)->u.s2.directory_index_count,\r
2933 +                               file->f_pos);\r
2934 +\r
2935 +       while (length < i_size_read(i)) {\r
2936 +               /* read directory header */\r
2937 +               if (msblk->swap) {\r
2938 +                       struct squashfs_dir_header sdirh;\r
2939 +                       \r
2940 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
2941 +                                       next_block, next_offset, sizeof(sdirh),\r
2942 +                                       &next_block, &next_offset))\r
2943 +                               goto failed_read;\r
2944 +\r
2945 +                       length += sizeof(sdirh);\r
2946 +                       SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);\r
2947 +               } else {\r
2948 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
2949 +                                       next_block, next_offset, sizeof(dirh),\r
2950 +                                       &next_block, &next_offset))\r
2951 +                               goto failed_read;\r
2952 +\r
2953 +                       length += sizeof(dirh);\r
2954 +               }\r
2955 +\r
2956 +               dir_count = dirh.count + 1;\r
2957 +               while (dir_count--) {\r
2958 +                       if (msblk->swap) {\r
2959 +                               struct squashfs_dir_entry sdire;\r
2960 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
2961 +                                               &sdire, next_block, next_offset,\r
2962 +                                               sizeof(sdire), &next_block,\r
2963 +                                               &next_offset))\r
2964 +                                       goto failed_read;\r
2965 +                               \r
2966 +                               length += sizeof(sdire);\r
2967 +                               SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);\r
2968 +                       } else {\r
2969 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
2970 +                                               dire, next_block, next_offset,\r
2971 +                                               sizeof(*dire), &next_block,\r
2972 +                                               &next_offset))\r
2973 +                                       goto failed_read;\r
2974 +\r
2975 +                               length += sizeof(*dire);\r
2976 +                       }\r
2977 +\r
2978 +                       if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
2979 +                                               next_block, next_offset,\r
2980 +                                               dire->size + 1, &next_block,\r
2981 +                                               &next_offset))\r
2982 +                               goto failed_read;\r
2983 +\r
2984 +                       length += dire->size + 1;\r
2985 +\r
2986 +                       if (file->f_pos >= length)\r
2987 +                               continue;\r
2988 +\r
2989 +                       dire->name[dire->size + 1] = '\0';\r
2990 +\r
2991 +                       TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",\r
2992 +                                       (unsigned int) dirent, dire->name,\r
2993 +                                       dire->size + 1, (int) file->f_pos,\r
2994 +                                       dirh.start_block, dire->offset,\r
2995 +                                       dirh.inode_number + dire->inode_number,\r
2996 +                                       squashfs_filetype_table[dire->type]);\r
2997 +\r
2998 +                       if (filldir(dirent, dire->name, dire->size + 1,\r
2999 +                                       file->f_pos,\r
3000 +                                       dirh.inode_number + dire->inode_number,\r
3001 +                                       squashfs_filetype_table[dire->type])\r
3002 +                                       < 0) {\r
3003 +                               TRACE("Filldir returned less than 0\n");\r
3004 +                               goto finish;\r
3005 +                       }\r
3006 +                       file->f_pos = length;\r
3007 +               }\r
3008 +       }\r
3009 +\r
3010 +finish:\r
3011 +       kfree(dire);\r
3012 +       return 0;\r
3013 +\r
3014 +failed_read:\r
3015 +       ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
3016 +               next_offset);\r
3017 +       kfree(dire);\r
3018 +       return 0;\r
3019 +}\r
3020 +\r
3021 +\r
3022 +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,\r
3023 +                               struct nameidata *nd)\r
3024 +{\r
3025 +       const unsigned char *name = dentry->d_name.name;\r
3026 +       int len = dentry->d_name.len;\r
3027 +       struct inode *inode = NULL;\r
3028 +       struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
3029 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
3030 +       long long next_block = SQUASHFS_I(i)->start_block +\r
3031 +                               sblk->directory_table_start;\r
3032 +       int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
3033 +                               dir_count;\r
3034 +       struct squashfs_dir_header dirh;\r
3035 +       struct squashfs_dir_entry *dire;\r
3036 +\r
3037 +       TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);\r
3038 +\r
3039 +       if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
3040 +               SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
3041 +               ERROR("Failed to allocate squashfs_dir_entry\n");\r
3042 +               goto exit_lookup;\r
3043 +       }\r
3044 +\r
3045 +       if (len > SQUASHFS_NAME_LEN)\r
3046 +               goto exit_lookup;\r
3047 +\r
3048 +       length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,\r
3049 +                               SQUASHFS_I(i)->u.s2.directory_index_start,\r
3050 +                               SQUASHFS_I(i)->u.s2.directory_index_offset,\r
3051 +                               SQUASHFS_I(i)->u.s2.directory_index_count, name,\r
3052 +                               len);\r
3053 +\r
3054 +       while (length < i_size_read(i)) {\r
3055 +               /* read directory header */\r
3056 +               if (msblk->swap) {\r
3057 +                       struct squashfs_dir_header sdirh;\r
3058 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
3059 +                                       next_block, next_offset, sizeof(sdirh),\r
3060 +                                       &next_block, &next_offset))\r
3061 +                               goto failed_read;\r
3062 +\r
3063 +                       length += sizeof(sdirh);\r
3064 +                       SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);\r
3065 +               } else {\r
3066 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
3067 +                                       next_block, next_offset, sizeof(dirh),\r
3068 +                                       &next_block, &next_offset))\r
3069 +                               goto failed_read;\r
3070 +\r
3071 +                       length += sizeof(dirh);\r
3072 +               }\r
3073 +\r
3074 +               dir_count = dirh.count + 1;\r
3075 +               while (dir_count--) {\r
3076 +                       if (msblk->swap) {\r
3077 +                               struct squashfs_dir_entry sdire;\r
3078 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
3079 +                                               &sdire, next_block,next_offset,\r
3080 +                                               sizeof(sdire), &next_block,\r
3081 +                                               &next_offset))\r
3082 +                                       goto failed_read;\r
3083 +                               \r
3084 +                               length += sizeof(sdire);\r
3085 +                               SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);\r
3086 +                       } else {\r
3087 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
3088 +                                               dire, next_block,next_offset,\r
3089 +                                               sizeof(*dire), &next_block,\r
3090 +                                               &next_offset))\r
3091 +                                       goto failed_read;\r
3092 +\r
3093 +                               length += sizeof(*dire);\r
3094 +                       }\r
3095 +\r
3096 +                       if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
3097 +                                       next_block, next_offset, dire->size + 1,\r
3098 +                                       &next_block, &next_offset))\r
3099 +                               goto failed_read;\r
3100 +\r
3101 +                       length += dire->size + 1;\r
3102 +\r
3103 +                       if (name[0] < dire->name[0])\r
3104 +                               goto exit_lookup;\r
3105 +\r
3106 +                       if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {\r
3107 +                               squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,\r
3108 +                                                               dire->offset);\r
3109 +\r
3110 +                               TRACE("calling squashfs_iget for directory "\r
3111 +                                       "entry %s, inode %x:%x, %d\n", name,\r
3112 +                                       dirh.start_block, dire->offset,\r
3113 +                                       dirh.inode_number + dire->inode_number);\r
3114 +\r
3115 +                               inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);\r
3116 +\r
3117 +                               goto exit_lookup;\r
3118 +                       }\r
3119 +               }\r
3120 +       }\r
3121 +\r
3122 +exit_lookup:\r
3123 +       kfree(dire);\r
3124 +       if (inode)\r
3125 +               return d_splice_alias(inode, dentry);\r
3126 +       d_add(dentry, inode);\r
3127 +       return ERR_PTR(0);\r
3128 +\r
3129 +failed_read:\r
3130 +       ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
3131 +               next_offset);\r
3132 +       goto exit_lookup;\r
3133 +}\r
3134 +\r
3135 +\r
3136 +static int squashfs_remount(struct super_block *s, int *flags, char *data)\r
3137 +{\r
3138 +       *flags |= MS_RDONLY;\r
3139 +       return 0;\r
3140 +}\r
3141 +\r
3142 +\r
3143 +static void squashfs_put_super(struct super_block *s)\r
3144 +{\r
3145 +       int i;\r
3146 +\r
3147 +       if (s->s_fs_info) {\r
3148 +               struct squashfs_sb_info *sbi = s->s_fs_info;\r
3149 +               if (sbi->block_cache)\r
3150 +                       for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)\r
3151 +                               if (sbi->block_cache[i].block !=\r
3152 +                                                       SQUASHFS_INVALID_BLK)\r
3153 +                                       kfree(sbi->block_cache[i].data);\r
3154 +               if (sbi->fragment)\r
3155 +                       for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) \r
3156 +                               SQUASHFS_FREE(sbi->fragment[i].data);\r
3157 +               kfree(sbi->fragment);\r
3158 +               kfree(sbi->block_cache);\r
3159 +               kfree(sbi->read_page);\r
3160 +               kfree(sbi->uid);\r
3161 +               kfree(sbi->fragment_index);\r
3162 +               kfree(sbi->fragment_index_2);\r
3163 +               kfree(sbi->meta_index);\r
3164 +               kfree(s->s_fs_info);\r
3165 +               s->s_fs_info = NULL;\r
3166 +       }\r
3167 +}\r
3168 +\r
3169 +\r
3170 +static int squashfs_get_sb(struct file_system_type *fs_type, int flags,\r
3171 +                               const char *dev_name, void *data,\r
3172 +                               struct vfsmount *mnt)\r
3173 +{\r
3174 +       return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,\r
3175 +                               mnt);\r
3176 +}\r
3177 +\r
3178 +\r
3179 +static void free_sqlzma(void)\r
3180 +{\r
3181 +       int cpu;\r
3182 +       struct sqlzma *p;\r
3183 +\r
3184 +       for_each_online_cpu(cpu) {\r
3185 +               p = per_cpu(sqlzma, cpu);\r
3186 +               if (p) {\r
3187 +#ifdef KeepPreemptive\r
3188 +                       mutex_destroy(&p->mtx);\r
3189 +#endif\r
3190 +                       sqlzma_fin(&p->un);\r
3191 +                       kfree(p);\r
3192 +               }\r
3193 +       }\r
3194 +}\r
3195 +\r
3196 +static int __init init_squashfs_fs(void)\r
3197 +{\r
3198 +       struct sqlzma *p;\r
3199 +       int cpu;\r
3200 +       int err = init_inodecache();\r
3201 +       if (err)\r
3202 +               goto out;\r
3203 +\r
3204 +       for_each_online_cpu(cpu) {\r
3205 +               dpri("%d: %p\n", cpu, per_cpu(sqlzma, cpu));\r
3206 +               err = -ENOMEM;\r
3207 +               p = kmalloc(sizeof(struct sqlzma), GFP_KERNEL);\r
3208 +               if (p) {\r
3209 +#ifdef KeepPreemptive\r
3210 +                       mutex_init(&p->mtx);\r
3211 +#endif\r
3212 +                       err = sqlzma_init(&p->un, 1, 0);\r
3213 +                       if (unlikely(err)) {\r
3214 +                               ERROR("Failed to intialize uncompress workspace\n");\r
3215 +                               break;\r
3216 +                       }\r
3217 +                       per_cpu(sqlzma, cpu) = p;\r
3218 +                       err = 0;\r
3219 +               } else\r
3220 +                       break;\r
3221 +       }\r
3222 +       if (unlikely(err)) {\r
3223 +               free_sqlzma();\r
3224 +               goto out;\r
3225 +       }\r
3226 +\r
3227 +       printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "\r
3228 +               "Phillip Lougher\n"\r
3229 +               "squashfs: LZMA suppport for slax.org by jro\n");\r
3230 +\r
3231 +       if ((err = register_filesystem(&squashfs_fs_type))) {\r
3232 +               free_sqlzma();\r
3233 +               destroy_inodecache();\r
3234 +       }\r
3235 +\r
3236 +out:\r
3237 +       return err;\r
3238 +}\r
3239 +\r
3240 +\r
3241 +static void __exit exit_squashfs_fs(void)\r
3242 +{\r
3243 +       unregister_filesystem(&squashfs_fs_type);\r
3244 +       free_sqlzma();\r
3245 +       destroy_inodecache();\r
3246 +}\r
3247 +\r
3248 +\r
3249 +static struct kmem_cache * squashfs_inode_cachep;\r
3250 +\r
3251 +\r
3252 +static struct inode *squashfs_alloc_inode(struct super_block *sb)\r
3253 +{\r
3254 +       struct squashfs_inode_info *ei;\r
3255 +       ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);\r
3256 +       if (!ei)\r
3257 +               return NULL;\r
3258 +       return &ei->vfs_inode;\r
3259 +}\r
3260 +\r
3261 +\r
3262 +static void squashfs_destroy_inode(struct inode *inode)\r
3263 +{\r
3264 +       kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));\r
3265 +}\r
3266 +\r
3267 +\r
3268 +static void init_once(struct kmem_cache * cachep, void * foo)\r
3269 +{\r
3270 +       struct squashfs_inode_info *ei = foo;\r
3271 +               inode_init_once(&ei->vfs_inode);\r
3272 +}\r
3273\r
3274 +\r
3275 +static int __init init_inodecache(void)\r
3276 +{\r
3277 +       squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",\r
3278 +            sizeof(struct squashfs_inode_info),\r
3279 +            0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,\r
3280 +            init_once);\r
3281 +       if (squashfs_inode_cachep == NULL)\r
3282 +               return -ENOMEM;\r
3283 +       return 0;\r
3284 +}\r
3285 +\r
3286 +\r
3287 +static void destroy_inodecache(void)\r
3288 +{\r
3289 +       kmem_cache_destroy(squashfs_inode_cachep);\r
3290 +}\r
3291 +\r
3292 +\r
3293 +module_init(init_squashfs_fs);\r
3294 +module_exit(exit_squashfs_fs);\r
3295 +MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem, and LZMA suppport for slax.org");\r
3296 +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>, and LZMA suppport for slax.org by jro");\r
3297 +MODULE_LICENSE("GPL");\r
3298 diff -urN linux-2.6.23/fs/squashfs/module.c linux-2.6.23.sqlzma/fs/squashfs/module.c\r
3299 --- linux-2.6.23/fs/squashfs/module.c   1969-12-31 19:00:00.000000000 -0500\r
3300 +++ linux-2.6.23.sqlzma/fs/squashfs/module.c    2007-10-14 12:58:25.000000000 -0400\r
3301 @@ -0,0 +1,36 @@\r
3302 +\r
3303 +/*\r
3304 + * Copyright (C) 2006 Junjiro Okajima\r
3305 + * Copyright (C) 2006 Tomas Matejicek, slax.org\r
3306 + *\r
3307 + * LICENSE follows the described one in lzma.txt.\r
3308 + */\r
3309 +\r
3310 +/* $Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $ */\r
3311 +\r
3312 +#include <linux/init.h>\r
3313 +#include <linux/module.h>\r
3314 +\r
3315 +#include "LzmaDecode.c"\r
3316 +\r
3317 +EXPORT_SYMBOL(LzmaDecodeProperties);\r
3318 +EXPORT_SYMBOL(LzmaDecode);\r
3319 +\r
3320 +#if 0\r
3321 +static int __init unlzma_init(void)\r
3322 +{\r
3323 +       return 0;\r
3324 +}\r
3325 +\r
3326 +static void __exit unlzma_exit(void)\r
3327 +{\r
3328 +}\r
3329 +\r
3330 +module_init(unlzma_init);\r
3331 +module_exit(unlzma_exit);\r
3332 +#endif\r
3333 +\r
3334 +MODULE_LICENSE("GPL");\r
3335 +MODULE_VERSION("$Id: module.c,v 1.5 2006/11/27 03:54:58 jro Exp $");\r
3336 +MODULE_DESCRIPTION("LZMA uncompress. "\r
3337 +                  "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");\r
3338 diff -urN linux-2.6.23/fs/squashfs/sqlzma.h linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h\r
3339 --- linux-2.6.23/fs/squashfs/sqlzma.h   1969-12-31 19:00:00.000000000 -0500\r
3340 +++ linux-2.6.23.sqlzma/fs/squashfs/sqlzma.h    2007-10-14 13:07:12.000000000 -0400\r
3341 @@ -0,0 +1,79 @@\r
3342 +/*\r
3343 + * Copyright (C) 2006 Junjiro Okajima\r
3344 + * Copyright (C) 2006 Tomas Matejicek, slax.org\r
3345 + *\r
3346 + * LICENSE follows the described one in lzma.\r
3347 + */\r
3348 +\r
3349 +/* $Id: sqlzma.h,v 1.13 2007/01/07 15:12:48 jro Exp $ */\r
3350 +\r
3351 +#ifndef __sqlzma_h__\r
3352 +#define __sqlzma_h__\r
3353 +\r
3354 +#ifndef __KERNEL__\r
3355 +#include <stdlib.h>\r
3356 +#include <string.h>\r
3357 +#include <zlib.h>\r
3358 +#ifdef _REENTRANT\r
3359 +#include <pthread.h>\r
3360 +#endif\r
3361 +#else\r
3362 +#include <linux/zlib.h>\r
3363 +#endif\r
3364 +#define _7ZIP_BYTE_DEFINED\r
3365 +\r
3366 +/*\r
3367 + * detect the compression method automatically by the first byte of compressed\r
3368 + * data.\r
3369 + * according to rfc1950, the first byte of zlib compression must be 0x?8.\r
3370 + */\r
3371 +#define is_lzma(c)     (c == 0x5d)\r
3372 +\r
3373 +/* ---------------------------------------------------------------------- */\r
3374 +\r
3375 +#ifdef __cplusplus\r
3376 +extern "C" {\r
3377 +#endif\r
3378 +\r
3379 +#ifndef __KERNEL__\r
3380 +/* for mksquashfs only */\r
3381 +int sqlzma_cm(int lzma, z_stream *stream, Bytef *next_in, uInt avail_in,\r
3382 +             Bytef *next_out, uInt avail_out);\r
3383 +#endif\r
3384 +\r
3385 +/* ---------------------------------------------------------------------- */\r
3386 +/*\r
3387 + * Three patterns for sqlzma uncompression. very dirty code.\r
3388 + * - kernel space (squashfs kernel module)\r
3389 + * - user space with pthread (mksquashfs)\r
3390 + * - user space without pthread (unsquashfs)\r
3391 + */\r
3392 +\r
3393 +struct sized_buf {\r
3394 +       unsigned int    sz;\r
3395 +       unsigned char   *buf;\r
3396 +};\r
3397 +\r
3398 +enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST};\r
3399 +struct sqlzma_un {\r
3400 +       int                     un_lzma;\r
3401 +       struct sized_buf        un_a[SQUN_LAST];\r
3402 +       unsigned char           un_prob[31960]; /* unlzma 64KB */\r
3403 +       z_stream                un_stream;\r
3404 +#define un_cmbuf       un_stream.next_in\r
3405 +#define un_cmlen       un_stream.avail_in\r
3406 +#define un_resbuf      un_stream.next_out\r
3407 +#define un_resroom     un_stream.avail_out\r
3408 +#define un_reslen      un_stream.total_out\r
3409 +};\r
3410 +\r
3411 +int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz);\r
3412 +int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst);\r
3413 +void sqlzma_fin(struct sqlzma_un *un);\r
3414 +\r
3415 +/* ---------------------------------------------------------------------- */\r
3416 +\r
3417 +#ifdef __cplusplus\r
3418 +};\r
3419 +#endif\r
3420 +#endif\r
3421 diff -urN linux-2.6.23/fs/squashfs/sqmagic.h linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h\r
3422 --- linux-2.6.23/fs/squashfs/sqmagic.h  1969-12-31 19:00:00.000000000 -0500\r
3423 +++ linux-2.6.23.sqlzma/fs/squashfs/sqmagic.h   2007-10-14 14:32:24.000000000 -0400\r
3424 @@ -0,0 +1,17 @@\r
3425 +/*\r
3426 + * Copyright (C) 2006 Junjiro Okajima\r
3427 + * Copyright (C) 2006 Tomas Matejicek, slax.org\r
3428 + *\r
3429 + * LICENSE must follow the one in squashfs.\r
3430 + */\r
3431 +\r
3432 +/* $Id: sqmagic.h,v 1.2 2006/11/27 03:54:58 jro Exp $ */\r
3433 +\r
3434 +#ifndef __sqmagic_h__\r
3435 +#define __sqmagic_h__\r
3436 +\r
3437 +/* see SQUASHFS_MAGIC in squashfs_fs.h */\r
3438 +#define SQUASHFS_MAGIC_LZMA            0x71736873\r
3439 +#define SQUASHFS_MAGIC_LZMA_SWAP       0x73687371\r
3440 +\r
3441 +#endif\r
3442 diff -urN linux-2.6.23/fs/squashfs/squashfs.h linux-2.6.23.sqlzma/fs/squashfs/squashfs.h\r
3443 --- linux-2.6.23/fs/squashfs/squashfs.h 1969-12-31 19:00:00.000000000 -0500\r
3444 +++ linux-2.6.23.sqlzma/fs/squashfs/squashfs.h  2007-10-14 10:24:31.000000000 -0400\r
3445 @@ -0,0 +1,87 @@\r
3446 +/*\r
3447 + * Squashfs - a compressed read only filesystem for Linux\r
3448 + *\r
3449 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
3450 + * Phillip Lougher <phillip@lougher.org.uk>\r
3451 + *\r
3452 + * This program is free software; you can redistribute it and/or\r
3453 + * modify it under the terms of the GNU General Public License\r
3454 + * as published by the Free Software Foundation; either version 2,\r
3455 + * or (at your option) any later version.\r
3456 + *\r
3457 + * This program is distributed in the hope that it will be useful,\r
3458 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
3459 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
3460 + * GNU General Public License for more details.\r
3461 + *\r
3462 + * You should have received a copy of the GNU General Public License\r
3463 + * along with this program; if not, write to the Free Software\r
3464 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
3465 + *\r
3466 + * squashfs.h\r
3467 + */\r
3468 +\r
3469 +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
3470 +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
3471 +#endif\r
3472 +\r
3473 +#ifdef SQUASHFS_TRACE\r
3474 +#define TRACE(s, args...)      printk(KERN_NOTICE "SQUASHFS: "s, ## args)\r
3475 +#else\r
3476 +#define TRACE(s, args...)      {}\r
3477 +#endif\r
3478 +\r
3479 +#define ERROR(s, args...)      printk(KERN_ERR "SQUASHFS error: "s, ## args)\r
3480 +\r
3481 +#define SERROR(s, args...)     do { \\r
3482 +                               if (!silent) \\r
3483 +                               printk(KERN_ERR "SQUASHFS error: "s, ## args);\\r
3484 +                               } while(0)\r
3485 +\r
3486 +#define WARNING(s, args...)    printk(KERN_WARNING "SQUASHFS: "s, ## args)\r
3487 +\r
3488 +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)\r
3489 +{\r
3490 +       return list_entry(inode, struct squashfs_inode_info, vfs_inode);\r
3491 +}\r
3492 +\r
3493 +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)\r
3494 +#define SQSH_EXTERN\r
3495 +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,\r
3496 +                               long long index, unsigned int length,\r
3497 +                               long long *next_index, int srclength);\r
3498 +extern int squashfs_get_cached_block(struct super_block *s, char *buffer,\r
3499 +                               long long block, unsigned int offset,\r
3500 +                               int length, long long *next_block,\r
3501 +                               unsigned int *next_offset);\r
3502 +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct\r
3503 +                                       squashfs_fragment_cache *fragment);\r
3504 +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block\r
3505 +                                       *s, long long start_block,\r
3506 +                                       int length);\r
3507 +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);\r
3508 +extern const struct address_space_operations squashfs_symlink_aops;\r
3509 +extern const struct address_space_operations squashfs_aops;\r
3510 +extern const struct address_space_operations squashfs_aops_4K;\r
3511 +extern struct inode_operations squashfs_dir_inode_ops;\r
3512 +#else\r
3513 +#define SQSH_EXTERN static\r
3514 +#endif\r
3515 +\r
3516 +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
3517 +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);\r
3518 +#else\r
3519 +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)\r
3520 +{\r
3521 +       return 0;\r
3522 +}\r
3523 +#endif\r
3524 +\r
3525 +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
3526 +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);\r
3527 +#else\r
3528 +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)\r
3529 +{\r
3530 +       return 0;\r
3531 +}\r
3532 +#endif\r
3533 diff -urN linux-2.6.23/fs/squashfs/squashfs2_0.c linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c\r
3534 --- linux-2.6.23/fs/squashfs/squashfs2_0.c      1969-12-31 19:00:00.000000000 -0500\r
3535 +++ linux-2.6.23.sqlzma/fs/squashfs/squashfs2_0.c       2007-10-14 10:24:31.000000000 -0400\r
3536 @@ -0,0 +1,742 @@\r
3537 +/*\r
3538 + * Squashfs - a compressed read only filesystem for Linux\r
3539 + *\r
3540 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
3541 + * Phillip Lougher <phillip@lougher.org.uk>\r
3542 + *\r
3543 + * This program is free software; you can redistribute it and/or\r
3544 + * modify it under the terms of the GNU General Public License\r
3545 + * as published by the Free Software Foundation; either version 2,\r
3546 + * or (at your option) any later version.\r
3547 + *\r
3548 + * This program is distributed in the hope that it will be useful,\r
3549 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
3550 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
3551 + * GNU General Public License for more details.\r
3552 + *\r
3553 + * You should have received a copy of the GNU General Public License\r
3554 + * along with this program; if not, write to the Free Software\r
3555 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
3556 + *\r
3557 + * squashfs2_0.c\r
3558 + */\r
3559 +\r
3560 +#include <linux/squashfs_fs.h>\r
3561 +#include <linux/module.h>\r
3562 +#include <linux/zlib.h>\r
3563 +#include <linux/fs.h>\r
3564 +#include <linux/squashfs_fs_sb.h>\r
3565 +#include <linux/squashfs_fs_i.h>\r
3566 +\r
3567 +#include "squashfs.h"\r
3568 +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);\r
3569 +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,\r
3570 +                               struct nameidata *);\r
3571 +\r
3572 +static struct file_operations squashfs_dir_ops_2 = {\r
3573 +       .read = generic_read_dir,\r
3574 +       .readdir = squashfs_readdir_2\r
3575 +};\r
3576 +\r
3577 +static struct inode_operations squashfs_dir_inode_ops_2 = {\r
3578 +       .lookup = squashfs_lookup_2\r
3579 +};\r
3580 +\r
3581 +static unsigned char squashfs_filetype_table[] = {\r
3582 +       DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK\r
3583 +};\r
3584 +\r
3585 +static int read_fragment_index_table_2(struct super_block *s)\r
3586 +{\r
3587 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
3588 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
3589 +\r
3590 +       if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2\r
3591 +                                       (sblk->fragments), GFP_KERNEL))) {\r
3592 +               ERROR("Failed to allocate uid/gid table\n");\r
3593 +               return 0;\r
3594 +       }\r
3595 +   \r
3596 +       if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&\r
3597 +                                       !squashfs_read_data(s, (char *)\r
3598 +                                       msblk->fragment_index_2,\r
3599 +                                       sblk->fragment_table_start,\r
3600 +                                       SQUASHFS_FRAGMENT_INDEX_BYTES_2\r
3601 +                                       (sblk->fragments) |\r
3602 +                                       SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {\r
3603 +               ERROR("unable to read fragment index table\n");\r
3604 +               return 0;\r
3605 +       }\r
3606 +\r
3607 +       if (msblk->swap) {\r
3608 +               int i;\r
3609 +               unsigned int fragment;\r
3610 +\r
3611 +               for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);\r
3612 +                                                                       i++) {\r
3613 +                       SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),\r
3614 +                                               &msblk->fragment_index_2[i], 1);\r
3615 +                       msblk->fragment_index_2[i] = fragment;\r
3616 +               }\r
3617 +       }\r
3618 +\r
3619 +       return 1;\r
3620 +}\r
3621 +\r
3622 +\r
3623 +static int get_fragment_location_2(struct super_block *s, unsigned int fragment,\r
3624 +                               long long *fragment_start_block,\r
3625 +                               unsigned int *fragment_size)\r
3626 +{\r
3627 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
3628 +       long long start_block =\r
3629 +               msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];\r
3630 +       int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);\r
3631 +       struct squashfs_fragment_entry_2 fragment_entry;\r
3632 +\r
3633 +       if (msblk->swap) {\r
3634 +               struct squashfs_fragment_entry_2 sfragment_entry;\r
3635 +\r
3636 +               if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,\r
3637 +                                       start_block, offset,\r
3638 +                                       sizeof(sfragment_entry), &start_block,\r
3639 +                                       &offset))\r
3640 +                       goto out;\r
3641 +               SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);\r
3642 +       } else\r
3643 +               if (!squashfs_get_cached_block(s, (char *) &fragment_entry,\r
3644 +                                       start_block, offset,\r
3645 +                                       sizeof(fragment_entry), &start_block,\r
3646 +                                       &offset))\r
3647 +                       goto out;\r
3648 +\r
3649 +       *fragment_start_block = fragment_entry.start_block;\r
3650 +       *fragment_size = fragment_entry.size;\r
3651 +\r
3652 +       return 1;\r
3653 +\r
3654 +out:\r
3655 +       return 0;\r
3656 +}\r
3657 +\r
3658 +\r
3659 +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,\r
3660 +               struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)\r
3661 +{\r
3662 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
3663 +\r
3664 +       i->i_ino = ino;\r
3665 +       i->i_mtime.tv_sec = sblk->mkfs_time;\r
3666 +       i->i_atime.tv_sec = sblk->mkfs_time;\r
3667 +       i->i_ctime.tv_sec = sblk->mkfs_time;\r
3668 +       i->i_uid = msblk->uid[inodeb->uid];\r
3669 +       i->i_mode = inodeb->mode;\r
3670 +       i->i_nlink = 1;\r
3671 +       i->i_size = 0;\r
3672 +       if (inodeb->guid == SQUASHFS_GUIDS)\r
3673 +               i->i_gid = i->i_uid;\r
3674 +       else\r
3675 +               i->i_gid = msblk->guid[inodeb->guid];\r
3676 +}\r
3677 +\r
3678 +\r
3679 +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)\r
3680 +{\r
3681 +       struct super_block *s = i->i_sb;\r
3682 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
3683 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
3684 +       unsigned int block = SQUASHFS_INODE_BLK(inode) +\r
3685 +               sblk->inode_table_start;\r
3686 +       unsigned int offset = SQUASHFS_INODE_OFFSET(inode);\r
3687 +       unsigned int ino = i->i_ino;\r
3688 +       long long next_block;\r
3689 +       unsigned int next_offset;\r
3690 +       union squashfs_inode_header_2 id, sid;\r
3691 +       struct squashfs_base_inode_header_2 *inodeb = &id.base,\r
3692 +                                         *sinodeb = &sid.base;\r
3693 +\r
3694 +       TRACE("Entered squashfs_iget\n");\r
3695 +\r
3696 +       if (msblk->swap) {\r
3697 +               if (!squashfs_get_cached_block(s, (char *) sinodeb, block,\r
3698 +                                       offset, sizeof(*sinodeb), &next_block,\r
3699 +                                       &next_offset))\r
3700 +                       goto failed_read;\r
3701 +               SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,\r
3702 +                                       sizeof(*sinodeb));\r
3703 +       } else\r
3704 +               if (!squashfs_get_cached_block(s, (char *) inodeb, block,\r
3705 +                                       offset, sizeof(*inodeb), &next_block,\r
3706 +                                       &next_offset))\r
3707 +                       goto failed_read;\r
3708 +\r
3709 +       squashfs_new_inode(msblk, i, inodeb, ino);\r
3710 +\r
3711 +       switch(inodeb->inode_type) {\r
3712 +               case SQUASHFS_FILE_TYPE: {\r
3713 +                       struct squashfs_reg_inode_header_2 *inodep = &id.reg;\r
3714 +                       struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;\r
3715 +                       long long frag_blk;\r
3716 +                       unsigned int frag_size = 0;\r
3717 +                               \r
3718 +                       if (msblk->swap) {\r
3719 +                               if (!squashfs_get_cached_block(s, (char *)\r
3720 +                                               sinodep, block, offset,\r
3721 +                                               sizeof(*sinodep), &next_block,\r
3722 +                                               &next_offset))\r
3723 +                                       goto failed_read;\r
3724 +                               SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);\r
3725 +                       } else\r
3726 +                               if (!squashfs_get_cached_block(s, (char *)\r
3727 +                                               inodep, block, offset,\r
3728 +                                               sizeof(*inodep), &next_block,\r
3729 +                                               &next_offset))\r
3730 +                                       goto failed_read;\r
3731 +\r
3732 +                       frag_blk = SQUASHFS_INVALID_BLK;\r
3733 +                       if (inodep->fragment != SQUASHFS_INVALID_FRAG &&\r
3734 +                                       !get_fragment_location_2(s,\r
3735 +                                       inodep->fragment, &frag_blk, &frag_size))\r
3736 +                               goto failed_read;\r
3737 +                               \r
3738 +                       i->i_size = inodep->file_size;\r
3739 +                       i->i_fop = &generic_ro_fops;\r
3740 +                       i->i_mode |= S_IFREG;\r
3741 +                       i->i_mtime.tv_sec = inodep->mtime;\r
3742 +                       i->i_atime.tv_sec = inodep->mtime;\r
3743 +                       i->i_ctime.tv_sec = inodep->mtime;\r
3744 +                       i->i_blocks = ((i->i_size - 1) >> 9) + 1;\r
3745 +                       SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;\r
3746 +                       SQUASHFS_I(i)->u.s1.fragment_size = frag_size;\r
3747 +                       SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;\r
3748 +                       SQUASHFS_I(i)->start_block = inodep->start_block;\r
3749 +                       SQUASHFS_I(i)->u.s1.block_list_start = next_block;\r
3750 +                       SQUASHFS_I(i)->offset = next_offset;\r
3751 +                       if (sblk->block_size > 4096)\r
3752 +                               i->i_data.a_ops = &squashfs_aops;\r
3753 +                       else\r
3754 +                               i->i_data.a_ops = &squashfs_aops_4K;\r
3755 +\r
3756 +                       TRACE("File inode %x:%x, start_block %x, "\r
3757 +                                       "block_list_start %llx, offset %x\n",\r
3758 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
3759 +                                       inodep->start_block, next_block,\r
3760 +                                       next_offset);\r
3761 +                       break;\r
3762 +               }\r
3763 +               case SQUASHFS_DIR_TYPE: {\r
3764 +                       struct squashfs_dir_inode_header_2 *inodep = &id.dir;\r
3765 +                       struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;\r
3766 +\r
3767 +                       if (msblk->swap) {\r
3768 +                               if (!squashfs_get_cached_block(s, (char *)\r
3769 +                                               sinodep, block, offset,\r
3770 +                                               sizeof(*sinodep), &next_block,\r
3771 +                                               &next_offset))\r
3772 +                                       goto failed_read;\r
3773 +                               SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);\r
3774 +                       } else\r
3775 +                               if (!squashfs_get_cached_block(s, (char *)\r
3776 +                                               inodep, block, offset,\r
3777 +                                               sizeof(*inodep), &next_block,\r
3778 +                                               &next_offset))\r
3779 +                                       goto failed_read;\r
3780 +\r
3781 +                       i->i_size = inodep->file_size;\r
3782 +                       i->i_op = &squashfs_dir_inode_ops_2;\r
3783 +                       i->i_fop = &squashfs_dir_ops_2;\r
3784 +                       i->i_mode |= S_IFDIR;\r
3785 +                       i->i_mtime.tv_sec = inodep->mtime;\r
3786 +                       i->i_atime.tv_sec = inodep->mtime;\r
3787 +                       i->i_ctime.tv_sec = inodep->mtime;\r
3788 +                       SQUASHFS_I(i)->start_block = inodep->start_block;\r
3789 +                       SQUASHFS_I(i)->offset = inodep->offset;\r
3790 +                       SQUASHFS_I(i)->u.s2.directory_index_count = 0;\r
3791 +                       SQUASHFS_I(i)->u.s2.parent_inode = 0;\r
3792 +\r
3793 +                       TRACE("Directory inode %x:%x, start_block %x, offset "\r
3794 +                                       "%x\n", SQUASHFS_INODE_BLK(inode),\r
3795 +                                       offset, inodep->start_block,\r
3796 +                                       inodep->offset);\r
3797 +                       break;\r
3798 +               }\r
3799 +               case SQUASHFS_LDIR_TYPE: {\r
3800 +                       struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;\r
3801 +                       struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;\r
3802 +\r
3803 +                       if (msblk->swap) {\r
3804 +                               if (!squashfs_get_cached_block(s, (char *)\r
3805 +                                               sinodep, block, offset,\r
3806 +                                               sizeof(*sinodep), &next_block,\r
3807 +                                               &next_offset))\r
3808 +                                       goto failed_read;\r
3809 +                               SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,\r
3810 +                                               sinodep);\r
3811 +                       } else\r
3812 +                               if (!squashfs_get_cached_block(s, (char *)\r
3813 +                                               inodep, block, offset,\r
3814 +                                               sizeof(*inodep), &next_block,\r
3815 +                                               &next_offset))\r
3816 +                                       goto failed_read;\r
3817 +\r
3818 +                       i->i_size = inodep->file_size;\r
3819 +                       i->i_op = &squashfs_dir_inode_ops_2;\r
3820 +                       i->i_fop = &squashfs_dir_ops_2;\r
3821 +                       i->i_mode |= S_IFDIR;\r
3822 +                       i->i_mtime.tv_sec = inodep->mtime;\r
3823 +                       i->i_atime.tv_sec = inodep->mtime;\r
3824 +                       i->i_ctime.tv_sec = inodep->mtime;\r
3825 +                       SQUASHFS_I(i)->start_block = inodep->start_block;\r
3826 +                       SQUASHFS_I(i)->offset = inodep->offset;\r
3827 +                       SQUASHFS_I(i)->u.s2.directory_index_start = next_block;\r
3828 +                       SQUASHFS_I(i)->u.s2.directory_index_offset =\r
3829 +                                                               next_offset;\r
3830 +                       SQUASHFS_I(i)->u.s2.directory_index_count =\r
3831 +                                                               inodep->i_count;\r
3832 +                       SQUASHFS_I(i)->u.s2.parent_inode = 0;\r
3833 +\r
3834 +                       TRACE("Long directory inode %x:%x, start_block %x, "\r
3835 +                                       "offset %x\n",\r
3836 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
3837 +                                       inodep->start_block, inodep->offset);\r
3838 +                       break;\r
3839 +               }\r
3840 +               case SQUASHFS_SYMLINK_TYPE: {\r
3841 +                       struct squashfs_symlink_inode_header_2 *inodep =\r
3842 +                                                               &id.symlink;\r
3843 +                       struct squashfs_symlink_inode_header_2 *sinodep =\r
3844 +                                                               &sid.symlink;\r
3845 +       \r
3846 +                       if (msblk->swap) {\r
3847 +                               if (!squashfs_get_cached_block(s, (char *)\r
3848 +                                               sinodep, block, offset,\r
3849 +                                               sizeof(*sinodep), &next_block,\r
3850 +                                               &next_offset))\r
3851 +                                       goto failed_read;\r
3852 +                               SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,\r
3853 +                                                               sinodep);\r
3854 +                       } else\r
3855 +                               if (!squashfs_get_cached_block(s, (char *)\r
3856 +                                               inodep, block, offset,\r
3857 +                                               sizeof(*inodep), &next_block,\r
3858 +                                               &next_offset))\r
3859 +                                       goto failed_read;\r
3860 +\r
3861 +                       i->i_size = inodep->symlink_size;\r
3862 +                       i->i_op = &page_symlink_inode_operations;\r
3863 +                       i->i_data.a_ops = &squashfs_symlink_aops;\r
3864 +                       i->i_mode |= S_IFLNK;\r
3865 +                       SQUASHFS_I(i)->start_block = next_block;\r
3866 +                       SQUASHFS_I(i)->offset = next_offset;\r
3867 +\r
3868 +                       TRACE("Symbolic link inode %x:%x, start_block %llx, "\r
3869 +                                       "offset %x\n",\r
3870 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
3871 +                                       next_block, next_offset);\r
3872 +                       break;\r
3873 +                }\r
3874 +                case SQUASHFS_BLKDEV_TYPE:\r
3875 +                case SQUASHFS_CHRDEV_TYPE: {\r
3876 +                       struct squashfs_dev_inode_header_2 *inodep = &id.dev;\r
3877 +                       struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;\r
3878 +\r
3879 +                       if (msblk->swap) {\r
3880 +                               if (!squashfs_get_cached_block(s, (char *)\r
3881 +                                               sinodep, block, offset,\r
3882 +                                               sizeof(*sinodep), &next_block,\r
3883 +                                               &next_offset))\r
3884 +                                       goto failed_read;\r
3885 +                               SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);\r
3886 +                       } else  \r
3887 +                               if (!squashfs_get_cached_block(s, (char *)\r
3888 +                                               inodep, block, offset,\r
3889 +                                               sizeof(*inodep), &next_block,\r
3890 +                                               &next_offset))\r
3891 +                                       goto failed_read;\r
3892 +\r
3893 +                       i->i_mode |= (inodeb->inode_type ==\r
3894 +                                       SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :\r
3895 +                                       S_IFBLK;\r
3896 +                       init_special_inode(i, i->i_mode,\r
3897 +                                       old_decode_dev(inodep->rdev));\r
3898 +\r
3899 +                       TRACE("Device inode %x:%x, rdev %x\n",\r
3900 +                                       SQUASHFS_INODE_BLK(inode), offset,\r
3901 +                                       inodep->rdev);\r
3902 +                       break;\r
3903 +                }\r
3904 +                case SQUASHFS_FIFO_TYPE:\r
3905 +                case SQUASHFS_SOCKET_TYPE: {\r
3906 +\r
3907 +                       i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)\r
3908 +                                                       ? S_IFIFO : S_IFSOCK;\r
3909 +                       init_special_inode(i, i->i_mode, 0);\r
3910 +                       break;\r
3911 +                }\r
3912 +                default:\r
3913 +                       ERROR("Unknown inode type %d in squashfs_iget!\n",\r
3914 +                                       inodeb->inode_type);\r
3915 +                       goto failed_read1;\r
3916 +       }\r
3917 +       \r
3918 +       return 1;\r
3919 +\r
3920 +failed_read:\r
3921 +       ERROR("Unable to read inode [%x:%x]\n", block, offset);\r
3922 +\r
3923 +failed_read1:\r
3924 +       return 0;\r
3925 +}\r
3926 +\r
3927 +\r
3928 +static int get_dir_index_using_offset(struct super_block *s, long long \r
3929 +                               *next_block, unsigned int *next_offset,\r
3930 +                               long long index_start,\r
3931 +                               unsigned int index_offset, int i_count,\r
3932 +                               long long f_pos)\r
3933 +{\r
3934 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
3935 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
3936 +       int i, length = 0;\r
3937 +       struct squashfs_dir_index_2 index;\r
3938 +\r
3939 +       TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",\r
3940 +                                       i_count, (unsigned int) f_pos);\r
3941 +\r
3942 +       if (f_pos == 0)\r
3943 +               goto finish;\r
3944 +\r
3945 +       for (i = 0; i < i_count; i++) {\r
3946 +               if (msblk->swap) {\r
3947 +                       struct squashfs_dir_index_2 sindex;\r
3948 +                       squashfs_get_cached_block(s, (char *) &sindex,\r
3949 +                                       index_start, index_offset,\r
3950 +                                       sizeof(sindex), &index_start,\r
3951 +                                       &index_offset);\r
3952 +                       SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);\r
3953 +               } else\r
3954 +                       squashfs_get_cached_block(s, (char *) &index,\r
3955 +                                       index_start, index_offset,\r
3956 +                                       sizeof(index), &index_start,\r
3957 +                                       &index_offset);\r
3958 +\r
3959 +               if (index.index > f_pos)\r
3960 +                       break;\r
3961 +\r
3962 +               squashfs_get_cached_block(s, NULL, index_start, index_offset,\r
3963 +                                       index.size + 1, &index_start,\r
3964 +                                       &index_offset);\r
3965 +\r
3966 +               length = index.index;\r
3967 +               *next_block = index.start_block + sblk->directory_table_start;\r
3968 +       }\r
3969 +\r
3970 +       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
3971 +\r
3972 +finish:\r
3973 +       return length;\r
3974 +}\r
3975 +\r
3976 +\r
3977 +static int get_dir_index_using_name(struct super_block *s, long long\r
3978 +                               *next_block, unsigned int *next_offset,\r
3979 +                               long long index_start,\r
3980 +                               unsigned int index_offset, int i_count,\r
3981 +                               const char *name, int size)\r
3982 +{\r
3983 +       struct squashfs_sb_info *msblk = s->s_fs_info;\r
3984 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
3985 +       int i, length = 0;\r
3986 +       struct squashfs_dir_index_2 *index;\r
3987 +       char *str;\r
3988 +\r
3989 +       TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);\r
3990 +\r
3991 +       if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +\r
3992 +               (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {\r
3993 +               ERROR("Failed to allocate squashfs_dir_index\n");\r
3994 +               goto failure;\r
3995 +       }\r
3996 +\r
3997 +       index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);\r
3998 +       strncpy(str, name, size);\r
3999 +       str[size] = '\0';\r
4000 +\r
4001 +       for (i = 0; i < i_count; i++) {\r
4002 +               if (msblk->swap) {\r
4003 +                       struct squashfs_dir_index_2 sindex;\r
4004 +                       squashfs_get_cached_block(s, (char *) &sindex,\r
4005 +                                       index_start, index_offset,\r
4006 +                                       sizeof(sindex), &index_start,\r
4007 +                                       &index_offset);\r
4008 +                       SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);\r
4009 +               } else\r
4010 +                       squashfs_get_cached_block(s, (char *) index,\r
4011 +                                       index_start, index_offset,\r
4012 +                                       sizeof(struct squashfs_dir_index_2),\r
4013 +                                       &index_start, &index_offset);\r
4014 +\r
4015 +               squashfs_get_cached_block(s, index->name, index_start,\r
4016 +                                       index_offset, index->size + 1,\r
4017 +                                       &index_start, &index_offset);\r
4018 +\r
4019 +               index->name[index->size + 1] = '\0';\r
4020 +\r
4021 +               if (strcmp(index->name, str) > 0)\r
4022 +                       break;\r
4023 +\r
4024 +               length = index->index;\r
4025 +               *next_block = index->start_block + sblk->directory_table_start;\r
4026 +       }\r
4027 +\r
4028 +       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;\r
4029 +       kfree(str);\r
4030 +failure:\r
4031 +       return length;\r
4032 +}\r
4033 +\r
4034 +               \r
4035 +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)\r
4036 +{\r
4037 +       struct inode *i = file->f_dentry->d_inode;\r
4038 +       struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
4039 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
4040 +       long long next_block = SQUASHFS_I(i)->start_block +\r
4041 +               sblk->directory_table_start;\r
4042 +       int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
4043 +               dir_count;\r
4044 +       struct squashfs_dir_header_2 dirh;\r
4045 +       struct squashfs_dir_entry_2 *dire;\r
4046 +\r
4047 +       TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);\r
4048 +\r
4049 +       if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
4050 +               SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
4051 +               ERROR("Failed to allocate squashfs_dir_entry\n");\r
4052 +               goto finish;\r
4053 +       }\r
4054 +\r
4055 +       length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,\r
4056 +                               SQUASHFS_I(i)->u.s2.directory_index_start,\r
4057 +                               SQUASHFS_I(i)->u.s2.directory_index_offset,\r
4058 +                               SQUASHFS_I(i)->u.s2.directory_index_count,\r
4059 +                               file->f_pos);\r
4060 +\r
4061 +       while (length < i_size_read(i)) {\r
4062 +               /* read directory header */\r
4063 +               if (msblk->swap) {\r
4064 +                       struct squashfs_dir_header_2 sdirh;\r
4065 +                       \r
4066 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
4067 +                                       next_block, next_offset, sizeof(sdirh),\r
4068 +                                       &next_block, &next_offset))\r
4069 +                               goto failed_read;\r
4070 +\r
4071 +                       length += sizeof(sdirh);\r
4072 +                       SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);\r
4073 +               } else {\r
4074 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
4075 +                                       next_block, next_offset, sizeof(dirh),\r
4076 +                                       &next_block, &next_offset))\r
4077 +                               goto failed_read;\r
4078 +\r
4079 +                       length += sizeof(dirh);\r
4080 +               }\r
4081 +\r
4082 +               dir_count = dirh.count + 1;\r
4083 +               while (dir_count--) {\r
4084 +                       if (msblk->swap) {\r
4085 +                               struct squashfs_dir_entry_2 sdire;\r
4086 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
4087 +                                               &sdire, next_block, next_offset,\r
4088 +                                               sizeof(sdire), &next_block,\r
4089 +                                               &next_offset))\r
4090 +                                       goto failed_read;\r
4091 +                               \r
4092 +                               length += sizeof(sdire);\r
4093 +                               SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);\r
4094 +                       } else {\r
4095 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
4096 +                                               dire, next_block, next_offset,\r
4097 +                                               sizeof(*dire), &next_block,\r
4098 +                                               &next_offset))\r
4099 +                                       goto failed_read;\r
4100 +\r
4101 +                               length += sizeof(*dire);\r
4102 +                       }\r
4103 +\r
4104 +                       if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
4105 +                                               next_block, next_offset,\r
4106 +                                               dire->size + 1, &next_block,\r
4107 +                                               &next_offset))\r
4108 +                               goto failed_read;\r
4109 +\r
4110 +                       length += dire->size + 1;\r
4111 +\r
4112 +                       if (file->f_pos >= length)\r
4113 +                               continue;\r
4114 +\r
4115 +                       dire->name[dire->size + 1] = '\0';\r
4116 +\r
4117 +                       TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",\r
4118 +                                       (unsigned int) dirent, dire->name,\r
4119 +                                       dire->size + 1, (int) file->f_pos,\r
4120 +                                       dirh.start_block, dire->offset,\r
4121 +                                       squashfs_filetype_table[dire->type]);\r
4122 +\r
4123 +                       if (filldir(dirent, dire->name, dire->size + 1,\r
4124 +                                       file->f_pos, SQUASHFS_MK_VFS_INODE(\r
4125 +                                       dirh.start_block, dire->offset),\r
4126 +                                       squashfs_filetype_table[dire->type])\r
4127 +                                       < 0) {\r
4128 +                               TRACE("Filldir returned less than 0\n");\r
4129 +                               goto finish;\r
4130 +                       }\r
4131 +                       file->f_pos = length;\r
4132 +               }\r
4133 +       }\r
4134 +\r
4135 +finish:\r
4136 +       kfree(dire);\r
4137 +       return 0;\r
4138 +\r
4139 +failed_read:\r
4140 +       ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
4141 +               next_offset);\r
4142 +       kfree(dire);\r
4143 +       return 0;\r
4144 +}\r
4145 +\r
4146 +\r
4147 +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,\r
4148 +                               struct nameidata *nd)\r
4149 +{\r
4150 +       const unsigned char *name = dentry->d_name.name;\r
4151 +       int len = dentry->d_name.len;\r
4152 +       struct inode *inode = NULL;\r
4153 +       struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;\r
4154 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
4155 +       long long next_block = SQUASHFS_I(i)->start_block +\r
4156 +                               sblk->directory_table_start;\r
4157 +       int next_offset = SQUASHFS_I(i)->offset, length = 0,\r
4158 +                               dir_count;\r
4159 +       struct squashfs_dir_header_2 dirh;\r
4160 +       struct squashfs_dir_entry_2 *dire;\r
4161 +       int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;\r
4162 +\r
4163 +       TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);\r
4164 +\r
4165 +       if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +\r
4166 +               SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {\r
4167 +               ERROR("Failed to allocate squashfs_dir_entry\n");\r
4168 +               goto exit_loop;\r
4169 +       }\r
4170 +\r
4171 +       if (len > SQUASHFS_NAME_LEN)\r
4172 +               goto exit_loop;\r
4173 +\r
4174 +       length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,\r
4175 +                               SQUASHFS_I(i)->u.s2.directory_index_start,\r
4176 +                               SQUASHFS_I(i)->u.s2.directory_index_offset,\r
4177 +                               SQUASHFS_I(i)->u.s2.directory_index_count, name,\r
4178 +                               len);\r
4179 +\r
4180 +       while (length < i_size_read(i)) {\r
4181 +               /* read directory header */\r
4182 +               if (msblk->swap) {\r
4183 +                       struct squashfs_dir_header_2 sdirh;\r
4184 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,\r
4185 +                                       next_block, next_offset, sizeof(sdirh),\r
4186 +                                       &next_block, &next_offset))\r
4187 +                               goto failed_read;\r
4188 +\r
4189 +                       length += sizeof(sdirh);\r
4190 +                       SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);\r
4191 +               } else {\r
4192 +                       if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,\r
4193 +                                       next_block, next_offset, sizeof(dirh),\r
4194 +                                       &next_block, &next_offset))\r
4195 +                               goto failed_read;\r
4196 +\r
4197 +                       length += sizeof(dirh);\r
4198 +               }\r
4199 +\r
4200 +               dir_count = dirh.count + 1;\r
4201 +               while (dir_count--) {\r
4202 +                       if (msblk->swap) {\r
4203 +                               struct squashfs_dir_entry_2 sdire;\r
4204 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
4205 +                                               &sdire, next_block,next_offset,\r
4206 +                                               sizeof(sdire), &next_block,\r
4207 +                                               &next_offset))\r
4208 +                                       goto failed_read;\r
4209 +                               \r
4210 +                               length += sizeof(sdire);\r
4211 +                               SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);\r
4212 +                       } else {\r
4213 +                               if (!squashfs_get_cached_block(i->i_sb, (char *)\r
4214 +                                               dire, next_block,next_offset,\r
4215 +                                               sizeof(*dire), &next_block,\r
4216 +                                               &next_offset))\r
4217 +                                       goto failed_read;\r
4218 +\r
4219 +                               length += sizeof(*dire);\r
4220 +                       }\r
4221 +\r
4222 +                       if (!squashfs_get_cached_block(i->i_sb, dire->name,\r
4223 +                                       next_block, next_offset, dire->size + 1,\r
4224 +                                       &next_block, &next_offset))\r
4225 +                               goto failed_read;\r
4226 +\r
4227 +                       length += dire->size + 1;\r
4228 +\r
4229 +                       if (sorted && name[0] < dire->name[0])\r
4230 +                               goto exit_loop;\r
4231 +\r
4232 +                       if ((len == dire->size + 1) && !strncmp(name,\r
4233 +                                               dire->name, len)) {\r
4234 +                               squashfs_inode_t ino =\r
4235 +                                       SQUASHFS_MKINODE(dirh.start_block,\r
4236 +                                       dire->offset);\r
4237 +                               unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,\r
4238 +                                       dire->offset);\r
4239 +\r
4240 +                               TRACE("calling squashfs_iget for directory "\r
4241 +                                       "entry %s, inode %x:%x, %lld\n", name,\r
4242 +                                       dirh.start_block, dire->offset, ino);\r
4243 +\r
4244 +                               inode = squashfs_iget(i->i_sb, ino, inode_number);\r
4245 +\r
4246 +                               goto exit_loop;\r
4247 +                       }\r
4248 +               }\r
4249 +       }\r
4250 +\r
4251 +exit_loop:\r
4252 +       kfree(dire);\r
4253 +       d_add(dentry, inode);\r
4254 +       return ERR_PTR(0);\r
4255 +\r
4256 +failed_read:\r
4257 +       ERROR("Unable to read directory block [%llx:%x]\n", next_block,\r
4258 +               next_offset);\r
4259 +       goto exit_loop;\r
4260 +}\r
4261 +\r
4262 +\r
4263 +int squashfs_2_0_supported(struct squashfs_sb_info *msblk)\r
4264 +{\r
4265 +       struct squashfs_super_block *sblk = &msblk->sblk;\r
4266 +\r
4267 +       msblk->read_inode = squashfs_read_inode_2;\r
4268 +       msblk->read_fragment_index_table = read_fragment_index_table_2;\r
4269 +\r
4270 +       sblk->bytes_used = sblk->bytes_used_2;\r
4271 +       sblk->uid_start = sblk->uid_start_2;\r
4272 +       sblk->guid_start = sblk->guid_start_2;\r
4273 +       sblk->inode_table_start = sblk->inode_table_start_2;\r
4274 +       sblk->directory_table_start = sblk->directory_table_start_2;\r
4275 +       sblk->fragment_table_start = sblk->fragment_table_start_2;\r
4276 +\r
4277 +       return 1;\r
4278 +}\r
4279 diff -urN linux-2.6.23/fs/squashfs/uncomp.c linux-2.6.23.sqlzma/fs/squashfs/uncomp.c\r
4280 --- linux-2.6.23/fs/squashfs/uncomp.c   1969-12-31 19:00:00.000000000 -0500\r
4281 +++ linux-2.6.23.sqlzma/fs/squashfs/uncomp.c    2007-10-14 12:43:55.000000000 -0400\r
4282 @@ -0,0 +1,221 @@\r
4283 +/*\r
4284 + * Copyright (C) 2006, 2007 Junjiro Okajima\r
4285 + * Copyright (C) 2006, 2007 Tomas Matejicek, slax.org\r
4286 + *\r
4287 + * LICENSE follows the described one in lzma.txt.\r
4288 + */\r
4289 +\r
4290 +/* $Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $ */\r
4291 +\r
4292 +/* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */\r
4293 +\r
4294 +#ifndef __KERNEL__\r
4295 +#include <stdio.h>\r
4296 +#include <stdlib.h>\r
4297 +#include <string.h>\r
4298 +#include <errno.h>\r
4299 +#include <assert.h>\r
4300 +#include <pthread.h>\r
4301 +#define unlikely(x)            __builtin_expect(!!(x), 0)\r
4302 +#define BUG_ON(x)              assert(!(x))\r
4303 +/* sqlzma buffers are always larger than a page. true? */\r
4304 +#define kmalloc(sz,gfp)                malloc(sz)\r
4305 +#define kfree(p)               free(p)\r
4306 +#define zlib_inflate(s, f)     inflate(s, f)\r
4307 +#define zlib_inflateInit(s)    inflateInit(s)\r
4308 +#define zlib_inflateReset(s)   inflateReset(s)\r
4309 +#define zlib_inflateEnd(s)     inflateEnd(s)\r
4310 +#else\r
4311 +#include <linux/init.h>\r
4312 +#include <linux/module.h>\r
4313 +#include <linux/kernel.h>\r
4314 +#include <linux/vmalloc.h>\r
4315 +#ifndef WARN_ON_ONCE\r
4316 +#define WARN_ON_ONCE(b)        WARN_ON(b)\r
4317 +#endif\r
4318 +#endif /* __KERNEL__ */\r
4319 +\r
4320 +#include "sqlzma.h"\r
4321 +#include "LzmaDecode.h"\r
4322 +\r
4323 +static int LzmaUncompress(struct sqlzma_un *un)\r
4324 +{\r
4325 +       int err, i, ret;\r
4326 +       SizeT outSize, inProcessed, outProcessed, srclen;\r
4327 +       /* it's about 24-80 bytes structure, if int is 32-bit */\r
4328 +       CLzmaDecoderState state;\r
4329 +       unsigned char *dst, *src, a[8];\r
4330 +       struct sized_buf *sbuf;\r
4331 +\r
4332 +       /* Decode LZMA properties and allocate memory */\r
4333 +       err = -EINVAL;\r
4334 +       src = (unsigned char *)un->un_cmbuf;\r
4335 +       ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);\r
4336 +       src += LZMA_PROPERTIES_SIZE;\r
4337 +       if (unlikely(ret != LZMA_RESULT_OK))\r
4338 +               goto out;\r
4339 +       i = LzmaGetNumProbs(&state.Properties);\r
4340 +       if (unlikely(i <= 0))\r
4341 +               i = 1;\r
4342 +       i *= sizeof(CProb);\r
4343 +       sbuf = un->un_a + SQUN_PROB;\r
4344 +       if (unlikely(sbuf->sz < i)) {\r
4345 +               if (sbuf->buf && sbuf->buf != un->un_prob)\r
4346 +                       kfree(sbuf->buf);\r
4347 +#ifdef __KERNEL__\r
4348 +               printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i);\r
4349 +#else\r
4350 +               printf("%d --> %d\n", sbuf->sz, i);\r
4351 +#endif\r
4352 +               err = -ENOMEM;\r
4353 +               sbuf->sz = 0;\r
4354 +               sbuf->buf = kmalloc(i, GFP_ATOMIC);\r
4355 +               if (unlikely(!sbuf->buf))\r
4356 +                       goto out;\r
4357 +               sbuf->sz = i;\r
4358 +       }\r
4359 +       state.Probs = (void*)sbuf->buf;\r
4360 +\r
4361 +       /* Read uncompressed size */\r
4362 +       memcpy(a, src, sizeof(a));\r
4363 +       src += sizeof(a);\r
4364 +       outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);\r
4365 +\r
4366 +       err = -EINVAL;\r
4367 +       dst = un->un_resbuf;\r
4368 +       if (unlikely(!dst || outSize > un->un_reslen))\r
4369 +               goto out;\r
4370 +       un->un_reslen = outSize;\r
4371 +       srclen = un->un_cmlen - (src - un->un_cmbuf);\r
4372 +\r
4373 +       /* Decompress */\r
4374 +       err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize,\r
4375 +                        &outProcessed);\r
4376 +       if (err)\r
4377 +               err = -EINVAL;\r
4378 +\r
4379 + out:\r
4380 +#ifndef __KERNEL__\r
4381 +       if (err)\r
4382 +               fprintf(stderr, "err %d\n", err);\r
4383 +#endif\r
4384 +       return err;\r
4385 +}\r
4386 +\r
4387 +int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src,\r
4388 +             struct sized_buf *dst)\r
4389 +{\r
4390 +       int err, by_lzma = 0;\r
4391 +       if (un->un_lzma && is_lzma(*src->buf)) {\r
4392 +               by_lzma = 1;\r
4393 +               un->un_cmbuf = src->buf;\r
4394 +               un->un_cmlen = src->sz;\r
4395 +               un->un_resbuf = dst->buf;\r
4396 +               un->un_reslen = dst->sz;\r
4397 +\r
4398 +               /* this library is thread-safe */\r
4399 +               err = LzmaUncompress(un);\r
4400 +               goto out;\r
4401 +       }\r
4402 +\r
4403 +       err = zlib_inflateReset(&un->un_stream);\r
4404 +       if (unlikely(err != Z_OK))\r
4405 +               goto out;\r
4406 +       un->un_stream.next_in = src->buf;\r
4407 +       un->un_stream.avail_in = src->sz;\r
4408 +       un->un_stream.next_out = dst->buf;\r
4409 +       un->un_stream.avail_out = dst->sz;\r
4410 +       err = zlib_inflate(&un->un_stream, Z_FINISH);\r
4411 +       if (err == Z_STREAM_END)\r
4412 +               err = 0;\r
4413 +\r
4414 + out:\r
4415 +       if (err) {\r
4416 +#ifdef __KERNEL__\r
4417 +               WARN_ON_ONCE(1);\r
4418 +#else\r
4419 +               char a[64] = "ZLIB ";\r
4420 +               if (by_lzma) {\r
4421 +                       strcpy(a, "LZMA ");\r
4422 +#ifdef _REENTRANT\r
4423 +                       strerror_r(err, a + 5, sizeof(a) - 5);\r
4424 +#else\r
4425 +                       strncat(a, strerror(err), sizeof(a) - 5);\r
4426 +#endif\r
4427 +               } else\r
4428 +                       strncat(a, zError(err), sizeof(a) - 5);\r
4429 +               fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a);\r
4430 +#endif\r
4431 +       }\r
4432 +       return err;\r
4433 +}\r
4434 +\r
4435 +int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz)\r
4436 +{\r
4437 +       int err;\r
4438 +\r
4439 +       err = -ENOMEM;\r
4440 +       un->un_lzma = do_lzma;\r
4441 +       memset(un->un_a, 0, sizeof(un->un_a));\r
4442 +       un->un_a[SQUN_PROB].buf = un->un_prob;\r
4443 +       un->un_a[SQUN_PROB].sz = sizeof(un->un_prob);\r
4444 +       if (res_sz) {\r
4445 +               un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL);\r
4446 +               if (unlikely(!un->un_a[SQUN_RESULT].buf))\r
4447 +                       return err;\r
4448 +               un->un_a[SQUN_RESULT].sz = res_sz;\r
4449 +       }\r
4450 +\r
4451 +       un->un_stream.next_in = NULL;\r
4452 +       un->un_stream.avail_in = 0;\r
4453 +#ifdef __KERNEL__\r
4454 +       un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);\r
4455 +       if (unlikely(!un->un_stream.workspace))\r
4456 +               return err;\r
4457 +#else\r
4458 +       un->un_stream.opaque = NULL;\r
4459 +       un->un_stream.zalloc = Z_NULL;\r
4460 +       un->un_stream.zfree = Z_NULL;\r
4461 +#endif\r
4462 +       err = zlib_inflateInit(&un->un_stream);\r
4463 +       if (unlikely(err == Z_MEM_ERROR))\r
4464 +               return -ENOMEM;\r
4465 +       BUG_ON(err);\r
4466 +       return err;\r
4467 +}\r
4468 +\r
4469 +void sqlzma_fin(struct sqlzma_un *un)\r
4470 +{\r
4471 +       int i;\r
4472 +       for (i = 0; i < SQUN_LAST; i++)\r
4473 +               if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob)\r
4474 +                       kfree(un->un_a[i].buf);\r
4475 +       BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK);\r
4476 +}\r
4477 +\r
4478 +#ifdef __KERNEL__\r
4479 +EXPORT_SYMBOL(sqlzma_un);\r
4480 +EXPORT_SYMBOL(sqlzma_init);\r
4481 +EXPORT_SYMBOL(sqlzma_fin);\r
4482 +\r
4483 +#if 0\r
4484 +static int __init sqlzma_init(void)\r
4485 +{\r
4486 +       return 0;\r
4487 +}\r
4488 +\r
4489 +static void __exit sqlzma_exit(void)\r
4490 +{\r
4491 +}\r
4492 +\r
4493 +module_init(sqlzma_init);\r
4494 +module_exit(sqlzma_exit);\r
4495 +#endif\r
4496 +\r
4497 +MODULE_LICENSE("GPL");\r
4498 +MODULE_AUTHOR("Junjiro Okajima <hooanon05 at yahoo dot co dot jp>");\r
4499 +MODULE_VERSION("$Id: uncomp.c,v 1.30 2007/03/04 12:45:53 jro Exp $");\r
4500 +MODULE_DESCRIPTION("LZMA uncompress for squashfs. "\r
4501 +                  "Some functions for squashfs to support LZMA and "\r
4502 +                  "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org.");\r
4503 +#endif\r
4504 diff -urN linux-2.6.23/include/linux/squashfs_fs.h linux-2.6.23.sqlzma/include/linux/squashfs_fs.h\r
4505 --- linux-2.6.23/include/linux/squashfs_fs.h    1969-12-31 19:00:00.000000000 -0500\r
4506 +++ linux-2.6.23.sqlzma/include/linux/squashfs_fs.h     2007-10-14 10:24:31.000000000 -0400\r
4507 @@ -0,0 +1,934 @@\r
4508 +#ifndef SQUASHFS_FS\r
4509 +#define SQUASHFS_FS\r
4510 +\r
4511 +/*\r
4512 + * Squashfs\r
4513 + *\r
4514 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
4515 + * Phillip Lougher <phillip@lougher.org.uk>\r
4516 + *\r
4517 + * This program is free software; you can redistribute it and/or\r
4518 + * modify it under the terms of the GNU General Public License\r
4519 + * as published by the Free Software Foundation; either version 2,\r
4520 + * or (at your option) any later version.\r
4521 + *\r
4522 + * This program is distributed in the hope that it will be useful,\r
4523 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
4524 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
4525 + * GNU General Public License for more details.\r
4526 + *\r
4527 + * You should have received a copy of the GNU General Public License\r
4528 + * along with this program; if not, write to the Free Software\r
4529 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
4530 + *\r
4531 + * squashfs_fs.h\r
4532 + */\r
4533 +\r
4534 +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
4535 +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
4536 +#endif\r
4537 +\r
4538 +#ifdef CONFIG_SQUASHFS_VMALLOC\r
4539 +#define SQUASHFS_ALLOC(a)              vmalloc(a)\r
4540 +#define SQUASHFS_FREE(a)               vfree(a)\r
4541 +#else\r
4542 +#define SQUASHFS_ALLOC(a)              kmalloc(a, GFP_KERNEL)\r
4543 +#define SQUASHFS_FREE(a)               kfree(a)\r
4544 +#endif\r
4545 +#define SQUASHFS_CACHED_FRAGMENTS      CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE     \r
4546 +#define SQUASHFS_MAJOR                 3\r
4547 +#define SQUASHFS_MINOR                 0\r
4548 +#define SQUASHFS_MAGIC                 0x73717368\r
4549 +#define SQUASHFS_MAGIC_SWAP            0x68737173\r
4550 +#define SQUASHFS_START                 0\r
4551 +\r
4552 +/* size of metadata (inode and directory) blocks */\r
4553 +#define SQUASHFS_METADATA_SIZE         8192\r
4554 +#define SQUASHFS_METADATA_LOG          13\r
4555 +\r
4556 +/* default size of data blocks */\r
4557 +#define SQUASHFS_FILE_SIZE             65536\r
4558 +#define SQUASHFS_FILE_LOG              16\r
4559 +\r
4560 +#define SQUASHFS_FILE_MAX_SIZE         65536\r
4561 +\r
4562 +/* Max number of uids and gids */\r
4563 +#define SQUASHFS_UIDS                  256\r
4564 +#define SQUASHFS_GUIDS                 255\r
4565 +\r
4566 +/* Max length of filename (not 255) */\r
4567 +#define SQUASHFS_NAME_LEN              256\r
4568 +\r
4569 +#define SQUASHFS_INVALID               ((long long) 0xffffffffffff)\r
4570 +#define SQUASHFS_INVALID_FRAG          ((unsigned int) 0xffffffff)\r
4571 +#define SQUASHFS_INVALID_BLK           ((long long) -1)\r
4572 +#define SQUASHFS_USED_BLK              ((long long) -2)\r
4573 +\r
4574 +/* Filesystem flags */\r
4575 +#define SQUASHFS_NOI                   0\r
4576 +#define SQUASHFS_NOD                   1\r
4577 +#define SQUASHFS_CHECK                 2\r
4578 +#define SQUASHFS_NOF                   3\r
4579 +#define SQUASHFS_NO_FRAG               4\r
4580 +#define SQUASHFS_ALWAYS_FRAG           5\r
4581 +#define SQUASHFS_DUPLICATE             6\r
4582 +#define SQUASHFS_EXPORT                        7\r
4583 +\r
4584 +#define SQUASHFS_BIT(flag, bit)                ((flag >> bit) & 1)\r
4585 +\r
4586 +#define SQUASHFS_UNCOMPRESSED_INODES(flags)    SQUASHFS_BIT(flags, \\r
4587 +                                               SQUASHFS_NOI)\r
4588 +\r
4589 +#define SQUASHFS_UNCOMPRESSED_DATA(flags)      SQUASHFS_BIT(flags, \\r
4590 +                                               SQUASHFS_NOD)\r
4591 +\r
4592 +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \\r
4593 +                                               SQUASHFS_NOF)\r
4594 +\r
4595 +#define SQUASHFS_NO_FRAGMENTS(flags)           SQUASHFS_BIT(flags, \\r
4596 +                                               SQUASHFS_NO_FRAG)\r
4597 +\r
4598 +#define SQUASHFS_ALWAYS_FRAGMENTS(flags)       SQUASHFS_BIT(flags, \\r
4599 +                                               SQUASHFS_ALWAYS_FRAG)\r
4600 +\r
4601 +#define SQUASHFS_DUPLICATES(flags)             SQUASHFS_BIT(flags, \\r
4602 +                                               SQUASHFS_DUPLICATE)\r
4603 +\r
4604 +#define SQUASHFS_EXPORTABLE(flags)             SQUASHFS_BIT(flags, \\r
4605 +                                               SQUASHFS_EXPORT)\r
4606 +\r
4607 +#define SQUASHFS_CHECK_DATA(flags)             SQUASHFS_BIT(flags, \\r
4608 +                                               SQUASHFS_CHECK)\r
4609 +\r
4610 +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \\r
4611 +               duplicate_checking, exortable)  (noi | (nod << 1) | (check_data << 2) \\r
4612 +               | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \\r
4613 +               (duplicate_checking << 6) | (exportable << 7))\r
4614 +\r
4615 +/* Max number of types and file types */\r
4616 +#define SQUASHFS_DIR_TYPE              1\r
4617 +#define SQUASHFS_FILE_TYPE             2\r
4618 +#define SQUASHFS_SYMLINK_TYPE          3\r
4619 +#define SQUASHFS_BLKDEV_TYPE           4\r
4620 +#define SQUASHFS_CHRDEV_TYPE           5\r
4621 +#define SQUASHFS_FIFO_TYPE             6\r
4622 +#define SQUASHFS_SOCKET_TYPE           7\r
4623 +#define SQUASHFS_LDIR_TYPE             8\r
4624 +#define SQUASHFS_LREG_TYPE             9\r
4625 +\r
4626 +/* 1.0 filesystem type definitions */\r
4627 +#define SQUASHFS_TYPES                 5\r
4628 +#define SQUASHFS_IPC_TYPE              0\r
4629 +\r
4630 +/* Flag whether block is compressed or uncompressed, bit is set if block is\r
4631 + * uncompressed */\r
4632 +#define SQUASHFS_COMPRESSED_BIT                (1 << 15)\r
4633 +\r
4634 +#define SQUASHFS_COMPRESSED_SIZE(B)    (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \\r
4635 +               (B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)\r
4636 +\r
4637 +#define SQUASHFS_COMPRESSED(B)         (!((B) & SQUASHFS_COMPRESSED_BIT))\r
4638 +\r
4639 +#define SQUASHFS_COMPRESSED_BIT_BLOCK          (1 << 24)\r
4640 +\r
4641 +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)      (((B) & \\r
4642 +       ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \\r
4643 +       ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)\r
4644 +\r
4645 +#define SQUASHFS_COMPRESSED_BLOCK(B)   (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))\r
4646 +\r
4647 +/*\r
4648 + * Inode number ops.  Inodes consist of a compressed block number, and an\r
4649 + * uncompressed  offset within that block\r
4650 + */\r
4651 +#define SQUASHFS_INODE_BLK(a)          ((unsigned int) ((a) >> 16))\r
4652 +\r
4653 +#define SQUASHFS_INODE_OFFSET(a)       ((unsigned int) ((a) & 0xffff))\r
4654 +\r
4655 +#define SQUASHFS_MKINODE(A, B)         ((squashfs_inode_t)(((squashfs_inode_t) (A)\\r
4656 +                                       << 16) + (B)))\r
4657 +\r
4658 +/* Compute 32 bit VFS inode number from squashfs inode number */\r
4659 +#define SQUASHFS_MK_VFS_INODE(a, b)    ((unsigned int) (((a) << 8) + \\r
4660 +                                       ((b) >> 2) + 1))\r
4661 +/* XXX */\r
4662 +\r
4663 +/* Translate between VFS mode and squashfs mode */\r
4664 +#define SQUASHFS_MODE(a)               ((a) & 0xfff)\r
4665 +\r
4666 +/* fragment and fragment table defines */\r
4667 +#define SQUASHFS_FRAGMENT_BYTES(A)     ((A) * sizeof(struct squashfs_fragment_entry))\r
4668 +\r
4669 +#define SQUASHFS_FRAGMENT_INDEX(A)     (SQUASHFS_FRAGMENT_BYTES(A) / \\r
4670 +                                       SQUASHFS_METADATA_SIZE)\r
4671 +\r
4672 +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)      (SQUASHFS_FRAGMENT_BYTES(A) % \\r
4673 +                                               SQUASHFS_METADATA_SIZE)\r
4674 +\r
4675 +#define SQUASHFS_FRAGMENT_INDEXES(A)   ((SQUASHFS_FRAGMENT_BYTES(A) + \\r
4676 +                                       SQUASHFS_METADATA_SIZE - 1) / \\r
4677 +                                       SQUASHFS_METADATA_SIZE)\r
4678 +\r
4679 +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)       (SQUASHFS_FRAGMENT_INDEXES(A) *\\r
4680 +                                               sizeof(long long))\r
4681 +\r
4682 +/* inode lookup table defines */\r
4683 +#define SQUASHFS_LOOKUP_BYTES(A)       ((A) * sizeof(squashfs_inode_t))\r
4684 +\r
4685 +#define SQUASHFS_LOOKUP_BLOCK(A)               (SQUASHFS_LOOKUP_BYTES(A) / \\r
4686 +                                               SQUASHFS_METADATA_SIZE)\r
4687 +\r
4688 +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A)                (SQUASHFS_LOOKUP_BYTES(A) % \\r
4689 +                                               SQUASHFS_METADATA_SIZE)\r
4690 +\r
4691 +#define SQUASHFS_LOOKUP_BLOCKS(A)      ((SQUASHFS_LOOKUP_BYTES(A) + \\r
4692 +                                       SQUASHFS_METADATA_SIZE - 1) / \\r
4693 +                                       SQUASHFS_METADATA_SIZE)\r
4694 +\r
4695 +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\\r
4696 +                                       sizeof(long long))\r
4697 +\r
4698 +/* cached data constants for filesystem */\r
4699 +#define SQUASHFS_CACHED_BLKS           8\r
4700 +\r
4701 +#define SQUASHFS_MAX_FILE_SIZE_LOG     64\r
4702 +\r
4703 +#define SQUASHFS_MAX_FILE_SIZE         ((long long) 1 << \\r
4704 +                                       (SQUASHFS_MAX_FILE_SIZE_LOG - 2))\r
4705 +\r
4706 +#define SQUASHFS_MARKER_BYTE           0xff\r
4707 +\r
4708 +/* meta index cache */\r
4709 +#define SQUASHFS_META_INDEXES  (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))\r
4710 +#define SQUASHFS_META_ENTRIES  31\r
4711 +#define SQUASHFS_META_NUMBER   8\r
4712 +#define SQUASHFS_SLOTS         4\r
4713 +\r
4714 +struct meta_entry {\r
4715 +       long long               data_block;\r
4716 +       unsigned int            index_block;\r
4717 +       unsigned short          offset;\r
4718 +       unsigned short          pad;\r
4719 +};\r
4720 +\r
4721 +struct meta_index {\r
4722 +       unsigned int            inode_number;\r
4723 +       unsigned int            offset;\r
4724 +       unsigned short          entries;\r
4725 +       unsigned short          skip;\r
4726 +       unsigned short          locked;\r
4727 +       unsigned short          pad;\r
4728 +       struct meta_entry       meta_entry[SQUASHFS_META_ENTRIES];\r
4729 +};\r
4730 +\r
4731 +\r
4732 +/*\r
4733 + * definitions for structures on disk\r
4734 + */\r
4735 +\r
4736 +typedef long long              squashfs_block_t;\r
4737 +typedef long long              squashfs_inode_t;\r
4738 +\r
4739 +struct squashfs_super_block {\r
4740 +       unsigned int            s_magic;\r
4741 +       unsigned int            inodes;\r
4742 +       unsigned int            bytes_used_2;\r
4743 +       unsigned int            uid_start_2;\r
4744 +       unsigned int            guid_start_2;\r
4745 +       unsigned int            inode_table_start_2;\r
4746 +       unsigned int            directory_table_start_2;\r
4747 +       unsigned int            s_major:16;\r
4748 +       unsigned int            s_minor:16;\r
4749 +       unsigned int            block_size_1:16;\r
4750 +       unsigned int            block_log:16;\r
4751 +       unsigned int            flags:8;\r
4752 +       unsigned int            no_uids:8;\r
4753 +       unsigned int            no_guids:8;\r
4754 +       unsigned int            mkfs_time /* time of filesystem creation */;\r
4755 +       squashfs_inode_t        root_inode;\r
4756 +       unsigned int            block_size;\r
4757 +       unsigned int            fragments;\r
4758 +       unsigned int            fragment_table_start_2;\r
4759 +       long long               bytes_used;\r
4760 +       long long               uid_start;\r
4761 +       long long               guid_start;\r
4762 +       long long               inode_table_start;\r
4763 +       long long               directory_table_start;\r
4764 +       long long               fragment_table_start;\r
4765 +       long long               lookup_table_start;\r
4766 +} __attribute__ ((packed));\r
4767 +\r
4768 +struct squashfs_dir_index {\r
4769 +       unsigned int            index;\r
4770 +       unsigned int            start_block;\r
4771 +       unsigned char           size;\r
4772 +       unsigned char           name[0];\r
4773 +} __attribute__ ((packed));\r
4774 +\r
4775 +#define SQUASHFS_BASE_INODE_HEADER             \\r
4776 +       unsigned int            inode_type:4;   \\r
4777 +       unsigned int            mode:12;        \\r
4778 +       unsigned int            uid:8;          \\r
4779 +       unsigned int            guid:8;         \\r
4780 +       unsigned int            mtime;          \\r
4781 +       unsigned int            inode_number;\r
4782 +\r
4783 +struct squashfs_base_inode_header {\r
4784 +       SQUASHFS_BASE_INODE_HEADER;\r
4785 +} __attribute__ ((packed));\r
4786 +\r
4787 +struct squashfs_ipc_inode_header {\r
4788 +       SQUASHFS_BASE_INODE_HEADER;\r
4789 +       unsigned int            nlink;\r
4790 +} __attribute__ ((packed));\r
4791 +\r
4792 +struct squashfs_dev_inode_header {\r
4793 +       SQUASHFS_BASE_INODE_HEADER;\r
4794 +       unsigned int            nlink;\r
4795 +       unsigned short          rdev;\r
4796 +} __attribute__ ((packed));\r
4797 +       \r
4798 +struct squashfs_symlink_inode_header {\r
4799 +       SQUASHFS_BASE_INODE_HEADER;\r
4800 +       unsigned int            nlink;\r
4801 +       unsigned short          symlink_size;\r
4802 +       char                    symlink[0];\r
4803 +} __attribute__ ((packed));\r
4804 +\r
4805 +struct squashfs_reg_inode_header {\r
4806 +       SQUASHFS_BASE_INODE_HEADER;\r
4807 +       squashfs_block_t        start_block;\r
4808 +       unsigned int            fragment;\r
4809 +       unsigned int            offset;\r
4810 +       unsigned int            file_size;\r
4811 +       unsigned short          block_list[0];\r
4812 +} __attribute__ ((packed));\r
4813 +\r
4814 +struct squashfs_lreg_inode_header {\r
4815 +       SQUASHFS_BASE_INODE_HEADER;\r
4816 +       unsigned int            nlink;\r
4817 +       squashfs_block_t        start_block;\r
4818 +       unsigned int            fragment;\r
4819 +       unsigned int            offset;\r
4820 +       long long               file_size;\r
4821 +       unsigned short          block_list[0];\r
4822 +} __attribute__ ((packed));\r
4823 +\r
4824 +struct squashfs_dir_inode_header {\r
4825 +       SQUASHFS_BASE_INODE_HEADER;\r
4826 +       unsigned int            nlink;\r
4827 +       unsigned int            file_size:19;\r
4828 +       unsigned int            offset:13;\r
4829 +       unsigned int            start_block;\r
4830 +       unsigned int            parent_inode;\r
4831 +} __attribute__  ((packed));\r
4832 +\r
4833 +struct squashfs_ldir_inode_header {\r
4834 +       SQUASHFS_BASE_INODE_HEADER;\r
4835 +       unsigned int            nlink;\r
4836 +       unsigned int            file_size:27;\r
4837 +       unsigned int            offset:13;\r
4838 +       unsigned int            start_block;\r
4839 +       unsigned int            i_count:16;\r
4840 +       unsigned int            parent_inode;\r
4841 +       struct squashfs_dir_index       index[0];\r
4842 +} __attribute__  ((packed));\r
4843 +\r
4844 +union squashfs_inode_header {\r
4845 +       struct squashfs_base_inode_header       base;\r
4846 +       struct squashfs_dev_inode_header        dev;\r
4847 +       struct squashfs_symlink_inode_header    symlink;\r
4848 +       struct squashfs_reg_inode_header        reg;\r
4849 +       struct squashfs_lreg_inode_header       lreg;\r
4850 +       struct squashfs_dir_inode_header        dir;\r
4851 +       struct squashfs_ldir_inode_header       ldir;\r
4852 +       struct squashfs_ipc_inode_header        ipc;\r
4853 +};\r
4854 +       \r
4855 +struct squashfs_dir_entry {\r
4856 +       unsigned int            offset:13;\r
4857 +       unsigned int            type:3;\r
4858 +       unsigned int            size:8;\r
4859 +       int                     inode_number:16;\r
4860 +       char                    name[0];\r
4861 +} __attribute__ ((packed));\r
4862 +\r
4863 +struct squashfs_dir_header {\r
4864 +       unsigned int            count:8;\r
4865 +       unsigned int            start_block;\r
4866 +       unsigned int            inode_number;\r
4867 +} __attribute__ ((packed));\r
4868 +\r
4869 +struct squashfs_fragment_entry {\r
4870 +       long long               start_block;\r
4871 +       unsigned int            size;\r
4872 +       unsigned int            pending;\r
4873 +} __attribute__ ((packed));\r
4874 +\r
4875 +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);\r
4876 +extern int squashfs_uncompress_init(void);\r
4877 +extern int squashfs_uncompress_exit(void);\r
4878 +\r
4879 +/*\r
4880 + * macros to convert each packed bitfield structure from little endian to big\r
4881 + * endian and vice versa.  These are needed when creating or using a filesystem\r
4882 + * on a machine with different byte ordering to the target architecture.\r
4883 + *\r
4884 + */\r
4885 +\r
4886 +#define SQUASHFS_SWAP_START \\r
4887 +       int bits;\\r
4888 +       int b_pos;\\r
4889 +       unsigned long long val;\\r
4890 +       unsigned char *s;\\r
4891 +       unsigned char *d;\r
4892 +\r
4893 +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\\r
4894 +       SQUASHFS_SWAP_START\\r
4895 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\\r
4896 +       SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\\r
4897 +       SQUASHFS_SWAP((s)->inodes, d, 32, 32);\\r
4898 +       SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\\r
4899 +       SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\\r
4900 +       SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\\r
4901 +       SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\\r
4902 +       SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\\r
4903 +       SQUASHFS_SWAP((s)->s_major, d, 224, 16);\\r
4904 +       SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\\r
4905 +       SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\\r
4906 +       SQUASHFS_SWAP((s)->block_log, d, 272, 16);\\r
4907 +       SQUASHFS_SWAP((s)->flags, d, 288, 8);\\r
4908 +       SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\\r
4909 +       SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\\r
4910 +       SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\\r
4911 +       SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\\r
4912 +       SQUASHFS_SWAP((s)->block_size, d, 408, 32);\\r
4913 +       SQUASHFS_SWAP((s)->fragments, d, 440, 32);\\r
4914 +       SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\\r
4915 +       SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\\r
4916 +       SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\\r
4917 +       SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\\r
4918 +       SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\\r
4919 +       SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\\r
4920 +       SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\\r
4921 +       SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\\r
4922 +}\r
4923 +\r
4924 +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\\r
4925 +       SQUASHFS_MEMSET(s, d, n);\\r
4926 +       SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
4927 +       SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
4928 +       SQUASHFS_SWAP((s)->uid, d, 16, 8);\\r
4929 +       SQUASHFS_SWAP((s)->guid, d, 24, 8);\\r
4930 +       SQUASHFS_SWAP((s)->mtime, d, 32, 32);\\r
4931 +       SQUASHFS_SWAP((s)->inode_number, d, 64, 32);\r
4932 +\r
4933 +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\\r
4934 +       SQUASHFS_SWAP_START\\r
4935 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\\r
4936 +}\r
4937 +\r
4938 +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\\r
4939 +       SQUASHFS_SWAP_START\\r
4940 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
4941 +                       sizeof(struct squashfs_ipc_inode_header))\\r
4942 +       SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
4943 +}\r
4944 +\r
4945 +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\\r
4946 +       SQUASHFS_SWAP_START\\r
4947 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
4948 +                       sizeof(struct squashfs_dev_inode_header)); \\r
4949 +       SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
4950 +       SQUASHFS_SWAP((s)->rdev, d, 128, 16);\\r
4951 +}\r
4952 +\r
4953 +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\\r
4954 +       SQUASHFS_SWAP_START\\r
4955 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
4956 +                       sizeof(struct squashfs_symlink_inode_header));\\r
4957 +       SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
4958 +       SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\\r
4959 +}\r
4960 +\r
4961 +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\\r
4962 +       SQUASHFS_SWAP_START\\r
4963 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
4964 +                       sizeof(struct squashfs_reg_inode_header));\\r
4965 +       SQUASHFS_SWAP((s)->start_block, d, 96, 64);\\r
4966 +       SQUASHFS_SWAP((s)->fragment, d, 160, 32);\\r
4967 +       SQUASHFS_SWAP((s)->offset, d, 192, 32);\\r
4968 +       SQUASHFS_SWAP((s)->file_size, d, 224, 32);\\r
4969 +}\r
4970 +\r
4971 +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\\r
4972 +       SQUASHFS_SWAP_START\\r
4973 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
4974 +                       sizeof(struct squashfs_lreg_inode_header));\\r
4975 +       SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
4976 +       SQUASHFS_SWAP((s)->start_block, d, 128, 64);\\r
4977 +       SQUASHFS_SWAP((s)->fragment, d, 192, 32);\\r
4978 +       SQUASHFS_SWAP((s)->offset, d, 224, 32);\\r
4979 +       SQUASHFS_SWAP((s)->file_size, d, 256, 64);\\r
4980 +}\r
4981 +\r
4982 +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\\r
4983 +       SQUASHFS_SWAP_START\\r
4984 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
4985 +                       sizeof(struct squashfs_dir_inode_header));\\r
4986 +       SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
4987 +       SQUASHFS_SWAP((s)->file_size, d, 128, 19);\\r
4988 +       SQUASHFS_SWAP((s)->offset, d, 147, 13);\\r
4989 +       SQUASHFS_SWAP((s)->start_block, d, 160, 32);\\r
4990 +       SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\\r
4991 +}\r
4992 +\r
4993 +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\\r
4994 +       SQUASHFS_SWAP_START\\r
4995 +       SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \\r
4996 +                       sizeof(struct squashfs_ldir_inode_header));\\r
4997 +       SQUASHFS_SWAP((s)->nlink, d, 96, 32);\\r
4998 +       SQUASHFS_SWAP((s)->file_size, d, 128, 27);\\r
4999 +       SQUASHFS_SWAP((s)->offset, d, 155, 13);\\r
5000 +       SQUASHFS_SWAP((s)->start_block, d, 168, 32);\\r
5001 +       SQUASHFS_SWAP((s)->i_count, d, 200, 16);\\r
5002 +       SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\\r
5003 +}\r
5004 +\r
5005 +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\\r
5006 +       SQUASHFS_SWAP_START\\r
5007 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\\r
5008 +       SQUASHFS_SWAP((s)->index, d, 0, 32);\\r
5009 +       SQUASHFS_SWAP((s)->start_block, d, 32, 32);\\r
5010 +       SQUASHFS_SWAP((s)->size, d, 64, 8);\\r
5011 +}\r
5012 +\r
5013 +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\\r
5014 +       SQUASHFS_SWAP_START\\r
5015 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\\r
5016 +       SQUASHFS_SWAP((s)->count, d, 0, 8);\\r
5017 +       SQUASHFS_SWAP((s)->start_block, d, 8, 32);\\r
5018 +       SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\\r
5019 +}\r
5020 +\r
5021 +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\\r
5022 +       SQUASHFS_SWAP_START\\r
5023 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\\r
5024 +       SQUASHFS_SWAP((s)->offset, d, 0, 13);\\r
5025 +       SQUASHFS_SWAP((s)->type, d, 13, 3);\\r
5026 +       SQUASHFS_SWAP((s)->size, d, 16, 8);\\r
5027 +       SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\\r
5028 +}\r
5029 +\r
5030 +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\\r
5031 +       SQUASHFS_SWAP_START\\r
5032 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\\r
5033 +       SQUASHFS_SWAP((s)->start_block, d, 0, 64);\\r
5034 +       SQUASHFS_SWAP((s)->size, d, 64, 32);\\r
5035 +}\r
5036 +\r
5037 +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)\r
5038 +\r
5039 +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\\r
5040 +       int entry;\\r
5041 +       int bit_position;\\r
5042 +       SQUASHFS_SWAP_START\\r
5043 +       SQUASHFS_MEMSET(s, d, n * 2);\\r
5044 +       for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
5045 +                       16)\\r
5046 +               SQUASHFS_SWAP(s[entry], d, bit_position, 16);\\r
5047 +}\r
5048 +\r
5049 +#define SQUASHFS_SWAP_INTS(s, d, n) {\\r
5050 +       int entry;\\r
5051 +       int bit_position;\\r
5052 +       SQUASHFS_SWAP_START\\r
5053 +       SQUASHFS_MEMSET(s, d, n * 4);\\r
5054 +       for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
5055 +                       32)\\r
5056 +               SQUASHFS_SWAP(s[entry], d, bit_position, 32);\\r
5057 +}\r
5058 +\r
5059 +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\\r
5060 +       int entry;\\r
5061 +       int bit_position;\\r
5062 +       SQUASHFS_SWAP_START\\r
5063 +       SQUASHFS_MEMSET(s, d, n * 8);\\r
5064 +       for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
5065 +                       64)\\r
5066 +               SQUASHFS_SWAP(s[entry], d, bit_position, 64);\\r
5067 +}\r
5068 +\r
5069 +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\\r
5070 +       int entry;\\r
5071 +       int bit_position;\\r
5072 +       SQUASHFS_SWAP_START\\r
5073 +       SQUASHFS_MEMSET(s, d, n * bits / 8);\\r
5074 +       for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \\r
5075 +                       bits)\\r
5076 +               SQUASHFS_SWAP(s[entry], d, bit_position, bits);\\r
5077 +}\r
5078 +\r
5079 +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\r
5080 +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)\r
5081 +\r
5082 +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY\r
5083 +\r
5084 +struct squashfs_base_inode_header_1 {\r
5085 +       unsigned int            inode_type:4;\r
5086 +       unsigned int            mode:12; /* protection */\r
5087 +       unsigned int            uid:4; /* index into uid table */\r
5088 +       unsigned int            guid:4; /* index into guid table */\r
5089 +} __attribute__ ((packed));\r
5090 +\r
5091 +struct squashfs_ipc_inode_header_1 {\r
5092 +       unsigned int            inode_type:4;\r
5093 +       unsigned int            mode:12; /* protection */\r
5094 +       unsigned int            uid:4; /* index into uid table */\r
5095 +       unsigned int            guid:4; /* index into guid table */\r
5096 +       unsigned int            type:4;\r
5097 +       unsigned int            offset:4;\r
5098 +} __attribute__ ((packed));\r
5099 +\r
5100 +struct squashfs_dev_inode_header_1 {\r
5101 +       unsigned int            inode_type:4;\r
5102 +       unsigned int            mode:12; /* protection */\r
5103 +       unsigned int            uid:4; /* index into uid table */\r
5104 +       unsigned int            guid:4; /* index into guid table */\r
5105 +       unsigned short          rdev;\r
5106 +} __attribute__ ((packed));\r
5107 +       \r
5108 +struct squashfs_symlink_inode_header_1 {\r
5109 +       unsigned int            inode_type:4;\r
5110 +       unsigned int            mode:12; /* protection */\r
5111 +       unsigned int            uid:4; /* index into uid table */\r
5112 +       unsigned int            guid:4; /* index into guid table */\r
5113 +       unsigned short          symlink_size;\r
5114 +       char                    symlink[0];\r
5115 +} __attribute__ ((packed));\r
5116 +\r
5117 +struct squashfs_reg_inode_header_1 {\r
5118 +       unsigned int            inode_type:4;\r
5119 +       unsigned int            mode:12; /* protection */\r
5120 +       unsigned int            uid:4; /* index into uid table */\r
5121 +       unsigned int            guid:4; /* index into guid table */\r
5122 +       unsigned int            mtime;\r
5123 +       unsigned int            start_block;\r
5124 +       unsigned int            file_size:32;\r
5125 +       unsigned short          block_list[0];\r
5126 +} __attribute__ ((packed));\r
5127 +\r
5128 +struct squashfs_dir_inode_header_1 {\r
5129 +       unsigned int            inode_type:4;\r
5130 +       unsigned int            mode:12; /* protection */\r
5131 +       unsigned int            uid:4; /* index into uid table */\r
5132 +       unsigned int            guid:4; /* index into guid table */\r
5133 +       unsigned int            file_size:19;\r
5134 +       unsigned int            offset:13;\r
5135 +       unsigned int            mtime;\r
5136 +       unsigned int            start_block:24;\r
5137 +} __attribute__  ((packed));\r
5138 +\r
5139 +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \\r
5140 +       SQUASHFS_MEMSET(s, d, n);\\r
5141 +       SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
5142 +       SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
5143 +       SQUASHFS_SWAP((s)->uid, d, 16, 4);\\r
5144 +       SQUASHFS_SWAP((s)->guid, d, 20, 4);\r
5145 +\r
5146 +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\\r
5147 +       SQUASHFS_SWAP_START\\r
5148 +       SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\\r
5149 +}\r
5150 +\r
5151 +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\\r
5152 +       SQUASHFS_SWAP_START\\r
5153 +       SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
5154 +                       sizeof(struct squashfs_ipc_inode_header_1));\\r
5155 +       SQUASHFS_SWAP((s)->type, d, 24, 4);\\r
5156 +       SQUASHFS_SWAP((s)->offset, d, 28, 4);\\r
5157 +}\r
5158 +\r
5159 +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\\r
5160 +       SQUASHFS_SWAP_START\\r
5161 +       SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
5162 +                       sizeof(struct squashfs_dev_inode_header_1));\\r
5163 +       SQUASHFS_SWAP((s)->rdev, d, 24, 16);\\r
5164 +}\r
5165 +\r
5166 +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\\r
5167 +       SQUASHFS_SWAP_START\\r
5168 +       SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
5169 +                       sizeof(struct squashfs_symlink_inode_header_1));\\r
5170 +       SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\\r
5171 +}\r
5172 +\r
5173 +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\\r
5174 +       SQUASHFS_SWAP_START\\r
5175 +       SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
5176 +                       sizeof(struct squashfs_reg_inode_header_1));\\r
5177 +       SQUASHFS_SWAP((s)->mtime, d, 24, 32);\\r
5178 +       SQUASHFS_SWAP((s)->start_block, d, 56, 32);\\r
5179 +       SQUASHFS_SWAP((s)->file_size, d, 88, 32);\\r
5180 +}\r
5181 +\r
5182 +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\\r
5183 +       SQUASHFS_SWAP_START\\r
5184 +       SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \\r
5185 +                       sizeof(struct squashfs_dir_inode_header_1));\\r
5186 +       SQUASHFS_SWAP((s)->file_size, d, 24, 19);\\r
5187 +       SQUASHFS_SWAP((s)->offset, d, 43, 13);\\r
5188 +       SQUASHFS_SWAP((s)->mtime, d, 56, 32);\\r
5189 +       SQUASHFS_SWAP((s)->start_block, d, 88, 24);\\r
5190 +}\r
5191 +\r
5192 +#endif\r
5193 +\r
5194 +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY\r
5195 +\r
5196 +struct squashfs_dir_index_2 {\r
5197 +       unsigned int            index:27;\r
5198 +       unsigned int            start_block:29;\r
5199 +       unsigned char           size;\r
5200 +       unsigned char           name[0];\r
5201 +} __attribute__ ((packed));\r
5202 +\r
5203 +struct squashfs_base_inode_header_2 {\r
5204 +       unsigned int            inode_type:4;\r
5205 +       unsigned int            mode:12; /* protection */\r
5206 +       unsigned int            uid:8; /* index into uid table */\r
5207 +       unsigned int            guid:8; /* index into guid table */\r
5208 +} __attribute__ ((packed));\r
5209 +\r
5210 +struct squashfs_ipc_inode_header_2 {\r
5211 +       unsigned int            inode_type:4;\r
5212 +       unsigned int            mode:12; /* protection */\r
5213 +       unsigned int            uid:8; /* index into uid table */\r
5214 +       unsigned int            guid:8; /* index into guid table */\r
5215 +} __attribute__ ((packed));\r
5216 +\r
5217 +struct squashfs_dev_inode_header_2 {\r
5218 +       unsigned int            inode_type:4;\r
5219 +       unsigned int            mode:12; /* protection */\r
5220 +       unsigned int            uid:8; /* index into uid table */\r
5221 +       unsigned int            guid:8; /* index into guid table */\r
5222 +       unsigned short          rdev;\r
5223 +} __attribute__ ((packed));\r
5224 +       \r
5225 +struct squashfs_symlink_inode_header_2 {\r
5226 +       unsigned int            inode_type:4;\r
5227 +       unsigned int            mode:12; /* protection */\r
5228 +       unsigned int            uid:8; /* index into uid table */\r
5229 +       unsigned int            guid:8; /* index into guid table */\r
5230 +       unsigned short          symlink_size;\r
5231 +       char                    symlink[0];\r
5232 +} __attribute__ ((packed));\r
5233 +\r
5234 +struct squashfs_reg_inode_header_2 {\r
5235 +       unsigned int            inode_type:4;\r
5236 +       unsigned int            mode:12; /* protection */\r
5237 +       unsigned int            uid:8; /* index into uid table */\r
5238 +       unsigned int            guid:8; /* index into guid table */\r
5239 +       unsigned int            mtime;\r
5240 +       unsigned int            start_block;\r
5241 +       unsigned int            fragment;\r
5242 +       unsigned int            offset;\r
5243 +       unsigned int            file_size:32;\r
5244 +       unsigned short          block_list[0];\r
5245 +} __attribute__ ((packed));\r
5246 +\r
5247 +struct squashfs_dir_inode_header_2 {\r
5248 +       unsigned int            inode_type:4;\r
5249 +       unsigned int            mode:12; /* protection */\r
5250 +       unsigned int            uid:8; /* index into uid table */\r
5251 +       unsigned int            guid:8; /* index into guid table */\r
5252 +       unsigned int            file_size:19;\r
5253 +       unsigned int            offset:13;\r
5254 +       unsigned int            mtime;\r
5255 +       unsigned int            start_block:24;\r
5256 +} __attribute__  ((packed));\r
5257 +\r
5258 +struct squashfs_ldir_inode_header_2 {\r
5259 +       unsigned int            inode_type:4;\r
5260 +       unsigned int            mode:12; /* protection */\r
5261 +       unsigned int            uid:8; /* index into uid table */\r
5262 +       unsigned int            guid:8; /* index into guid table */\r
5263 +       unsigned int            file_size:27;\r
5264 +       unsigned int            offset:13;\r
5265 +       unsigned int            mtime;\r
5266 +       unsigned int            start_block:24;\r
5267 +       unsigned int            i_count:16;\r
5268 +       struct squashfs_dir_index_2     index[0];\r
5269 +} __attribute__  ((packed));\r
5270 +\r
5271 +union squashfs_inode_header_2 {\r
5272 +       struct squashfs_base_inode_header_2     base;\r
5273 +       struct squashfs_dev_inode_header_2      dev;\r
5274 +       struct squashfs_symlink_inode_header_2  symlink;\r
5275 +       struct squashfs_reg_inode_header_2      reg;\r
5276 +       struct squashfs_dir_inode_header_2      dir;\r
5277 +       struct squashfs_ldir_inode_header_2     ldir;\r
5278 +       struct squashfs_ipc_inode_header_2      ipc;\r
5279 +};\r
5280 +       \r
5281 +struct squashfs_dir_header_2 {\r
5282 +       unsigned int            count:8;\r
5283 +       unsigned int            start_block:24;\r
5284 +} __attribute__ ((packed));\r
5285 +\r
5286 +struct squashfs_dir_entry_2 {\r
5287 +       unsigned int            offset:13;\r
5288 +       unsigned int            type:3;\r
5289 +       unsigned int            size:8;\r
5290 +       char                    name[0];\r
5291 +} __attribute__ ((packed));\r
5292 +\r
5293 +struct squashfs_fragment_entry_2 {\r
5294 +       unsigned int            start_block;\r
5295 +       unsigned int            size;\r
5296 +} __attribute__ ((packed));\r
5297 +\r
5298 +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\r
5299 +       SQUASHFS_MEMSET(s, d, n);\\r
5300 +       SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\\r
5301 +       SQUASHFS_SWAP((s)->mode, d, 4, 12);\\r
5302 +       SQUASHFS_SWAP((s)->uid, d, 16, 8);\\r
5303 +       SQUASHFS_SWAP((s)->guid, d, 24, 8);\\r
5304 +\r
5305 +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\\r
5306 +       SQUASHFS_SWAP_START\\r
5307 +       SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\\r
5308 +}\r
5309 +\r
5310 +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \\r
5311 +       SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))\r
5312 +\r
5313 +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\\r
5314 +       SQUASHFS_SWAP_START\\r
5315 +       SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
5316 +                       sizeof(struct squashfs_dev_inode_header_2)); \\r
5317 +       SQUASHFS_SWAP((s)->rdev, d, 32, 16);\\r
5318 +}\r
5319 +\r
5320 +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\\r
5321 +       SQUASHFS_SWAP_START\\r
5322 +       SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
5323 +                       sizeof(struct squashfs_symlink_inode_header_2));\\r
5324 +       SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\\r
5325 +}\r
5326 +\r
5327 +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\\r
5328 +       SQUASHFS_SWAP_START\\r
5329 +       SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
5330 +                       sizeof(struct squashfs_reg_inode_header_2));\\r
5331 +       SQUASHFS_SWAP((s)->mtime, d, 32, 32);\\r
5332 +       SQUASHFS_SWAP((s)->start_block, d, 64, 32);\\r
5333 +       SQUASHFS_SWAP((s)->fragment, d, 96, 32);\\r
5334 +       SQUASHFS_SWAP((s)->offset, d, 128, 32);\\r
5335 +       SQUASHFS_SWAP((s)->file_size, d, 160, 32);\\r
5336 +}\r
5337 +\r
5338 +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\\r
5339 +       SQUASHFS_SWAP_START\\r
5340 +       SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
5341 +                       sizeof(struct squashfs_dir_inode_header_2));\\r
5342 +       SQUASHFS_SWAP((s)->file_size, d, 32, 19);\\r
5343 +       SQUASHFS_SWAP((s)->offset, d, 51, 13);\\r
5344 +       SQUASHFS_SWAP((s)->mtime, d, 64, 32);\\r
5345 +       SQUASHFS_SWAP((s)->start_block, d, 96, 24);\\r
5346 +}\r
5347 +\r
5348 +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\\r
5349 +       SQUASHFS_SWAP_START\\r
5350 +       SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \\r
5351 +                       sizeof(struct squashfs_ldir_inode_header_2));\\r
5352 +       SQUASHFS_SWAP((s)->file_size, d, 32, 27);\\r
5353 +       SQUASHFS_SWAP((s)->offset, d, 59, 13);\\r
5354 +       SQUASHFS_SWAP((s)->mtime, d, 72, 32);\\r
5355 +       SQUASHFS_SWAP((s)->start_block, d, 104, 24);\\r
5356 +       SQUASHFS_SWAP((s)->i_count, d, 128, 16);\\r
5357 +}\r
5358 +\r
5359 +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\\r
5360 +       SQUASHFS_SWAP_START\\r
5361 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\\r
5362 +       SQUASHFS_SWAP((s)->index, d, 0, 27);\\r
5363 +       SQUASHFS_SWAP((s)->start_block, d, 27, 29);\\r
5364 +       SQUASHFS_SWAP((s)->size, d, 56, 8);\\r
5365 +}\r
5366 +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\\r
5367 +       SQUASHFS_SWAP_START\\r
5368 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\\r
5369 +       SQUASHFS_SWAP((s)->count, d, 0, 8);\\r
5370 +       SQUASHFS_SWAP((s)->start_block, d, 8, 24);\\r
5371 +}\r
5372 +\r
5373 +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\\r
5374 +       SQUASHFS_SWAP_START\\r
5375 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\\r
5376 +       SQUASHFS_SWAP((s)->offset, d, 0, 13);\\r
5377 +       SQUASHFS_SWAP((s)->type, d, 13, 3);\\r
5378 +       SQUASHFS_SWAP((s)->size, d, 16, 8);\\r
5379 +}\r
5380 +\r
5381 +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\\r
5382 +       SQUASHFS_SWAP_START\\r
5383 +       SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\\r
5384 +       SQUASHFS_SWAP((s)->start_block, d, 0, 32);\\r
5385 +       SQUASHFS_SWAP((s)->size, d, 32, 32);\\r
5386 +}\r
5387 +\r
5388 +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)\r
5389 +\r
5390 +/* fragment and fragment table defines */\r
5391 +#define SQUASHFS_FRAGMENT_BYTES_2(A)   (A * sizeof(struct squashfs_fragment_entry_2))\r
5392 +\r
5393 +#define SQUASHFS_FRAGMENT_INDEX_2(A)   (SQUASHFS_FRAGMENT_BYTES_2(A) / \\r
5394 +                                       SQUASHFS_METADATA_SIZE)\r
5395 +\r
5396 +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)    (SQUASHFS_FRAGMENT_BYTES_2(A) % \\r
5397 +                                               SQUASHFS_METADATA_SIZE)\r
5398 +\r
5399 +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \\r
5400 +                                       SQUASHFS_METADATA_SIZE - 1) / \\r
5401 +                                       SQUASHFS_METADATA_SIZE)\r
5402 +\r
5403 +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)     (SQUASHFS_FRAGMENT_INDEXES_2(A) *\\r
5404 +                                               sizeof(int))\r
5405 +\r
5406 +#endif\r
5407 +\r
5408 +#ifdef __KERNEL__\r
5409 +\r
5410 +/*\r
5411 + * macros used to swap each structure entry, taking into account\r
5412 + * bitfields and different bitfield placing conventions on differing\r
5413 + * architectures\r
5414 + */\r
5415 +\r
5416 +#include <asm/byteorder.h>\r
5417 +\r
5418 +#ifdef __BIG_ENDIAN\r
5419 +       /* convert from little endian to big endian */\r
5420 +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \\r
5421 +               tbits, b_pos)\r
5422 +#else\r
5423 +       /* convert from big endian to little endian */ \r
5424 +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \\r
5425 +               tbits, 64 - tbits - b_pos)\r
5426 +#endif\r
5427 +\r
5428 +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\\r
5429 +       b_pos = pos % 8;\\r
5430 +       val = 0;\\r
5431 +       s = (unsigned char *)p + (pos / 8);\\r
5432 +       d = ((unsigned char *) &val) + 7;\\r
5433 +       for(bits = 0; bits < (tbits + b_pos); bits += 8) \\r
5434 +               *d-- = *s++;\\r
5435 +       value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\\r
5436 +}\r
5437 +\r
5438 +#define SQUASHFS_MEMSET(s, d, n)       memset(s, 0, n);\r
5439 +\r
5440 +#endif\r
5441 +#endif\r
5442 diff -urN linux-2.6.23/include/linux/squashfs_fs_i.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h\r
5443 --- linux-2.6.23/include/linux/squashfs_fs_i.h  1969-12-31 19:00:00.000000000 -0500\r
5444 +++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_i.h   2007-10-14 10:24:31.000000000 -0400\r
5445 @@ -0,0 +1,45 @@\r
5446 +#ifndef SQUASHFS_FS_I\r
5447 +#define SQUASHFS_FS_I\r
5448 +/*\r
5449 + * Squashfs\r
5450 + *\r
5451 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
5452 + * Phillip Lougher <phillip@lougher.org.uk>\r
5453 + *\r
5454 + * This program is free software; you can redistribute it and/or\r
5455 + * modify it under the terms of the GNU General Public License\r
5456 + * as published by the Free Software Foundation; either version 2,\r
5457 + * or (at your option) any later version.\r
5458 + *\r
5459 + * This program is distributed in the hope that it will be useful,\r
5460 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
5461 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
5462 + * GNU General Public License for more details.\r
5463 + *\r
5464 + * You should have received a copy of the GNU General Public License\r
5465 + * along with this program; if not, write to the Free Software\r
5466 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
5467 + *\r
5468 + * squashfs_fs_i.h\r
5469 + */\r
5470 +\r
5471 +struct squashfs_inode_info {\r
5472 +       long long       start_block;\r
5473 +       unsigned int    offset;\r
5474 +       union {\r
5475 +               struct {\r
5476 +                       long long       fragment_start_block;\r
5477 +                       unsigned int    fragment_size;\r
5478 +                       unsigned int    fragment_offset;\r
5479 +                       long long       block_list_start;\r
5480 +               } s1;\r
5481 +               struct {\r
5482 +                       long long       directory_index_start;\r
5483 +                       unsigned int    directory_index_offset;\r
5484 +                       unsigned int    directory_index_count;\r
5485 +                       unsigned int    parent_inode;\r
5486 +               } s2;\r
5487 +       } u;\r
5488 +       struct inode    vfs_inode;\r
5489 +};\r
5490 +#endif\r
5491 diff -urN linux-2.6.23/include/linux/squashfs_fs_sb.h linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h\r
5492 --- linux-2.6.23/include/linux/squashfs_fs_sb.h 1969-12-31 19:00:00.000000000 -0500\r
5493 +++ linux-2.6.23.sqlzma/include/linux/squashfs_fs_sb.h  2007-10-14 14:32:50.000000000 -0400\r
5494 @@ -0,0 +1,73 @@\r
5495 +#ifndef SQUASHFS_FS_SB\r
5496 +#define SQUASHFS_FS_SB\r
5497 +/*\r
5498 + * Squashfs\r
5499 + *\r
5500 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007\r
5501 + * Phillip Lougher <phillip@lougher.org.uk>\r
5502 + *\r
5503 + * This program is free software; you can redistribute it and/or\r
5504 + * modify it under the terms of the GNU General Public License\r
5505 + * as published by the Free Software Foundation; either version 2,\r
5506 + * or (at your option) any later version.\r
5507 + *\r
5508 + * This program is distributed in the hope that it will be useful,\r
5509 + * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
5510 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
5511 + * GNU General Public License for more details.\r
5512 + *\r
5513 + * You should have received a copy of the GNU General Public License\r
5514 + * along with this program; if not, write to the Free Software\r
5515 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
5516 + *\r
5517 + * squashfs_fs_sb.h\r
5518 + */\r
5519 +\r
5520 +#include <linux/squashfs_fs.h>\r
5521 +\r
5522 +struct squashfs_cache {\r
5523 +       long long       block;\r
5524 +       int             length;\r
5525 +       long long       next_index;\r
5526 +       char            *data;\r
5527 +};\r
5528 +\r
5529 +struct squashfs_fragment_cache {\r
5530 +       long long       block;\r
5531 +       int             length;\r
5532 +       unsigned int    locked;\r
5533 +       char            *data;\r
5534 +};\r
5535 +\r
5536 +struct squashfs_sb_info {\r
5537 +       struct squashfs_super_block     sblk;\r
5538 +       int                     devblksize;\r
5539 +       int                     devblksize_log2;\r
5540 +       int                     swap;\r
5541 +       struct squashfs_cache   *block_cache;\r
5542 +       struct squashfs_fragment_cache  *fragment;\r
5543 +       int                     next_cache;\r
5544 +       int                     next_fragment;\r
5545 +       int                     next_meta_index;\r
5546 +       unsigned int            *uid;\r
5547 +       unsigned int            *guid;\r
5548 +       long long               *fragment_index;\r
5549 +       unsigned int            *fragment_index_2;\r
5550 +       char                    *read_page;\r
5551 +       //struct mutex          read_data_mutex;\r
5552 +       struct mutex            read_page_mutex;\r
5553 +       struct mutex            block_cache_mutex;\r
5554 +       struct mutex            fragment_mutex;\r
5555 +       struct mutex            meta_index_mutex;\r
5556 +       wait_queue_head_t       waitq;\r
5557 +       wait_queue_head_t       fragment_wait_queue;\r
5558 +       struct meta_index       *meta_index;\r
5559 +       long long               *inode_lookup_table;\r
5560 +       int                     (*read_inode)(struct inode *i,  squashfs_inode_t \\r
5561 +                               inode);\r
5562 +       long long               (*read_blocklist)(struct inode *inode, int \\r
5563 +                               index, int readahead_blks, char *block_list, \\r
5564 +                               unsigned short **block_p, unsigned int *bsize);\r
5565 +       int                     (*read_fragment_index_table)(struct super_block *s);\r
5566 +};\r
5567 +#endif\r
5568 diff -urN linux-2.6.23/init/do_mounts_rd.c linux-2.6.23.sqlzma/init/do_mounts_rd.c\r
5569 --- linux-2.6.23/init/do_mounts_rd.c    2007-10-09 16:31:38.000000000 -0400\r
5570 +++ linux-2.6.23.sqlzma/init/do_mounts_rd.c     2007-10-14 10:24:31.000000000 -0400\r
5571 @@ -5,6 +5,7 @@\r
5572  #include <linux/ext2_fs.h>\r
5573  #include <linux/romfs_fs.h>\r
5574  #include <linux/cramfs_fs.h>\r
5575 +#include <linux/squashfs_fs.h>\r
5576  #include <linux/initrd.h>\r
5577  #include <linux/string.h>\r
5578  \r
5579 @@ -39,6 +40,7 @@\r
5580   * numbers could not be found.\r
5581   *\r
5582   * We currently check for the following magic numbers:\r
5583 + *      squashfs\r
5584   *     minix\r
5585   *     ext2\r
5586   *     romfs\r
5587 @@ -53,6 +55,7 @@\r
5588         struct ext2_super_block *ext2sb;\r
5589         struct romfs_super_block *romfsb;\r
5590         struct cramfs_super *cramfsb;\r
5591 +       struct squashfs_super_block *squashfsb;\r
5592         int nblocks = -1;\r
5593         unsigned char *buf;\r
5594  \r
5595 @@ -64,6 +67,7 @@\r
5596         ext2sb = (struct ext2_super_block *) buf;\r
5597         romfsb = (struct romfs_super_block *) buf;\r
5598         cramfsb = (struct cramfs_super *) buf;\r
5599 +       squashfsb = (struct squashfs_super_block *) buf;\r
5600         memset(buf, 0xe5, size);\r
5601  \r
5602         /*\r
5603 @@ -101,6 +105,18 @@\r
5604                 goto done;\r
5605         }\r
5606  \r
5607 +       /* squashfs is at block zero too */\r
5608 +       if (squashfsb->s_magic == SQUASHFS_MAGIC) {\r
5609 +               printk(KERN_NOTICE\r
5610 +                      "RAMDISK: squashfs filesystem found at block %d\n",\r
5611 +                      start_block);\r
5612 +               if (squashfsb->s_major < 3)\r
5613 +                       nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;\r
5614 +               else\r
5615 +                       nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;\r
5616 +               goto done;\r
5617 +       }\r
5618 +\r
5619         /*\r
5620          * Read block 1 to test for minix and ext2 superblock\r
5621          */\r