omap3-pandora-kernel2: update
[openpandora.oe.git] / recipes / linux / omap3-pandora-kernel / squashfs / 0006-SquashFS-Backport-SquashFS4-to-our-2.6.27-tree.patch
1 From 59bc81578d57166e3a4c4626a679f3333739b4bb Mon Sep 17 00:00:00 2001
2 From: David-John Willis <John.Willis@Distant-earth.com>
3 Date: Mon, 21 Dec 2009 19:44:51 +0000
4 Subject: [PATCH 6/6] SquashFS: Backport SquashFS4 to our 2.6.27 tree.
5
6 ---
7  fs/Kconfig                   |    2 +
8  fs/Makefile                  |    1 +
9  fs/squashfs/Kconfig          |   51 +++++
10  fs/squashfs/Makefile         |    7 +
11  fs/squashfs/block.c          |  270 +++++++++++++++++++++++
12  fs/squashfs/cache.c          |  413 ++++++++++++++++++++++++++++++++++
13  fs/squashfs/dir.c            |  235 ++++++++++++++++++++
14  fs/squashfs/export.c         |  172 ++++++++++++++
15  fs/squashfs/file.c           |  502 ++++++++++++++++++++++++++++++++++++++++++
16  fs/squashfs/fragment.c       |   98 ++++++++
17  fs/squashfs/id.c             |   94 ++++++++
18  fs/squashfs/inode.c          |  348 +++++++++++++++++++++++++++++
19  fs/squashfs/namei.c          |  242 ++++++++++++++++++++
20  fs/squashfs/squashfs.h       |   90 ++++++++
21  fs/squashfs/squashfs_fs.h    |  382 ++++++++++++++++++++++++++++++++
22  fs/squashfs/squashfs_fs_i.h  |   45 ++++
23  fs/squashfs/squashfs_fs_sb.h |   76 +++++++
24  fs/squashfs/super.c          |  454 ++++++++++++++++++++++++++++++++++++++
25  fs/squashfs/symlink.c        |  118 ++++++++++
26  init/do_mounts_rd.c          |   14 ++
27  20 files changed, 3614 insertions(+), 0 deletions(-)
28  create mode 100644 fs/squashfs/Kconfig
29  create mode 100644 fs/squashfs/Makefile
30  create mode 100644 fs/squashfs/block.c
31  create mode 100644 fs/squashfs/cache.c
32  create mode 100644 fs/squashfs/dir.c
33  create mode 100644 fs/squashfs/export.c
34  create mode 100644 fs/squashfs/file.c
35  create mode 100644 fs/squashfs/fragment.c
36  create mode 100644 fs/squashfs/id.c
37  create mode 100644 fs/squashfs/inode.c
38  create mode 100644 fs/squashfs/namei.c
39  create mode 100644 fs/squashfs/squashfs.h
40  create mode 100644 fs/squashfs/squashfs_fs.h
41  create mode 100644 fs/squashfs/squashfs_fs_i.h
42  create mode 100644 fs/squashfs/squashfs_fs_sb.h
43  create mode 100644 fs/squashfs/super.c
44  create mode 100644 fs/squashfs/symlink.c
45
46 diff --git a/fs/Kconfig b/fs/Kconfig
47 index abccb5d..bd989c0 100644
48 --- a/fs/Kconfig
49 +++ b/fs/Kconfig
50 @@ -1348,6 +1348,8 @@ config CRAMFS
51  
52           If unsure, say N.
53  
54 +source "fs/squashfs/Kconfig"
55 +
56  config VXFS_FS
57         tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
58         depends on BLOCK
59 diff --git a/fs/Makefile b/fs/Makefile
60 index a1482a5..0871ab5 100644
61 --- a/fs/Makefile
62 +++ b/fs/Makefile
63 @@ -74,6 +74,7 @@ obj-$(CONFIG_JBD)             += jbd/
64  obj-$(CONFIG_JBD2)             += jbd2/
65  obj-$(CONFIG_EXT2_FS)          += ext2/
66  obj-$(CONFIG_CRAMFS)           += cramfs/
67 +obj-$(CONFIG_SQUASHFS)         += squashfs/
68  obj-y                          += ramfs/
69  obj-$(CONFIG_HUGETLBFS)                += hugetlbfs/
70  obj-$(CONFIG_CODA_FS)          += coda/
71 diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
72 new file mode 100644
73 index 0000000..25a00d1
74 --- /dev/null
75 +++ b/fs/squashfs/Kconfig
76 @@ -0,0 +1,51 @@
77 +config SQUASHFS
78 +       tristate "SquashFS 4.0 - Squashed file system support"
79 +       depends on BLOCK
80 +       select ZLIB_INFLATE
81 +       help
82 +         Saying Y here includes support for SquashFS 4.0 (a Compressed
83 +         Read-Only File System).  Squashfs is a highly compressed read-only
84 +         filesystem for Linux.  It uses zlib compression to compress both
85 +         files, inodes and directories.  Inodes in the system are very small
86 +         and all blocks are packed to minimise data overhead. Block sizes
87 +         greater than 4K are supported up to a maximum of 1 Mbytes (default
88 +         block size 128K).  SquashFS 4.0 supports 64 bit filesystems and files
89 +         (larger than 4GB), full uid/gid information, hard links and
90 +         timestamps.  
91 +
92 +         Squashfs is intended for general read-only filesystem use, for
93 +         archival use (i.e. in cases where a .tar.gz file may be used), and in
94 +         embedded systems where low overhead is needed.  Further information
95 +         and tools are available from http://squashfs.sourceforge.net.
96 +
97 +         If you want to compile this as a module ( = code which can be
98 +         inserted in and removed from the running kernel whenever you want),
99 +         say M here and read <file:Documentation/modules.txt>.  The module
100 +         will be called squashfs.  Note that the root file system (the one
101 +         containing the directory /) cannot be compiled as a module.
102 +
103 +         If unsure, say N.
104 +
105 +config SQUASHFS_EMBEDDED
106 +
107 +       bool "Additional option for memory-constrained systems" 
108 +       depends on SQUASHFS
109 +       default n
110 +       help
111 +         Saying Y here allows you to specify cache size.
112 +
113 +         If unsure, say N.
114 +
115 +config SQUASHFS_FRAGMENT_CACHE_SIZE
116 +       int "Number of fragments cached" if SQUASHFS_EMBEDDED
117 +       depends on SQUASHFS
118 +       default "3"
119 +       help
120 +         By default SquashFS caches the last 3 fragments read from
121 +         the filesystem.  Increasing this amount may mean SquashFS
122 +         has to re-read fragments less often from disk, at the expense
123 +         of extra system memory.  Decreasing this amount will mean
124 +         SquashFS uses less memory at the expense of extra reads from disk.
125 +
126 +         Note there must be at least one cached fragment.  Anything
127 +         much more than three will probably not make much difference.
128 diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
129 new file mode 100644
130 index 0000000..70e3244
131 --- /dev/null
132 +++ b/fs/squashfs/Makefile
133 @@ -0,0 +1,7 @@
134 +#
135 +# Makefile for the linux squashfs routines.
136 +#
137 +
138 +obj-$(CONFIG_SQUASHFS) += squashfs.o
139 +squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
140 +squashfs-y += namei.o super.o symlink.o
141 diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
142 new file mode 100644
143 index 0000000..2a79603
144 --- /dev/null
145 +++ b/fs/squashfs/block.c
146 @@ -0,0 +1,270 @@
147 +/*
148 + * Squashfs - a compressed read only filesystem for Linux
149 + *
150 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
151 + * Phillip Lougher <phillip@lougher.demon.co.uk>
152 + *
153 + * This program is free software; you can redistribute it and/or
154 + * modify it under the terms of the GNU General Public License
155 + * as published by the Free Software Foundation; either version 2,
156 + * or (at your option) any later version.
157 + *
158 + * This program is distributed in the hope that it will be useful,
159 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
160 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161 + * GNU General Public License for more details.
162 + *
163 + * You should have received a copy of the GNU General Public License
164 + * along with this program; if not, write to the Free Software
165 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
166 + *
167 + * block.c
168 + */
169 +
170 +/*
171 + * This file implements the low-level routines to read and decompress
172 + * datablocks and metadata blocks.
173 + */
174 +
175 +#include <linux/fs.h>
176 +#include <linux/vfs.h>
177 +#include <linux/slab.h>
178 +#include <linux/mutex.h>
179 +#include <linux/string.h>
180 +#include <linux/buffer_head.h>
181 +#include <linux/zlib.h>
182 +
183 +#include "squashfs_fs.h"
184 +#include "squashfs_fs_sb.h"
185 +#include "squashfs_fs_i.h"
186 +#include "squashfs.h"
187 +
188 +/*
189 + * Read the metadata block length, this is stored in the first two
190 + * bytes of the metadata block.
191 + */
192 +static struct buffer_head *get_block_length(struct super_block *sb,
193 +                       u64 *cur_index, int *offset, int *length)
194 +{
195 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
196 +       struct buffer_head *bh;
197 +
198 +       bh = sb_bread(sb, *cur_index);
199 +       if (bh == NULL)
200 +               return NULL;
201 +
202 +       if (msblk->devblksize - *offset == 1) {
203 +               *length = (unsigned char) bh->b_data[*offset];
204 +               put_bh(bh);
205 +               bh = sb_bread(sb, ++(*cur_index));
206 +               if (bh == NULL)
207 +                       return NULL;
208 +               *length |= (unsigned char) bh->b_data[0] << 8;
209 +               *offset = 1;
210 +       } else {
211 +               *length = (unsigned char) bh->b_data[*offset] |
212 +                       (unsigned char) bh->b_data[*offset + 1] << 8;
213 +               *offset += 2;
214 +       }
215 +
216 +       return bh;
217 +}
218 +
219 +
220 +/*
221 + * Read and decompress a metadata block or datablock.  Length is non-zero
222 + * if a datablock is being read (the size is stored elsewhere in the
223 + * filesystem), otherwise the length is obtained from the first two bytes of
224 + * the metadata block.  A bit in the length field indicates if the block
225 + * is stored uncompressed in the filesystem (usually because compression
226 + * generated a larger block - this does occasionally happen with zlib).
227 + */
228 +int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
229 +                       int length, u64 *next_index, int srclength, int pages)
230 +{
231 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
232 +       struct buffer_head **bh;
233 +       int offset = index & ((1 << msblk->devblksize_log2) - 1);
234 +       u64 cur_index = index >> msblk->devblksize_log2;
235 +       int bytes, compressed, b = 0, k = 0, page = 0, avail;
236 +
237 +
238 +       bh = kcalloc((msblk->block_size >> msblk->devblksize_log2) + 1,
239 +                               sizeof(*bh), GFP_KERNEL);
240 +       if (bh == NULL)
241 +               return -ENOMEM;
242 +
243 +       if (length) {
244 +               /*
245 +                * Datablock.
246 +                */
247 +               bytes = -offset;
248 +               compressed = SQUASHFS_COMPRESSED_BLOCK(length);
249 +               length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
250 +               if (next_index)
251 +                       *next_index = index + length;
252 +
253 +               TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n",
254 +                       index, compressed ? "" : "un", length, srclength);
255 +
256 +               if (length < 0 || length > srclength ||
257 +                               (index + length) > msblk->bytes_used)
258 +                       goto read_failure;
259 +
260 +               for (b = 0; bytes < length; b++, cur_index++) {
261 +                       bh[b] = sb_getblk(sb, cur_index);
262 +                       if (bh[b] == NULL)
263 +                               goto block_release;
264 +                       bytes += msblk->devblksize;
265 +               }
266 +               ll_rw_block(READ, b, bh);
267 +       } else {
268 +               /*
269 +                * Metadata block.
270 +                */
271 +               if ((index + 2) > msblk->bytes_used)
272 +                       goto read_failure;
273 +
274 +               bh[0] = get_block_length(sb, &cur_index, &offset, &length);
275 +               if (bh[0] == NULL)
276 +                       goto read_failure;
277 +               b = 1;
278 +
279 +               bytes = msblk->devblksize - offset;
280 +               compressed = SQUASHFS_COMPRESSED(length);
281 +               length = SQUASHFS_COMPRESSED_SIZE(length);
282 +               if (next_index)
283 +                       *next_index = index + length + 2;
284 +
285 +               TRACE("Block @ 0x%llx, %scompressed size %d\n", index,
286 +                               compressed ? "" : "un", length);
287 +
288 +               if (length < 0 || length > srclength ||
289 +                                       (index + length) > msblk->bytes_used)
290 +                       goto block_release;
291 +
292 +               for (; bytes < length; b++) {
293 +                       bh[b] = sb_getblk(sb, ++cur_index);
294 +                       if (bh[b] == NULL)
295 +                               goto block_release;
296 +                       bytes += msblk->devblksize;
297 +               }
298 +               ll_rw_block(READ, b - 1, bh + 1);
299 +       }
300 +
301 +       if (compressed) {
302 +               int zlib_err = 0, zlib_init = 0;
303 +
304 +               /*
305 +                * Uncompress block.
306 +                */
307 +
308 +               mutex_lock(&msblk->read_data_mutex);
309 +
310 +               msblk->stream.avail_out = 0;
311 +               msblk->stream.avail_in = 0;
312 +
313 +               bytes = length;
314 +               do {
315 +                       if (msblk->stream.avail_in == 0 && k < b) {
316 +                               avail = min(bytes, msblk->devblksize - offset);
317 +                               bytes -= avail;
318 +                               wait_on_buffer(bh[k]);
319 +                               if (!buffer_uptodate(bh[k]))
320 +                                       goto release_mutex;
321 +
322 +                               if (avail == 0) {
323 +                                       offset = 0;
324 +                                       put_bh(bh[k++]);
325 +                                       continue;
326 +                               }
327 +
328 +                               msblk->stream.next_in = bh[k]->b_data + offset;
329 +                               msblk->stream.avail_in = avail;
330 +                               offset = 0;
331 +                       }
332 +
333 +                       if (msblk->stream.avail_out == 0 && page < pages) {
334 +                               msblk->stream.next_out = buffer[page++];
335 +                               msblk->stream.avail_out = PAGE_CACHE_SIZE;
336 +                       }
337 +
338 +                       if (!zlib_init) {
339 +                               zlib_err = zlib_inflateInit(&msblk->stream);
340 +                               if (zlib_err != Z_OK) {
341 +                                       ERROR("zlib_inflateInit returned"
342 +                                               " unexpected result 0x%x,"
343 +                                               " srclength %d\n", zlib_err,
344 +                                               srclength);
345 +                                       goto release_mutex;
346 +                               }
347 +                               zlib_init = 1;
348 +                       }
349 +
350 +                       zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
351 +
352 +                       if (msblk->stream.avail_in == 0 && k < b)
353 +                               put_bh(bh[k++]);
354 +               } while (zlib_err == Z_OK);
355 +
356 +               if (zlib_err != Z_STREAM_END) {
357 +                       ERROR("zlib_inflate error, data probably corrupt\n");
358 +                       goto release_mutex;
359 +               }
360 +
361 +               zlib_err = zlib_inflateEnd(&msblk->stream);
362 +               if (zlib_err != Z_OK) {
363 +                       ERROR("zlib_inflate error, data probably corrupt\n");
364 +                       goto release_mutex;
365 +               }
366 +               length = msblk->stream.total_out;
367 +               mutex_unlock(&msblk->read_data_mutex);
368 +       } else {
369 +               /*
370 +                * Block is uncompressed.
371 +                */
372 +               int i, in, pg_offset = 0;
373 +
374 +               for (i = 0; i < b; i++) {
375 +                       wait_on_buffer(bh[i]);
376 +                       if (!buffer_uptodate(bh[i]))
377 +                               goto block_release;
378 +               }
379 +
380 +               for (bytes = length; k < b; k++) {
381 +                       in = min(bytes, msblk->devblksize - offset);
382 +                       bytes -= in;
383 +                       while (in) {
384 +                               if (pg_offset == PAGE_CACHE_SIZE) {
385 +                                       page++;
386 +                                       pg_offset = 0;
387 +                               }
388 +                               avail = min_t(int, in, PAGE_CACHE_SIZE -
389 +                                               pg_offset);
390 +                               memcpy(buffer[page] + pg_offset,
391 +                                               bh[k]->b_data + offset, avail);
392 +                               in -= avail;
393 +                               pg_offset += avail;
394 +                               offset += avail;
395 +                       }
396 +                       offset = 0;
397 +                       put_bh(bh[k]);
398 +               }
399 +       }
400 +
401 +       kfree(bh);
402 +       return length;
403 +
404 +release_mutex:
405 +       mutex_unlock(&msblk->read_data_mutex);
406 +
407 +block_release:
408 +       for (; k < b; k++)
409 +               put_bh(bh[k]);
410 +
411 +read_failure:
412 +       ERROR("squashfs_read_data failed to read block 0x%llx\n",
413 +                                       (unsigned long long) index);
414 +       kfree(bh);
415 +       return -EIO;
416 +}
417 diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
418 new file mode 100644
419 index 0000000..40c98fa
420 --- /dev/null
421 +++ b/fs/squashfs/cache.c
422 @@ -0,0 +1,413 @@
423 +/*
424 + * Squashfs - a compressed read only filesystem for Linux
425 + *
426 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
427 + * Phillip Lougher <phillip@lougher.demon.co.uk>
428 + *
429 + * This program is free software; you can redistribute it and/or
430 + * modify it under the terms of the GNU General Public License
431 + * as published by the Free Software Foundation; either version 2,
432 + * or (at your option) any later version.
433 + *
434 + * This program is distributed in the hope that it will be useful,
435 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
436 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
437 + * GNU General Public License for more details.
438 + *
439 + * You should have received a copy of the GNU General Public License
440 + * along with this program; if not, write to the Free Software
441 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
442 + *
443 + * cache.c
444 + */
445 +
446 +/*
447 + * Blocks in Squashfs are compressed.  To avoid repeatedly decompressing
448 + * recently accessed data Squashfs uses two small metadata and fragment caches.
449 + *
450 + * This file implements a generic cache implementation used for both caches,
451 + * plus functions layered ontop of the generic cache implementation to
452 + * access the metadata and fragment caches.
453 + *
454 + * To avoid out of memory and fragmentation isssues with vmalloc the cache
455 + * uses sequences of kmalloced PAGE_CACHE_SIZE buffers.
456 + *
457 + * It should be noted that the cache is not used for file datablocks, these
458 + * are decompressed and cached in the page-cache in the normal way.  The
459 + * cache is only used to temporarily cache fragment and metadata blocks
460 + * which have been read as as a result of a metadata (i.e. inode or
461 + * directory) or fragment access.  Because metadata and fragments are packed
462 + * together into blocks (to gain greater compression) the read of a particular
463 + * piece of metadata or fragment will retrieve other metadata/fragments which
464 + * have been packed with it, these because of locality-of-reference may be read
465 + * in the near future. Temporarily caching them ensures they are available for
466 + * near future access without requiring an additional read and decompress.
467 + */
468 +
469 +#include <linux/fs.h>
470 +#include <linux/vfs.h>
471 +#include <linux/slab.h>
472 +#include <linux/vmalloc.h>
473 +#include <linux/sched.h>
474 +#include <linux/spinlock.h>
475 +#include <linux/wait.h>
476 +#include <linux/zlib.h>
477 +#include <linux/pagemap.h>
478 +
479 +#include "squashfs_fs.h"
480 +#include "squashfs_fs_sb.h"
481 +#include "squashfs_fs_i.h"
482 +#include "squashfs.h"
483 +
484 +/*
485 + * Look-up block in cache, and increment usage count.  If not in cache, read
486 + * and decompress it from disk.
487 + */
488 +struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb,
489 +       struct squashfs_cache *cache, u64 block, int length)
490 +{
491 +       int i, n;
492 +       struct squashfs_cache_entry *entry;
493 +
494 +       spin_lock(&cache->lock);
495 +
496 +       while (1) {
497 +               for (i = 0; i < cache->entries; i++)
498 +                       if (cache->entry[i].block == block)
499 +                               break;
500 +
501 +               if (i == cache->entries) {
502 +                       /*
503 +                        * Block not in cache, if all cache entries are used
504 +                        * go to sleep waiting for one to become available.
505 +                        */
506 +                       if (cache->unused == 0) {
507 +                               cache->num_waiters++;
508 +                               spin_unlock(&cache->lock);
509 +                               wait_event(cache->wait_queue, cache->unused);
510 +                               spin_lock(&cache->lock);
511 +                               cache->num_waiters--;
512 +                               continue;
513 +                       }
514 +
515 +                       /*
516 +                        * At least one unused cache entry.  A simple
517 +                        * round-robin strategy is used to choose the entry to
518 +                        * be evicted from the cache.
519 +                        */
520 +                       i = cache->next_blk;
521 +                       for (n = 0; n < cache->entries; n++) {
522 +                               if (cache->entry[i].refcount == 0)
523 +                                       break;
524 +                               i = (i + 1) % cache->entries;
525 +                       }
526 +
527 +                       cache->next_blk = (i + 1) % cache->entries;
528 +                       entry = &cache->entry[i];
529 +
530 +                       /*
531 +                        * Initialise choosen cache entry, and fill it in from
532 +                        * disk.
533 +                        */
534 +                       cache->unused--;
535 +                       entry->block = block;
536 +                       entry->refcount = 1;
537 +                       entry->pending = 1;
538 +                       entry->num_waiters = 0;
539 +                       entry->error = 0;
540 +                       spin_unlock(&cache->lock);
541 +
542 +                       entry->length = squashfs_read_data(sb, entry->data,
543 +                               block, length, &entry->next_index,
544 +                               cache->block_size, cache->pages);
545 +
546 +                       spin_lock(&cache->lock);
547 +
548 +                       if (entry->length < 0)
549 +                               entry->error = entry->length;
550 +
551 +                       entry->pending = 0;
552 +
553 +                       /*
554 +                        * While filling this entry one or more other processes
555 +                        * have looked it up in the cache, and have slept
556 +                        * waiting for it to become available.
557 +                        */
558 +                       if (entry->num_waiters) {
559 +                               spin_unlock(&cache->lock);
560 +                               wake_up_all(&entry->wait_queue);
561 +                       } else
562 +                               spin_unlock(&cache->lock);
563 +
564 +                       goto out;
565 +               }
566 +
567 +               /*
568 +                * Block already in cache.  Increment refcount so it doesn't
569 +                * get reused until we're finished with it, if it was
570 +                * previously unused there's one less cache entry available
571 +                * for reuse.
572 +                */
573 +               entry = &cache->entry[i];
574 +               if (entry->refcount == 0)
575 +                       cache->unused--;
576 +               entry->refcount++;
577 +
578 +               /*
579 +                * If the entry is currently being filled in by another process
580 +                * go to sleep waiting for it to become available.
581 +                */
582 +               if (entry->pending) {
583 +                       entry->num_waiters++;
584 +                       spin_unlock(&cache->lock);
585 +                       wait_event(entry->wait_queue, !entry->pending);
586 +               } else
587 +                       spin_unlock(&cache->lock);
588 +
589 +               goto out;
590 +       }
591 +
592 +out:
593 +       TRACE("Got %s %d, start block %lld, refcount %d, error %d\n",
594 +               cache->name, i, entry->block, entry->refcount, entry->error);
595 +
596 +       if (entry->error)
597 +               ERROR("Unable to read %s cache entry [%llx]\n", cache->name,
598 +                                                       block);
599 +       return entry;
600 +}
601 +
602 +
603 +/*
604 + * Release cache entry, once usage count is zero it can be reused.
605 + */
606 +void squashfs_cache_put(struct squashfs_cache_entry *entry)
607 +{
608 +       struct squashfs_cache *cache = entry->cache;
609 +
610 +       spin_lock(&cache->lock);
611 +       entry->refcount--;
612 +       if (entry->refcount == 0) {
613 +               cache->unused++;
614 +               /*
615 +                * If there's any processes waiting for a block to become
616 +                * available, wake one up.
617 +                */
618 +               if (cache->num_waiters) {
619 +                       spin_unlock(&cache->lock);
620 +                       wake_up(&cache->wait_queue);
621 +                       return;
622 +               }
623 +       }
624 +       spin_unlock(&cache->lock);
625 +}
626 +
627 +/*
628 + * Delete cache reclaiming all kmalloced buffers.
629 + */
630 +void squashfs_cache_delete(struct squashfs_cache *cache)
631 +{
632 +       int i, j;
633 +
634 +       if (cache == NULL)
635 +               return;
636 +
637 +       for (i = 0; i < cache->entries; i++) {
638 +               if (cache->entry[i].data) {
639 +                       for (j = 0; j < cache->pages; j++)
640 +                               kfree(cache->entry[i].data[j]);
641 +                       kfree(cache->entry[i].data);
642 +               }
643 +       }
644 +
645 +       kfree(cache->entry);
646 +       kfree(cache);
647 +}
648 +
649 +
650 +/*
651 + * Initialise cache allocating the specified number of entries, each of
652 + * size block_size.  To avoid vmalloc fragmentation issues each entry
653 + * is allocated as a sequence of kmalloced PAGE_CACHE_SIZE buffers.
654 + */
655 +struct squashfs_cache *squashfs_cache_init(char *name, int entries,
656 +       int block_size)
657 +{
658 +       int i, j;
659 +       struct squashfs_cache *cache = kzalloc(sizeof(*cache), GFP_KERNEL);
660 +
661 +       if (cache == NULL) {
662 +               ERROR("Failed to allocate %s cache\n", name);
663 +               return NULL;
664 +       }
665 +
666 +       cache->entry = kcalloc(entries, sizeof(*(cache->entry)), GFP_KERNEL);
667 +       if (cache->entry == NULL) {
668 +               ERROR("Failed to allocate %s cache\n", name);
669 +               goto cleanup;
670 +       }
671 +
672 +       cache->next_blk = 0;
673 +       cache->unused = entries;
674 +       cache->entries = entries;
675 +       cache->block_size = block_size;
676 +       cache->pages = block_size >> PAGE_CACHE_SHIFT;
677 +       cache->pages = cache->pages ? cache->pages : 1;
678 +       cache->name = name;
679 +       cache->num_waiters = 0;
680 +       spin_lock_init(&cache->lock);
681 +       init_waitqueue_head(&cache->wait_queue);
682 +
683 +       for (i = 0; i < entries; i++) {
684 +               struct squashfs_cache_entry *entry = &cache->entry[i];
685 +
686 +               init_waitqueue_head(&cache->entry[i].wait_queue);
687 +               entry->cache = cache;
688 +               entry->block = SQUASHFS_INVALID_BLK;
689 +               entry->data = kcalloc(cache->pages, sizeof(void *), GFP_KERNEL);
690 +               if (entry->data == NULL) {
691 +                       ERROR("Failed to allocate %s cache entry\n", name);
692 +                       goto cleanup;
693 +               }
694 +
695 +               for (j = 0; j < cache->pages; j++) {
696 +                       entry->data[j] = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
697 +                       if (entry->data[j] == NULL) {
698 +                               ERROR("Failed to allocate %s buffer\n", name);
699 +                               goto cleanup;
700 +                       }
701 +               }
702 +       }
703 +
704 +       return cache;
705 +
706 +cleanup:
707 +       squashfs_cache_delete(cache);
708 +       return NULL;
709 +}
710 +
711 +
712 +/*
713 + * Copy upto length bytes from cache entry to buffer starting at offset bytes
714 + * into the cache entry.  If there's not length bytes then copy the number of
715 + * bytes available.  In all cases return the number of bytes copied.
716 + */
717 +int squashfs_copy_data(void *buffer, struct squashfs_cache_entry *entry,
718 +               int offset, int length)
719 +{
720 +       int remaining = length;
721 +
722 +       if (length == 0)
723 +               return 0;
724 +       else if (buffer == NULL)
725 +               return min(length, entry->length - offset);
726 +
727 +       while (offset < entry->length) {
728 +               void *buff = entry->data[offset / PAGE_CACHE_SIZE]
729 +                               + (offset % PAGE_CACHE_SIZE);
730 +               int bytes = min_t(int, entry->length - offset,
731 +                               PAGE_CACHE_SIZE - (offset % PAGE_CACHE_SIZE));
732 +
733 +               if (bytes >= remaining) {
734 +                       memcpy(buffer, buff, remaining);
735 +                       remaining = 0;
736 +                       break;
737 +               }
738 +
739 +               memcpy(buffer, buff, bytes);
740 +               buffer += bytes;
741 +               remaining -= bytes;
742 +               offset += bytes;
743 +       }
744 +
745 +       return length - remaining;
746 +}
747 +
748 +
749 +/*
750 + * Read length bytes from metadata position <block, offset> (block is the
751 + * start of the compressed block on disk, and offset is the offset into
752 + * the block once decompressed).  Data is packed into consecutive blocks,
753 + * and length bytes may require reading more than one block.
754 + */
755 +int squashfs_read_metadata(struct super_block *sb, void *buffer,
756 +               u64 *block, int *offset, int length)
757 +{
758 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
759 +       int bytes, copied = length;
760 +       struct squashfs_cache_entry *entry;
761 +
762 +       TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset);
763 +
764 +       while (length) {
765 +               entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0);
766 +               if (entry->error)
767 +                       return entry->error;
768 +               else if (*offset >= entry->length)
769 +                       return -EIO;
770 +
771 +               bytes = squashfs_copy_data(buffer, entry, *offset, length);
772 +               if (buffer)
773 +                       buffer += bytes;
774 +               length -= bytes;
775 +               *offset += bytes;
776 +
777 +               if (*offset == entry->length) {
778 +                       *block = entry->next_index;
779 +                       *offset = 0;
780 +               }
781 +
782 +               squashfs_cache_put(entry);
783 +       }
784 +
785 +       return copied;
786 +}
787 +
788 +
789 +/*
790 + * Look-up in the fragmment cache the fragment located at <start_block> in the
791 + * filesystem.  If necessary read and decompress it from disk.
792 + */
793 +struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *sb,
794 +                               u64 start_block, int length)
795 +{
796 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
797 +
798 +       return squashfs_cache_get(sb, msblk->fragment_cache, start_block,
799 +               length);
800 +}
801 +
802 +
803 +/*
804 + * Read and decompress the datablock located at <start_block> in the
805 + * filesystem.  The cache is used here to avoid duplicating locking and
806 + * read/decompress code.
807 + */
808 +struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb,
809 +                               u64 start_block, int length)
810 +{
811 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
812 +
813 +       return squashfs_cache_get(sb, msblk->read_page, start_block, length);
814 +}
815 +
816 +
817 +/*
818 + * Read a filesystem table (uncompressed sequence of bytes) from disk
819 + */
820 +int squashfs_read_table(struct super_block *sb, void *buffer, u64 block,
821 +       int length)
822 +{
823 +       int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
824 +       int i, res;
825 +       void **data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
826 +       if (data == NULL)
827 +               return -ENOMEM;
828 +
829 +       for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
830 +               data[i] = buffer;
831 +       res = squashfs_read_data(sb, data, block, length |
832 +               SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages);
833 +       kfree(data);
834 +       return res;
835 +}
836 diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
837 new file mode 100644
838 index 0000000..566b0ea
839 --- /dev/null
840 +++ b/fs/squashfs/dir.c
841 @@ -0,0 +1,235 @@
842 +/*
843 + * Squashfs - a compressed read only filesystem for Linux
844 + *
845 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
846 + * Phillip Lougher <phillip@lougher.demon.co.uk>
847 + *
848 + * This program is free software; you can redistribute it and/or
849 + * modify it under the terms of the GNU General Public License
850 + * as published by the Free Software Foundation; either version 2,
851 + * or (at your option) any later version.
852 + *
853 + * This program is distributed in the hope that it will be useful,
854 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
855 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
856 + * GNU General Public License for more details.
857 + *
858 + * You should have received a copy of the GNU General Public License
859 + * along with this program; if not, write to the Free Software
860 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
861 + *
862 + * dir.c
863 + */
864 +
865 +/*
866 + * This file implements code to read directories from disk.
867 + *
868 + * See namei.c for a description of directory organisation on disk.
869 + */
870 +
871 +#include <linux/fs.h>
872 +#include <linux/vfs.h>
873 +#include <linux/slab.h>
874 +#include <linux/zlib.h>
875 +
876 +#include "squashfs_fs.h"
877 +#include "squashfs_fs_sb.h"
878 +#include "squashfs_fs_i.h"
879 +#include "squashfs.h"
880 +
881 +static const unsigned char squashfs_filetype_table[] = {
882 +       DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
883 +};
884 +
885 +/*
886 + * Lookup offset (f_pos) in the directory index, returning the
887 + * metadata block containing it.
888 + *
889 + * If we get an error reading the index then return the part of the index
890 + * (if any) we have managed to read - the index isn't essential, just
891 + * quicker.
892 + */
893 +static int get_dir_index_using_offset(struct super_block *sb,
894 +       u64 *next_block, int *next_offset, u64 index_start, int index_offset,
895 +       int i_count, u64 f_pos)
896 +{
897 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
898 +       int err, i, index, length = 0;
899 +       struct squashfs_dir_index dir_index;
900 +
901 +       TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %lld\n",
902 +                                       i_count, f_pos);
903 +
904 +       /*
905 +        * Translate from external f_pos to the internal f_pos.  This
906 +        * is offset by 3 because we invent "." and ".." entries which are
907 +        * not actually stored in the directory.
908 +        */
909 +       if (f_pos < 3)
910 +               return f_pos;
911 +       f_pos -= 3;
912 +
913 +       for (i = 0; i < i_count; i++) {
914 +               err = squashfs_read_metadata(sb, &dir_index, &index_start,
915 +                               &index_offset, sizeof(dir_index));
916 +               if (err < 0)
917 +                       break;
918 +
919 +               index = le32_to_cpu(dir_index.index);
920 +               if (index > f_pos)
921 +                       /*
922 +                        * Found the index we're looking for.
923 +                        */
924 +                       break;
925 +
926 +               err = squashfs_read_metadata(sb, NULL, &index_start,
927 +                               &index_offset, le32_to_cpu(dir_index.size) + 1);
928 +               if (err < 0)
929 +                       break;
930 +
931 +               length = index;
932 +               *next_block = le32_to_cpu(dir_index.start_block) +
933 +                                       msblk->directory_table;
934 +       }
935 +
936 +       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
937 +
938 +       /*
939 +        * Translate back from internal f_pos to external f_pos.
940 +        */
941 +       return length + 3;
942 +}
943 +
944 +
945 +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
946 +{
947 +       struct inode *inode = file->f_dentry->d_inode;
948 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
949 +       u64 block = squashfs_i(inode)->start + msblk->directory_table;
950 +       int offset = squashfs_i(inode)->offset, length = 0, dir_count, size,
951 +                               type, err;
952 +       unsigned int inode_number;
953 +       struct squashfs_dir_header dirh;
954 +       struct squashfs_dir_entry *dire;
955 +
956 +       TRACE("Entered squashfs_readdir [%llx:%x]\n", block, offset);
957 +
958 +       dire = kmalloc(sizeof(*dire) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL);
959 +       if (dire == NULL) {
960 +               ERROR("Failed to allocate squashfs_dir_entry\n");
961 +               goto finish;
962 +       }
963 +
964 +       /*
965 +        * Return "." and  ".." entries as the first two filenames in the
966 +        * directory.  To maximise compression these two entries are not
967 +        * stored in the directory, and so we invent them here.
968 +        *
969 +        * It also means that the external f_pos is offset by 3 from the
970 +        * on-disk directory f_pos.
971 +        */
972 +       while (file->f_pos < 3) {
973 +               char *name;
974 +               int i_ino;
975 +
976 +               if (file->f_pos == 0) {
977 +                       name = ".";
978 +                       size = 1;
979 +                       i_ino = inode->i_ino;
980 +               } else {
981 +                       name = "..";
982 +                       size = 2;
983 +                       i_ino = squashfs_i(inode)->parent;
984 +               }
985 +
986 +               TRACE("Calling filldir(%p, %s, %d, %lld, %d, %d)\n",
987 +                               dirent, name, size, file->f_pos, i_ino,
988 +                               squashfs_filetype_table[1]);
989 +
990 +               if (filldir(dirent, name, size, file->f_pos, i_ino,
991 +                               squashfs_filetype_table[1]) < 0) {
992 +                               TRACE("Filldir returned less than 0\n");
993 +                       goto finish;
994 +               }
995 +
996 +               file->f_pos += size;
997 +       }
998 +
999 +       length = get_dir_index_using_offset(inode->i_sb, &block, &offset,
1000 +                               squashfs_i(inode)->dir_idx_start,
1001 +                               squashfs_i(inode)->dir_idx_offset,
1002 +                               squashfs_i(inode)->dir_idx_cnt,
1003 +                               file->f_pos);
1004 +
1005 +       while (length < i_size_read(inode)) {
1006 +               /*
1007 +                * Read directory header
1008 +                */
1009 +               err = squashfs_read_metadata(inode->i_sb, &dirh, &block,
1010 +                                       &offset, sizeof(dirh));
1011 +               if (err < 0)
1012 +                       goto failed_read;
1013 +
1014 +               length += sizeof(dirh);
1015 +
1016 +               dir_count = le32_to_cpu(dirh.count) + 1;
1017 +               while (dir_count--) {
1018 +                       /*
1019 +                        * Read directory entry.
1020 +                        */
1021 +                       err = squashfs_read_metadata(inode->i_sb, dire, &block,
1022 +                                       &offset, sizeof(*dire));
1023 +                       if (err < 0)
1024 +                               goto failed_read;
1025 +
1026 +                       size = le16_to_cpu(dire->size) + 1;
1027 +
1028 +                       err = squashfs_read_metadata(inode->i_sb, dire->name,
1029 +                                       &block, &offset, size);
1030 +                       if (err < 0)
1031 +                               goto failed_read;
1032 +
1033 +                       length += sizeof(*dire) + size;
1034 +
1035 +                       if (file->f_pos >= length)
1036 +                               continue;
1037 +
1038 +                       dire->name[size] = '\0';
1039 +                       inode_number = le32_to_cpu(dirh.inode_number) +
1040 +                               ((short) le16_to_cpu(dire->inode_number));
1041 +                       type = le16_to_cpu(dire->type);
1042 +
1043 +                       TRACE("Calling filldir(%p, %s, %d, %lld, %x:%x, %d, %d)"
1044 +                                       "\n", dirent, dire->name, size,
1045 +                                       file->f_pos,
1046 +                                       le32_to_cpu(dirh.start_block),
1047 +                                       le16_to_cpu(dire->offset),
1048 +                                       inode_number,
1049 +                                       squashfs_filetype_table[type]);
1050 +
1051 +                       if (filldir(dirent, dire->name, size, file->f_pos,
1052 +                                       inode_number,
1053 +                                       squashfs_filetype_table[type]) < 0) {
1054 +                               TRACE("Filldir returned less than 0\n");
1055 +                               goto finish;
1056 +                       }
1057 +
1058 +                       file->f_pos = length;
1059 +               }
1060 +       }
1061 +
1062 +finish:
1063 +       kfree(dire);
1064 +       return 0;
1065 +
1066 +failed_read:
1067 +       ERROR("Unable to read directory block [%llx:%x]\n", block, offset);
1068 +       kfree(dire);
1069 +       return 0;
1070 +}
1071 +
1072 +
1073 +const struct file_operations squashfs_dir_ops = {
1074 +       .read = generic_read_dir,
1075 +       .readdir = squashfs_readdir
1076 +};
1077 diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c
1078 new file mode 100644
1079 index 0000000..a1ded6f
1080 --- /dev/null
1081 +++ b/fs/squashfs/export.c
1082 @@ -0,0 +1,172 @@
1083 +/*
1084 + * Squashfs - a compressed read only filesystem for Linux
1085 + *
1086 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
1087 + * Phillip Lougher <phillip@lougher.demon.co.uk>
1088 + *
1089 + * This program is free software; you can redistribute it and/or
1090 + * modify it under the terms of the GNU General Public License
1091 + * as published by the Free Software Foundation; either version 2,
1092 + * or (at your option) any later version.
1093 + *
1094 + * This program is distributed in the hope that it will be useful,
1095 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1096 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1097 + * GNU General Public License for more details.
1098 + *
1099 + * You should have received a copy of the GNU General Public License
1100 + * along with this program; if not, write to the Free Software
1101 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1102 + *
1103 + * export.c
1104 + */
1105 +
1106 +/*
1107 + * This file implements code to make Squashfs filesystems exportable (NFS etc.)
1108 + *
1109 + * The export code uses an inode lookup table to map inode numbers passed in
1110 + * filehandles to an inode location on disk.  This table is stored compressed
1111 + * into metadata blocks.  A second index table is used to locate these.  This
1112 + * second index table for speed of access (and because it is small) is read at
1113 + * mount time and cached in memory.
1114 + *
1115 + * The inode lookup table is used only by the export code, inode disk
1116 + * locations are directly encoded in directories, enabling direct access
1117 + * without an intermediate lookup for all operations except the export ops.
1118 + */
1119 +
1120 +#include <linux/fs.h>
1121 +#include <linux/vfs.h>
1122 +#include <linux/dcache.h>
1123 +#include <linux/exportfs.h>
1124 +#include <linux/zlib.h>
1125 +#include <linux/slab.h>
1126 +
1127 +#include "squashfs_fs.h"
1128 +#include "squashfs_fs_sb.h"
1129 +#include "squashfs_fs_i.h"
1130 +#include "squashfs.h"
1131 +
1132 +/*
1133 + * Look-up inode number (ino) in table, returning the inode location.
1134 + */
1135 +static long long squashfs_inode_lookup(struct super_block *sb, int ino_num)
1136 +{
1137 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
1138 +       int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1);
1139 +       int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1);
1140 +       u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]);
1141 +       __le64 ino;
1142 +       int err;
1143 +
1144 +       TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num);
1145 +
1146 +       err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino));
1147 +       if (err < 0)
1148 +               return err;
1149 +
1150 +       TRACE("squashfs_inode_lookup, inode = 0x%llx\n",
1151 +               (u64) le64_to_cpu(ino));
1152 +
1153 +       return le64_to_cpu(ino);
1154 +}
1155 +
1156 +
1157 +static struct dentry *squashfs_export_iget(struct super_block *sb,
1158 +       unsigned int ino_num)
1159 +{
1160 +       long long ino;
1161 +       struct dentry *dentry;
1162 +       struct inode *i;
1163 +
1164 +       TRACE("Entered squashfs_export_iget\n");
1165 +
1166 +       ino = squashfs_inode_lookup(sb, ino_num);
1167 +       if (ino < 0) {
1168 +               dentry = ERR_PTR(-ENOENT);
1169 +               goto failure;
1170 +       }
1171 +
1172 +       i = squashfs_iget(sb, ino, ino_num);
1173 +       if (i == NULL) {
1174 +               dentry = ERR_PTR(-EACCES);
1175 +               goto failure;
1176 +       }
1177 +
1178 +       dentry = d_alloc_anon(i);
1179 +       if (dentry == NULL) {
1180 +               iput(i);
1181 +               dentry = ERR_PTR(-ENOMEM);
1182 +       }
1183 +
1184 +failure:
1185 +       return dentry;
1186 +}
1187 +
1188 +
1189 +static struct dentry *squashfs_fh_to_dentry(struct super_block *sb,
1190 +               struct fid *fid, int fh_len, int fh_type)
1191 +{
1192 +       if ((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT)
1193 +                       || fh_len < 2)
1194 +               return NULL;
1195 +
1196 +       return squashfs_export_iget(sb, fid->i32.ino);
1197 +}
1198 +
1199 +
1200 +static struct dentry *squashfs_fh_to_parent(struct super_block *sb,
1201 +               struct fid *fid, int fh_len, int fh_type)
1202 +{
1203 +       if (fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4)
1204 +               return NULL;
1205 +
1206 +       return squashfs_export_iget(sb, fid->i32.parent_ino);
1207 +}
1208 +
1209 +
1210 +static struct dentry *squashfs_get_parent(struct dentry *child)
1211 +{
1212 +       struct inode *inode = child->d_inode;
1213 +       unsigned int parent_ino = squashfs_i(inode)->parent;
1214 +
1215 +       return squashfs_export_iget(inode->i_sb, parent_ino);
1216 +}
1217 +
1218 +
1219 +/*
1220 + * Read uncompressed inode lookup table indexes off disk into memory
1221 + */
1222 +__le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
1223 +               u64 lookup_table_start, unsigned int inodes)
1224 +{
1225 +       unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes);
1226 +       __le64 *inode_lookup_table;
1227 +       int err;
1228 +
1229 +       TRACE("In read_inode_lookup_table, length %d\n", length);
1230 +
1231 +       /* Allocate inode lookup table indexes */
1232 +       inode_lookup_table = kmalloc(length, GFP_KERNEL);
1233 +       if (inode_lookup_table == NULL) {
1234 +               ERROR("Failed to allocate inode lookup table\n");
1235 +               return ERR_PTR(-ENOMEM);
1236 +       }
1237 +
1238 +       err = squashfs_read_table(sb, inode_lookup_table, lookup_table_start,
1239 +                       length);
1240 +       if (err < 0) {
1241 +               ERROR("unable to read inode lookup table\n");
1242 +               kfree(inode_lookup_table);
1243 +               return ERR_PTR(err);
1244 +       }
1245 +
1246 +       return inode_lookup_table;
1247 +}
1248 +
1249 +
1250 +const struct export_operations squashfs_export_ops = {
1251 +       .fh_to_dentry = squashfs_fh_to_dentry,
1252 +       .fh_to_parent = squashfs_fh_to_parent,
1253 +       .get_parent = squashfs_get_parent
1254 +};
1255 diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
1256 new file mode 100644
1257 index 0000000..717767d
1258 --- /dev/null
1259 +++ b/fs/squashfs/file.c
1260 @@ -0,0 +1,502 @@
1261 +/*
1262 + * Squashfs - a compressed read only filesystem for Linux
1263 + *
1264 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
1265 + * Phillip Lougher <phillip@lougher.demon.co.uk>
1266 + *
1267 + * This program is free software; you can redistribute it and/or
1268 + * modify it under the terms of the GNU General Public License
1269 + * as published by the Free Software Foundation; either version 2,
1270 + * or (at your option) any later version.
1271 + *
1272 + * This program is distributed in the hope that it will be useful,
1273 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1274 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1275 + * GNU General Public License for more details.
1276 + *
1277 + * You should have received a copy of the GNU General Public License
1278 + * along with this program; if not, write to the Free Software
1279 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1280 + *
1281 + * file.c
1282 + */
1283 +
1284 +/*
1285 + * This file contains code for handling regular files.  A regular file
1286 + * consists of a sequence of contiguous compressed blocks, and/or a
1287 + * compressed fragment block (tail-end packed block).   The compressed size
1288 + * of each datablock is stored in a block list contained within the
1289 + * file inode (itself stored in one or more compressed metadata blocks).
1290 + *
1291 + * To speed up access to datablocks when reading 'large' files (256 Mbytes or
1292 + * larger), the code implements an index cache that caches the mapping from
1293 + * block index to datablock location on disk.
1294 + *
1295 + * The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
1296 + * retaining a simple and space-efficient block list on disk.  The cache
1297 + * is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
1298 + * Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
1299 + * The index cache is designed to be memory efficient, and by default uses
1300 + * 16 KiB.
1301 + */
1302 +
1303 +#include <linux/fs.h>
1304 +#include <linux/vfs.h>
1305 +#include <linux/kernel.h>
1306 +#include <linux/slab.h>
1307 +#include <linux/string.h>
1308 +#include <linux/pagemap.h>
1309 +#include <linux/mutex.h>
1310 +#include <linux/zlib.h>
1311 +
1312 +#include "squashfs_fs.h"
1313 +#include "squashfs_fs_sb.h"
1314 +#include "squashfs_fs_i.h"
1315 +#include "squashfs.h"
1316 +
1317 +/*
1318 + * Locate cache slot in range [offset, index] for specified inode.  If
1319 + * there's more than one return the slot closest to index.
1320 + */
1321 +static struct meta_index *locate_meta_index(struct inode *inode, int offset,
1322 +                               int index)
1323 +{
1324 +       struct meta_index *meta = NULL;
1325 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1326 +       int i;
1327 +
1328 +       mutex_lock(&msblk->meta_index_mutex);
1329 +
1330 +       TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
1331 +
1332 +       if (msblk->meta_index == NULL)
1333 +               goto not_allocated;
1334 +
1335 +       for (i = 0; i < SQUASHFS_META_SLOTS; i++) {
1336 +               if (msblk->meta_index[i].inode_number == inode->i_ino &&
1337 +                               msblk->meta_index[i].offset >= offset &&
1338 +                               msblk->meta_index[i].offset <= index &&
1339 +                               msblk->meta_index[i].locked == 0) {
1340 +                       TRACE("locate_meta_index: entry %d, offset %d\n", i,
1341 +                                       msblk->meta_index[i].offset);
1342 +                       meta = &msblk->meta_index[i];
1343 +                       offset = meta->offset;
1344 +               }
1345 +       }
1346 +
1347 +       if (meta)
1348 +               meta->locked = 1;
1349 +
1350 +not_allocated:
1351 +       mutex_unlock(&msblk->meta_index_mutex);
1352 +
1353 +       return meta;
1354 +}
1355 +
1356 +
1357 +/*
1358 + * Find and initialise an empty cache slot for index offset.
1359 + */
1360 +static struct meta_index *empty_meta_index(struct inode *inode, int offset,
1361 +                               int skip)
1362 +{
1363 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1364 +       struct meta_index *meta = NULL;
1365 +       int i;
1366 +
1367 +       mutex_lock(&msblk->meta_index_mutex);
1368 +
1369 +       TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
1370 +
1371 +       if (msblk->meta_index == NULL) {
1372 +               /*
1373 +                * First time cache index has been used, allocate and
1374 +                * initialise.  The cache index could be allocated at
1375 +                * mount time but doing it here means it is allocated only
1376 +                * if a 'large' file is read.
1377 +                */
1378 +               msblk->meta_index = kcalloc(SQUASHFS_META_SLOTS,
1379 +                       sizeof(*(msblk->meta_index)), GFP_KERNEL);
1380 +               if (msblk->meta_index == NULL) {
1381 +                       ERROR("Failed to allocate meta_index\n");
1382 +                       goto failed;
1383 +               }
1384 +               for (i = 0; i < SQUASHFS_META_SLOTS; i++) {
1385 +                       msblk->meta_index[i].inode_number = 0;
1386 +                       msblk->meta_index[i].locked = 0;
1387 +               }
1388 +               msblk->next_meta_index = 0;
1389 +       }
1390 +
1391 +       for (i = SQUASHFS_META_SLOTS; i &&
1392 +                       msblk->meta_index[msblk->next_meta_index].locked; i--)
1393 +               msblk->next_meta_index = (msblk->next_meta_index + 1) %
1394 +                       SQUASHFS_META_SLOTS;
1395 +
1396 +       if (i == 0) {
1397 +               TRACE("empty_meta_index: failed!\n");
1398 +               goto failed;
1399 +       }
1400 +
1401 +       TRACE("empty_meta_index: returned meta entry %d, %p\n",
1402 +                       msblk->next_meta_index,
1403 +                       &msblk->meta_index[msblk->next_meta_index]);
1404 +
1405 +       meta = &msblk->meta_index[msblk->next_meta_index];
1406 +       msblk->next_meta_index = (msblk->next_meta_index + 1) %
1407 +                       SQUASHFS_META_SLOTS;
1408 +
1409 +       meta->inode_number = inode->i_ino;
1410 +       meta->offset = offset;
1411 +       meta->skip = skip;
1412 +       meta->entries = 0;
1413 +       meta->locked = 1;
1414 +
1415 +failed:
1416 +       mutex_unlock(&msblk->meta_index_mutex);
1417 +       return meta;
1418 +}
1419 +
1420 +
1421 +static void release_meta_index(struct inode *inode, struct meta_index *meta)
1422 +{
1423 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1424 +       mutex_lock(&msblk->meta_index_mutex);
1425 +       meta->locked = 0;
1426 +       mutex_unlock(&msblk->meta_index_mutex);
1427 +}
1428 +
1429 +
1430 +/*
1431 + * Read the next n blocks from the block list, starting from
1432 + * metadata block <start_block, offset>.
1433 + */
1434 +static long long read_indexes(struct super_block *sb, int n,
1435 +                               u64 *start_block, int *offset)
1436 +{
1437 +       int err, i;
1438 +       long long block = 0;
1439 +       __le32 *blist = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
1440 +
1441 +       if (blist == NULL) {
1442 +               ERROR("read_indexes: Failed to allocate block_list\n");
1443 +               return -ENOMEM;
1444 +       }
1445 +
1446 +       while (n) {
1447 +               int blocks = min_t(int, n, PAGE_CACHE_SIZE >> 2);
1448 +
1449 +               err = squashfs_read_metadata(sb, blist, start_block,
1450 +                               offset, blocks << 2);
1451 +               if (err < 0) {
1452 +                       ERROR("read_indexes: reading block [%llx:%x]\n",
1453 +                               *start_block, *offset);
1454 +                       goto failure;
1455 +               }
1456 +
1457 +               for (i = 0; i < blocks; i++) {
1458 +                       int size = le32_to_cpu(blist[i]);
1459 +                       block += SQUASHFS_COMPRESSED_SIZE_BLOCK(size);
1460 +               }
1461 +               n -= blocks;
1462 +       }
1463 +
1464 +       kfree(blist);
1465 +       return block;
1466 +
1467 +failure:
1468 +       kfree(blist);
1469 +       return err;
1470 +}
1471 +
1472 +
1473 +/*
1474 + * Each cache index slot has SQUASHFS_META_ENTRIES, each of which
1475 + * can cache one index -> datablock/blocklist-block mapping.  We wish
1476 + * to distribute these over the length of the file, entry[0] maps index x,
1477 + * entry[1] maps index x + skip, entry[2] maps index x + 2 * skip, and so on.
1478 + * The larger the file, the greater the skip factor.  The skip factor is
1479 + * limited to the size of the metadata cache (SQUASHFS_CACHED_BLKS) to ensure
1480 + * the number of metadata blocks that need to be read fits into the cache.
1481 + * If the skip factor is limited in this way then the file will use multiple
1482 + * slots.
1483 + */
1484 +static inline int calculate_skip(int blocks)
1485 +{
1486 +       int skip = blocks / ((SQUASHFS_META_ENTRIES + 1)
1487 +                * SQUASHFS_META_INDEXES);
1488 +       return min(SQUASHFS_CACHED_BLKS - 1, skip + 1);
1489 +}
1490 +
1491 +
1492 +/*
1493 + * Search and grow the index cache for the specified inode, returning the
1494 + * on-disk locations of the datablock and block list metadata block
1495 + * <index_block, index_offset> for index (scaled to nearest cache index).
1496 + */
1497 +static int fill_meta_index(struct inode *inode, int index,
1498 +               u64 *index_block, int *index_offset, u64 *data_block)
1499 +{
1500 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1501 +       int skip = calculate_skip(i_size_read(inode) >> msblk->block_log);
1502 +       int offset = 0;
1503 +       struct meta_index *meta;
1504 +       struct meta_entry *meta_entry;
1505 +       u64 cur_index_block = squashfs_i(inode)->block_list_start;
1506 +       int cur_offset = squashfs_i(inode)->offset;
1507 +       u64 cur_data_block = squashfs_i(inode)->start;
1508 +       int err, i;
1509 +
1510 +       /*
1511 +        * Scale index to cache index (cache slot entry)
1512 +        */
1513 +       index /= SQUASHFS_META_INDEXES * skip;
1514 +
1515 +       while (offset < index) {
1516 +               meta = locate_meta_index(inode, offset + 1, index);
1517 +
1518 +               if (meta == NULL) {
1519 +                       meta = empty_meta_index(inode, offset + 1, skip);
1520 +                       if (meta == NULL)
1521 +                               goto all_done;
1522 +               } else {
1523 +                       offset = index < meta->offset + meta->entries ? index :
1524 +                               meta->offset + meta->entries - 1;
1525 +                       meta_entry = &meta->meta_entry[offset - meta->offset];
1526 +                       cur_index_block = meta_entry->index_block +
1527 +                               msblk->inode_table;
1528 +                       cur_offset = meta_entry->offset;
1529 +                       cur_data_block = meta_entry->data_block;
1530 +                       TRACE("get_meta_index: offset %d, meta->offset %d, "
1531 +                               "meta->entries %d\n", offset, meta->offset,
1532 +                               meta->entries);
1533 +                       TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
1534 +                               " data_block 0x%llx\n", cur_index_block,
1535 +                               cur_offset, cur_data_block);
1536 +               }
1537 +
1538 +               /*
1539 +                * If necessary grow cache slot by reading block list.  Cache
1540 +                * slot is extended up to index or to the end of the slot, in
1541 +                * which case further slots will be used.
1542 +                */
1543 +               for (i = meta->offset + meta->entries; i <= index &&
1544 +                               i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
1545 +                       int blocks = skip * SQUASHFS_META_INDEXES;
1546 +                       long long res = read_indexes(inode->i_sb, blocks,
1547 +                                       &cur_index_block, &cur_offset);
1548 +
1549 +                       if (res < 0) {
1550 +                               if (meta->entries == 0)
1551 +                                       /*
1552 +                                        * Don't leave an empty slot on read
1553 +                                        * error allocated to this inode...
1554 +                                        */
1555 +                                       meta->inode_number = 0;
1556 +                               err = res;
1557 +                               goto failed;
1558 +                       }
1559 +
1560 +                       cur_data_block += res;
1561 +                       meta_entry = &meta->meta_entry[i - meta->offset];
1562 +                       meta_entry->index_block = cur_index_block -
1563 +                               msblk->inode_table;
1564 +                       meta_entry->offset = cur_offset;
1565 +                       meta_entry->data_block = cur_data_block;
1566 +                       meta->entries++;
1567 +                       offset++;
1568 +               }
1569 +
1570 +               TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
1571 +                               meta->offset, meta->entries);
1572 +
1573 +               release_meta_index(inode, meta);
1574 +       }
1575 +
1576 +all_done:
1577 +       *index_block = cur_index_block;
1578 +       *index_offset = cur_offset;
1579 +       *data_block = cur_data_block;
1580 +
1581 +       /*
1582 +        * Scale cache index (cache slot entry) to index
1583 +        */
1584 +       return offset * SQUASHFS_META_INDEXES * skip;
1585 +
1586 +failed:
1587 +       release_meta_index(inode, meta);
1588 +       return err;
1589 +}
1590 +
1591 +
1592 +/*
1593 + * Get the on-disk location and compressed size of the datablock
1594 + * specified by index.  Fill_meta_index() does most of the work.
1595 + */
1596 +static int read_blocklist(struct inode *inode, int index, u64 *block)
1597 +{
1598 +       u64 start;
1599 +       long long blks;
1600 +       int offset;
1601 +       __le32 size;
1602 +       int res = fill_meta_index(inode, index, &start, &offset, block);
1603 +
1604 +       TRACE("read_blocklist: res %d, index %d, start 0x%llx, offset"
1605 +                      " 0x%x, block 0x%llx\n", res, index, start, offset,
1606 +                       *block);
1607 +
1608 +       if (res < 0)
1609 +               return res;
1610 +
1611 +       /*
1612 +        * res contains the index of the mapping returned by fill_meta_index(),
1613 +        * this will likely be less than the desired index (because the
1614 +        * meta_index cache works at a higher granularity).  Read any
1615 +        * extra block indexes needed.
1616 +        */
1617 +       if (res < index) {
1618 +               blks = read_indexes(inode->i_sb, index - res, &start, &offset);
1619 +               if (blks < 0)
1620 +                       return (int) blks;
1621 +               *block += blks;
1622 +       }
1623 +
1624 +       /*
1625 +        * Read length of block specified by index.
1626 +        */
1627 +       res = squashfs_read_metadata(inode->i_sb, &size, &start, &offset,
1628 +                       sizeof(size));
1629 +       if (res < 0)
1630 +               return res;
1631 +       return le32_to_cpu(size);
1632 +}
1633 +
1634 +
1635 +static int squashfs_readpage(struct file *file, struct page *page)
1636 +{
1637 +       struct inode *inode = page->mapping->host;
1638 +       struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1639 +       int bytes, i, offset = 0, sparse = 0;
1640 +       struct squashfs_cache_entry *buffer = NULL;
1641 +       void *pageaddr;
1642 +
1643 +       int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1;
1644 +       int index = page->index >> (msblk->block_log - PAGE_CACHE_SHIFT);
1645 +       int start_index = page->index & ~mask;
1646 +       int end_index = start_index | mask;
1647 +       int file_end = i_size_read(inode) >> msblk->block_log;
1648 +
1649 +       TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
1650 +                               page->index, squashfs_i(inode)->start);
1651 +
1652 +       if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1653 +                                       PAGE_CACHE_SHIFT))
1654 +               goto out;
1655 +
1656 +       if (index < file_end || squashfs_i(inode)->fragment_block ==
1657 +                                       SQUASHFS_INVALID_BLK) {
1658 +               /*
1659 +                * Reading a datablock from disk.  Need to read block list
1660 +                * to get location and block size.
1661 +                */
1662 +               u64 block = 0;
1663 +               int bsize = read_blocklist(inode, index, &block);
1664 +               if (bsize < 0)
1665 +                       goto error_out;
1666 +
1667 +               if (bsize == 0) { /* hole */
1668 +                       bytes = index == file_end ?
1669 +                               (i_size_read(inode) & (msblk->block_size - 1)) :
1670 +                                msblk->block_size;
1671 +                       sparse = 1;
1672 +               } else {
1673 +                       /*
1674 +                        * Read and decompress datablock.
1675 +                        */
1676 +                       buffer = squashfs_get_datablock(inode->i_sb,
1677 +                                                               block, bsize);
1678 +                       if (buffer->error) {
1679 +                               ERROR("Unable to read page, block %llx, size %x"
1680 +                                       "\n", block, bsize);
1681 +                               squashfs_cache_put(buffer);
1682 +                               goto error_out;
1683 +                       }
1684 +                       bytes = buffer->length;
1685 +               }
1686 +       } else {
1687 +               /*
1688 +                * Datablock is stored inside a fragment (tail-end packed
1689 +                * block).
1690 +                */
1691 +               buffer = squashfs_get_fragment(inode->i_sb,
1692 +                               squashfs_i(inode)->fragment_block,
1693 +                               squashfs_i(inode)->fragment_size);
1694 +
1695 +               if (buffer->error) {
1696 +                       ERROR("Unable to read page, block %llx, size %x\n",
1697 +                               squashfs_i(inode)->fragment_block,
1698 +                               squashfs_i(inode)->fragment_size);
1699 +                       squashfs_cache_put(buffer);
1700 +                       goto error_out;
1701 +               }
1702 +               bytes = i_size_read(inode) & (msblk->block_size - 1);
1703 +               offset = squashfs_i(inode)->fragment_offset;
1704 +       }
1705 +
1706 +       /*
1707 +        * Loop copying datablock into pages.  As the datablock likely covers
1708 +        * many PAGE_CACHE_SIZE pages (default block size is 128 KiB) explicitly
1709 +        * grab the pages from the page cache, except for the page that we've
1710 +        * been called to fill.
1711 +        */
1712 +       for (i = start_index; i <= end_index && bytes > 0; i++,
1713 +                       bytes -= PAGE_CACHE_SIZE, offset += PAGE_CACHE_SIZE) {
1714 +               struct page *push_page;
1715 +               int avail = sparse ? 0 : min_t(int, bytes, PAGE_CACHE_SIZE);
1716 +
1717 +               TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail);
1718 +
1719 +               push_page = (i == page->index) ? page :
1720 +                       grab_cache_page_nowait(page->mapping, i);
1721 +
1722 +               if (!push_page)
1723 +                       continue;
1724 +
1725 +               if (PageUptodate(push_page))
1726 +                       goto skip_page;
1727 +
1728 +               pageaddr = kmap_atomic(push_page, KM_USER0);
1729 +               squashfs_copy_data(pageaddr, buffer, offset, avail);
1730 +               memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
1731 +               kunmap_atomic(pageaddr, KM_USER0);
1732 +               flush_dcache_page(push_page);
1733 +               SetPageUptodate(push_page);
1734 +skip_page:
1735 +               unlock_page(push_page);
1736 +               if (i != page->index)
1737 +                       page_cache_release(push_page);
1738 +       }
1739 +
1740 +       if (!sparse)
1741 +               squashfs_cache_put(buffer);
1742 +
1743 +       return 0;
1744 +
1745 +error_out:
1746 +       SetPageError(page);
1747 +out:
1748 +       pageaddr = kmap_atomic(page, KM_USER0);
1749 +       memset(pageaddr, 0, PAGE_CACHE_SIZE);
1750 +       kunmap_atomic(pageaddr, KM_USER0);
1751 +       flush_dcache_page(page);
1752 +       if (!PageError(page))
1753 +               SetPageUptodate(page);
1754 +       unlock_page(page);
1755 +
1756 +       return 0;
1757 +}
1758 +
1759 +
1760 +const struct address_space_operations squashfs_aops = {
1761 +       .readpage = squashfs_readpage
1762 +};
1763 diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
1764 new file mode 100644
1765 index 0000000..b5a2c15
1766 --- /dev/null
1767 +++ b/fs/squashfs/fragment.c
1768 @@ -0,0 +1,98 @@
1769 +/*
1770 + * Squashfs - a compressed read only filesystem for Linux
1771 + *
1772 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
1773 + * Phillip Lougher <phillip@lougher.demon.co.uk>
1774 + *
1775 + * This program is free software; you can redistribute it and/or
1776 + * modify it under the terms of the GNU General Public License
1777 + * as published by the Free Software Foundation; either version 2,
1778 + * or (at your option) any later version.
1779 + *
1780 + * This program is distributed in the hope that it will be useful,
1781 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1782 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1783 + * GNU General Public License for more details.
1784 + *
1785 + * You should have received a copy of the GNU General Public License
1786 + * along with this program; if not, write to the Free Software
1787 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1788 + *
1789 + * fragment.c
1790 + */
1791 +
1792 +/*
1793 + * This file implements code to handle compressed fragments (tail-end packed
1794 + * datablocks).
1795 + *
1796 + * Regular files contain a fragment index which is mapped to a fragment
1797 + * location on disk and compressed size using a fragment lookup table.
1798 + * Like everything in Squashfs this fragment lookup table is itself stored
1799 + * compressed into metadata blocks.  A second index table is used to locate
1800 + * these.  This second index table for speed of access (and because it
1801 + * is small) is read at mount time and cached in memory.
1802 + */
1803 +
1804 +#include <linux/fs.h>
1805 +#include <linux/vfs.h>
1806 +#include <linux/slab.h>
1807 +#include <linux/zlib.h>
1808 +
1809 +#include "squashfs_fs.h"
1810 +#include "squashfs_fs_sb.h"
1811 +#include "squashfs_fs_i.h"
1812 +#include "squashfs.h"
1813 +
1814 +/*
1815 + * Look-up fragment using the fragment index table.  Return the on disk
1816 + * location of the fragment and its compressed size
1817 + */
1818 +int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment,
1819 +                               u64 *fragment_block)
1820 +{
1821 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
1822 +       int block = SQUASHFS_FRAGMENT_INDEX(fragment);
1823 +       int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
1824 +       u64 start_block = le64_to_cpu(msblk->fragment_index[block]);
1825 +       struct squashfs_fragment_entry fragment_entry;
1826 +       int size;
1827 +
1828 +       size = squashfs_read_metadata(sb, &fragment_entry, &start_block,
1829 +                                       &offset, sizeof(fragment_entry));
1830 +       if (size < 0)
1831 +               return size;
1832 +
1833 +       *fragment_block = le64_to_cpu(fragment_entry.start_block);
1834 +       size = le32_to_cpu(fragment_entry.size);
1835 +
1836 +       return size;
1837 +}
1838 +
1839 +
1840 +/*
1841 + * Read the uncompressed fragment lookup table indexes off disk into memory
1842 + */
1843 +__le64 *squashfs_read_fragment_index_table(struct super_block *sb,
1844 +       u64 fragment_table_start, unsigned int fragments)
1845 +{
1846 +       unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(fragments);
1847 +       __le64 *fragment_index;
1848 +       int err;
1849 +
1850 +       /* Allocate fragment lookup table indexes */
1851 +       fragment_index = kmalloc(length, GFP_KERNEL);
1852 +       if (fragment_index == NULL) {
1853 +               ERROR("Failed to allocate fragment index table\n");
1854 +               return ERR_PTR(-ENOMEM);
1855 +       }
1856 +
1857 +       err = squashfs_read_table(sb, fragment_index, fragment_table_start,
1858 +                       length);
1859 +       if (err < 0) {
1860 +               ERROR("unable to read fragment index table\n");
1861 +               kfree(fragment_index);
1862 +               return ERR_PTR(err);
1863 +       }
1864 +
1865 +       return fragment_index;
1866 +}
1867 diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c
1868 new file mode 100644
1869 index 0000000..3795b83
1870 --- /dev/null
1871 +++ b/fs/squashfs/id.c
1872 @@ -0,0 +1,94 @@
1873 +/*
1874 + * Squashfs - a compressed read only filesystem for Linux
1875 + *
1876 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
1877 + * Phillip Lougher <phillip@lougher.demon.co.uk>
1878 + *
1879 + * This program is free software; you can redistribute it and/or
1880 + * modify it under the terms of the GNU General Public License
1881 + * as published by the Free Software Foundation; either version 2,
1882 + * or (at your option) any later version.
1883 + *
1884 + * This program is distributed in the hope that it will be useful,
1885 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1886 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1887 + * GNU General Public License for more details.
1888 + *
1889 + * You should have received a copy of the GNU General Public License
1890 + * along with this program; if not, write to the Free Software
1891 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1892 + *
1893 + * id.c
1894 + */
1895 +
1896 +/*
1897 + * This file implements code to handle uids and gids.
1898 + *
1899 + * For space efficiency regular files store uid and gid indexes, which are
1900 + * converted to 32-bit uids/gids using an id look up table.  This table is
1901 + * stored compressed into metadata blocks.  A second index table is used to
1902 + * locate these.  This second index table for speed of access (and because it
1903 + * is small) is read at mount time and cached in memory.
1904 + */
1905 +
1906 +#include <linux/fs.h>
1907 +#include <linux/vfs.h>
1908 +#include <linux/slab.h>
1909 +#include <linux/zlib.h>
1910 +
1911 +#include "squashfs_fs.h"
1912 +#include "squashfs_fs_sb.h"
1913 +#include "squashfs_fs_i.h"
1914 +#include "squashfs.h"
1915 +
1916 +/*
1917 + * Map uid/gid index into real 32-bit uid/gid using the id look up table
1918 + */
1919 +int squashfs_get_id(struct super_block *sb, unsigned int index,
1920 +                                       unsigned int *id)
1921 +{
1922 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
1923 +       int block = SQUASHFS_ID_BLOCK(index);
1924 +       int offset = SQUASHFS_ID_BLOCK_OFFSET(index);
1925 +       u64 start_block = le64_to_cpu(msblk->id_table[block]);
1926 +       __le32 disk_id;
1927 +       int err;
1928 +
1929 +       err = squashfs_read_metadata(sb, &disk_id, &start_block, &offset,
1930 +                                                       sizeof(disk_id));
1931 +       if (err < 0)
1932 +               return err;
1933 +
1934 +       *id = le32_to_cpu(disk_id);
1935 +       return 0;
1936 +}
1937 +
1938 +
1939 +/*
1940 + * Read uncompressed id lookup table indexes from disk into memory
1941 + */
1942 +__le64 *squashfs_read_id_index_table(struct super_block *sb,
1943 +                       u64 id_table_start, unsigned short no_ids)
1944 +{
1945 +       unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids);
1946 +       __le64 *id_table;
1947 +       int err;
1948 +
1949 +       TRACE("In read_id_index_table, length %d\n", length);
1950 +
1951 +       /* Allocate id lookup table indexes */
1952 +       id_table = kmalloc(length, GFP_KERNEL);
1953 +       if (id_table == NULL) {
1954 +               ERROR("Failed to allocate id index table\n");
1955 +               return ERR_PTR(-ENOMEM);
1956 +       }
1957 +
1958 +       err = squashfs_read_table(sb, id_table, id_table_start, length);
1959 +       if (err < 0) {
1960 +               ERROR("unable to read id index table\n");
1961 +               kfree(id_table);
1962 +               return ERR_PTR(err);
1963 +       }
1964 +
1965 +       return id_table;
1966 +}
1967 diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
1968 new file mode 100644
1969 index 0000000..9101dbd
1970 --- /dev/null
1971 +++ b/fs/squashfs/inode.c
1972 @@ -0,0 +1,348 @@
1973 +/*
1974 + * Squashfs - a compressed read only filesystem for Linux
1975 + *
1976 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
1977 + * Phillip Lougher <phillip@lougher.demon.co.uk>
1978 + *
1979 + * This program is free software; you can redistribute it and/or
1980 + * modify it under the terms of the GNU General Public License
1981 + * as published by the Free Software Foundation; either version 2,
1982 + * or (at your option) any later version.
1983 + *
1984 + * This program is distributed in the hope that it will be useful,
1985 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1986 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1987 + * GNU General Public License for more details.
1988 + *
1989 + * You should have received a copy of the GNU General Public License
1990 + * along with this program; if not, write to the Free Software
1991 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1992 + *
1993 + * inode.c
1994 + */
1995 +
1996 +/*
1997 + * This file implements code to create and read inodes from disk.
1998 + *
1999 + * Inodes in Squashfs are identified by a 48-bit inode which encodes the
2000 + * location of the compressed metadata block containing the inode, and the byte
2001 + * offset into that block where the inode is placed (<block, offset>).
2002 + *
2003 + * To maximise compression there are different inodes for each file type
2004 + * (regular file, directory, device, etc.), the inode contents and length
2005 + * varying with the type.
2006 + *
2007 + * To further maximise compression, two types of regular file inode and
2008 + * directory inode are defined: inodes optimised for frequently occurring
2009 + * regular files and directories, and extended types where extra
2010 + * information has to be stored.
2011 + */
2012 +
2013 +#include <linux/fs.h>
2014 +#include <linux/vfs.h>
2015 +#include <linux/zlib.h>
2016 +
2017 +#include "squashfs_fs.h"
2018 +#include "squashfs_fs_sb.h"
2019 +#include "squashfs_fs_i.h"
2020 +#include "squashfs.h"
2021 +
2022 +/*
2023 + * Initialise VFS inode with the base inode information common to all
2024 + * Squashfs inode types.  Sqsh_ino contains the unswapped base inode
2025 + * off disk.
2026 + */
2027 +static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
2028 +                               struct squashfs_base_inode *sqsh_ino)
2029 +{
2030 +       int err;
2031 +
2032 +       err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &inode->i_uid);
2033 +       if (err)
2034 +               return err;
2035 +
2036 +       err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->guid), &inode->i_gid);
2037 +       if (err)
2038 +               return err;
2039 +
2040 +       inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
2041 +       inode->i_mtime.tv_sec = le32_to_cpu(sqsh_ino->mtime);
2042 +       inode->i_atime.tv_sec = inode->i_mtime.tv_sec;
2043 +       inode->i_ctime.tv_sec = inode->i_mtime.tv_sec;
2044 +       inode->i_mode = le16_to_cpu(sqsh_ino->mode);
2045 +       inode->i_size = 0;
2046 +
2047 +       return err;
2048 +}
2049 +
2050 +
2051 +struct inode *squashfs_iget(struct super_block *sb, long long ino,
2052 +                               unsigned int ino_number)
2053 +{
2054 +       struct inode *inode = iget_locked(sb, ino_number);
2055 +       int err;
2056 +
2057 +       TRACE("Entered squashfs_iget\n");
2058 +
2059 +       if (!inode)
2060 +               return ERR_PTR(-ENOMEM);
2061 +       if (!(inode->i_state & I_NEW))
2062 +               return inode;
2063 +
2064 +       err = squashfs_read_inode(inode, ino);
2065 +       if (err) {
2066 +               iget_failed(inode);
2067 +               return ERR_PTR(err);
2068 +       }
2069 +
2070 +       unlock_new_inode(inode);
2071 +       return inode;
2072 +}
2073 +
2074 +
2075 +/*
2076 + * Initialise VFS inode by reading inode from inode table (compressed
2077 + * metadata).  The format and amount of data read depends on type.
2078 + */
2079 +int squashfs_read_inode(struct inode *inode, long long ino)
2080 +{
2081 +       struct super_block *sb = inode->i_sb;
2082 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
2083 +       u64 block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
2084 +       int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
2085 +       union squashfs_inode squashfs_ino;
2086 +       struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
2087 +
2088 +       TRACE("Entered squashfs_read_inode\n");
2089 +
2090 +       /*
2091 +        * Read inode base common to all inode types.
2092 +        */
2093 +       err = squashfs_read_metadata(sb, sqshb_ino, &block,
2094 +                               &offset, sizeof(*sqshb_ino));
2095 +       if (err < 0)
2096 +               goto failed_read;
2097 +
2098 +       err = squashfs_new_inode(sb, inode, sqshb_ino);
2099 +       if (err)
2100 +               goto failed_read;
2101 +
2102 +       block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
2103 +       offset = SQUASHFS_INODE_OFFSET(ino);
2104 +
2105 +       type = le16_to_cpu(sqshb_ino->inode_type);
2106 +       switch (type) {
2107 +       case SQUASHFS_REG_TYPE: {
2108 +               unsigned int frag_offset, frag;
2109 +               int frag_size;
2110 +               u64 frag_blk;
2111 +               struct squashfs_reg_inode *sqsh_ino = &squashfs_ino.reg;
2112 +
2113 +               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
2114 +                                                       sizeof(*sqsh_ino));
2115 +               if (err < 0)
2116 +                       goto failed_read;
2117 +
2118 +               frag = le32_to_cpu(sqsh_ino->fragment);
2119 +               if (frag != SQUASHFS_INVALID_FRAG) {
2120 +                       frag_offset = le32_to_cpu(sqsh_ino->offset);
2121 +                       frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
2122 +                       if (frag_size < 0) {
2123 +                               err = frag_size;
2124 +                               goto failed_read;
2125 +                       }
2126 +               } else {
2127 +                       frag_blk = SQUASHFS_INVALID_BLK;
2128 +                       frag_size = 0;
2129 +                       frag_offset = 0;
2130 +               }
2131 +
2132 +               inode->i_nlink = 1;
2133 +               inode->i_size = le32_to_cpu(sqsh_ino->file_size);
2134 +               inode->i_fop = &generic_ro_fops;
2135 +               inode->i_mode |= S_IFREG;
2136 +               inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
2137 +               squashfs_i(inode)->fragment_block = frag_blk;
2138 +               squashfs_i(inode)->fragment_size = frag_size;
2139 +               squashfs_i(inode)->fragment_offset = frag_offset;
2140 +               squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
2141 +               squashfs_i(inode)->block_list_start = block;
2142 +               squashfs_i(inode)->offset = offset;
2143 +               inode->i_data.a_ops = &squashfs_aops;
2144 +
2145 +               TRACE("File inode %x:%x, start_block %llx, block_list_start "
2146 +                       "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
2147 +                       offset, squashfs_i(inode)->start, block, offset);
2148 +               break;
2149 +       }
2150 +       case SQUASHFS_LREG_TYPE: {
2151 +               unsigned int frag_offset, frag;
2152 +               int frag_size;
2153 +               u64 frag_blk;
2154 +               struct squashfs_lreg_inode *sqsh_ino = &squashfs_ino.lreg;
2155 +
2156 +               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
2157 +                                                       sizeof(*sqsh_ino));
2158 +               if (err < 0)
2159 +                       goto failed_read;
2160 +
2161 +               frag = le32_to_cpu(sqsh_ino->fragment);
2162 +               if (frag != SQUASHFS_INVALID_FRAG) {
2163 +                       frag_offset = le32_to_cpu(sqsh_ino->offset);
2164 +                       frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
2165 +                       if (frag_size < 0) {
2166 +                               err = frag_size;
2167 +                               goto failed_read;
2168 +                       }
2169 +               } else {
2170 +                       frag_blk = SQUASHFS_INVALID_BLK;
2171 +                       frag_size = 0;
2172 +                       frag_offset = 0;
2173 +               }
2174 +
2175 +               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
2176 +               inode->i_size = le64_to_cpu(sqsh_ino->file_size);
2177 +               inode->i_fop = &generic_ro_fops;
2178 +               inode->i_mode |= S_IFREG;
2179 +               inode->i_blocks = ((inode->i_size -
2180 +                               le64_to_cpu(sqsh_ino->sparse) - 1) >> 9) + 1;
2181 +
2182 +               squashfs_i(inode)->fragment_block = frag_blk;
2183 +               squashfs_i(inode)->fragment_size = frag_size;
2184 +               squashfs_i(inode)->fragment_offset = frag_offset;
2185 +               squashfs_i(inode)->start = le64_to_cpu(sqsh_ino->start_block);
2186 +               squashfs_i(inode)->block_list_start = block;
2187 +               squashfs_i(inode)->offset = offset;
2188 +               inode->i_data.a_ops = &squashfs_aops;
2189 +
2190 +               TRACE("File inode %x:%x, start_block %llx, block_list_start "
2191 +                       "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
2192 +                       offset, squashfs_i(inode)->start, block, offset);
2193 +               break;
2194 +       }
2195 +       case SQUASHFS_DIR_TYPE: {
2196 +               struct squashfs_dir_inode *sqsh_ino = &squashfs_ino.dir;
2197 +
2198 +               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
2199 +                               sizeof(*sqsh_ino));
2200 +               if (err < 0)
2201 +                       goto failed_read;
2202 +
2203 +               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
2204 +               inode->i_size = le16_to_cpu(sqsh_ino->file_size);
2205 +               inode->i_op = &squashfs_dir_inode_ops;
2206 +               inode->i_fop = &squashfs_dir_ops;
2207 +               inode->i_mode |= S_IFDIR;
2208 +               squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
2209 +               squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
2210 +               squashfs_i(inode)->dir_idx_cnt = 0;
2211 +               squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
2212 +
2213 +               TRACE("Directory inode %x:%x, start_block %llx, offset %x\n",
2214 +                               SQUASHFS_INODE_BLK(ino), offset,
2215 +                               squashfs_i(inode)->start,
2216 +                               le16_to_cpu(sqsh_ino->offset));
2217 +               break;
2218 +       }
2219 +       case SQUASHFS_LDIR_TYPE: {
2220 +               struct squashfs_ldir_inode *sqsh_ino = &squashfs_ino.ldir;
2221 +
2222 +               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
2223 +                               sizeof(*sqsh_ino));
2224 +               if (err < 0)
2225 +                       goto failed_read;
2226 +
2227 +               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
2228 +               inode->i_size = le32_to_cpu(sqsh_ino->file_size);
2229 +               inode->i_op = &squashfs_dir_inode_ops;
2230 +               inode->i_fop = &squashfs_dir_ops;
2231 +               inode->i_mode |= S_IFDIR;
2232 +               squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
2233 +               squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
2234 +               squashfs_i(inode)->dir_idx_start = block;
2235 +               squashfs_i(inode)->dir_idx_offset = offset;
2236 +               squashfs_i(inode)->dir_idx_cnt = le16_to_cpu(sqsh_ino->i_count);
2237 +               squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
2238 +
2239 +               TRACE("Long directory inode %x:%x, start_block %llx, offset "
2240 +                               "%x\n", SQUASHFS_INODE_BLK(ino), offset,
2241 +                               squashfs_i(inode)->start,
2242 +                               le16_to_cpu(sqsh_ino->offset));
2243 +               break;
2244 +       }
2245 +       case SQUASHFS_SYMLINK_TYPE:
2246 +       case SQUASHFS_LSYMLINK_TYPE: {
2247 +               struct squashfs_symlink_inode *sqsh_ino = &squashfs_ino.symlink;
2248 +
2249 +               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
2250 +                               sizeof(*sqsh_ino));
2251 +               if (err < 0)
2252 +                       goto failed_read;
2253 +
2254 +               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
2255 +               inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
2256 +               inode->i_op = &page_symlink_inode_operations;
2257 +               inode->i_data.a_ops = &squashfs_symlink_aops;
2258 +               inode->i_mode |= S_IFLNK;
2259 +               squashfs_i(inode)->start = block;
2260 +               squashfs_i(inode)->offset = offset;
2261 +
2262 +               TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
2263 +                               "%x\n", SQUASHFS_INODE_BLK(ino), offset,
2264 +                               block, offset);
2265 +               break;
2266 +       }
2267 +       case SQUASHFS_BLKDEV_TYPE:
2268 +       case SQUASHFS_CHRDEV_TYPE:
2269 +       case SQUASHFS_LBLKDEV_TYPE:
2270 +       case SQUASHFS_LCHRDEV_TYPE: {
2271 +               struct squashfs_dev_inode *sqsh_ino = &squashfs_ino.dev;
2272 +               unsigned int rdev;
2273 +
2274 +               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
2275 +                               sizeof(*sqsh_ino));
2276 +               if (err < 0)
2277 +                       goto failed_read;
2278 +
2279 +               if (type == SQUASHFS_CHRDEV_TYPE)
2280 +                       inode->i_mode |= S_IFCHR;
2281 +               else
2282 +                       inode->i_mode |= S_IFBLK;
2283 +               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
2284 +               rdev = le32_to_cpu(sqsh_ino->rdev);
2285 +               init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
2286 +
2287 +               TRACE("Device inode %x:%x, rdev %x\n",
2288 +                               SQUASHFS_INODE_BLK(ino), offset, rdev);
2289 +               break;
2290 +       }
2291 +       case SQUASHFS_FIFO_TYPE:
2292 +       case SQUASHFS_SOCKET_TYPE:
2293 +       case SQUASHFS_LFIFO_TYPE:
2294 +       case SQUASHFS_LSOCKET_TYPE: {
2295 +               struct squashfs_ipc_inode *sqsh_ino = &squashfs_ino.ipc;
2296 +
2297 +               err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
2298 +                               sizeof(*sqsh_ino));
2299 +               if (err < 0)
2300 +                       goto failed_read;
2301 +
2302 +               if (type == SQUASHFS_FIFO_TYPE)
2303 +                       inode->i_mode |= S_IFIFO;
2304 +               else
2305 +                       inode->i_mode |= S_IFSOCK;
2306 +               inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
2307 +               init_special_inode(inode, inode->i_mode, 0);
2308 +               break;
2309 +       }
2310 +       default:
2311 +               ERROR("Unknown inode type %d in squashfs_iget!\n", type);
2312 +               return -EINVAL;
2313 +       }
2314 +
2315 +       return 0;
2316 +
2317 +failed_read:
2318 +       ERROR("Unable to read inode 0x%llx\n", ino);
2319 +       return err;
2320 +}
2321 diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
2322 new file mode 100644
2323 index 0000000..9e39865
2324 --- /dev/null
2325 +++ b/fs/squashfs/namei.c
2326 @@ -0,0 +1,242 @@
2327 +/*
2328 + * Squashfs - a compressed read only filesystem for Linux
2329 + *
2330 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
2331 + * Phillip Lougher <phillip@lougher.demon.co.uk>
2332 + *
2333 + * This program is free software; you can redistribute it and/or
2334 + * modify it under the terms of the GNU General Public License
2335 + * as published by the Free Software Foundation; either version 2,
2336 + * or (at your option) any later version.
2337 + *
2338 + * This program is distributed in the hope that it will be useful,
2339 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2340 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2341 + * GNU General Public License for more details.
2342 + *
2343 + * You should have received a copy of the GNU General Public License
2344 + * along with this program; if not, write to the Free Software
2345 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2346 + *
2347 + * namei.c
2348 + */
2349 +
2350 +/*
2351 + * This file implements code to do filename lookup in directories.
2352 + *
2353 + * Like inodes, directories are packed into compressed metadata blocks, stored
2354 + * in a directory table.  Directories are accessed using the start address of
2355 + * the metablock containing the directory and the offset into the
2356 + * decompressed block (<block, offset>).
2357 + *
2358 + * Directories are organised in a slightly complex way, and are not simply
2359 + * a list of file names.  The organisation takes advantage of the
2360 + * fact that (in most cases) the inodes of the files will be in the same
2361 + * compressed metadata block, and therefore, can share the start block.
2362 + * Directories are therefore organised in a two level list, a directory
2363 + * header containing the shared start block value, and a sequence of directory
2364 + * entries, each of which share the shared start block.  A new directory header
2365 + * is written once/if the inode start block changes.  The directory
2366 + * header/directory entry list is repeated as many times as necessary.
2367 + *
2368 + * Directories are sorted, and can contain a directory index to speed up
2369 + * file lookup.  Directory indexes store one entry per metablock, each entry
2370 + * storing the index/filename mapping to the first directory header
2371 + * in each metadata block.  Directories are sorted in alphabetical order,
2372 + * and at lookup the index is scanned linearly looking for the first filename
2373 + * alphabetically larger than the filename being looked up.  At this point the
2374 + * location of the metadata block the filename is in has been found.
2375 + * The general idea of the index is ensure only one metadata block needs to be
2376 + * decompressed to do a lookup irrespective of the length of the directory.
2377 + * This scheme has the advantage that it doesn't require extra memory overhead
2378 + * and doesn't require much extra storage on disk.
2379 + */
2380 +
2381 +#include <linux/fs.h>
2382 +#include <linux/vfs.h>
2383 +#include <linux/slab.h>
2384 +#include <linux/string.h>
2385 +#include <linux/dcache.h>
2386 +#include <linux/zlib.h>
2387 +
2388 +#include "squashfs_fs.h"
2389 +#include "squashfs_fs_sb.h"
2390 +#include "squashfs_fs_i.h"
2391 +#include "squashfs.h"
2392 +
2393 +/*
2394 + * Lookup name in the directory index, returning the location of the metadata
2395 + * block containing it, and the directory index this represents.
2396 + *
2397 + * If we get an error reading the index then return the part of the index
2398 + * (if any) we have managed to read - the index isn't essential, just
2399 + * quicker.
2400 + */
2401 +static int get_dir_index_using_name(struct super_block *sb,
2402 +                       u64 *next_block, int *next_offset, u64 index_start,
2403 +                       int index_offset, int i_count, const char *name,
2404 +                       int len)
2405 +{
2406 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
2407 +       int i, size, length = 0, err;
2408 +       struct squashfs_dir_index *index;
2409 +       char *str;
2410 +
2411 +       TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
2412 +
2413 +       index = kmalloc(sizeof(*index) + SQUASHFS_NAME_LEN * 2 + 2, GFP_KERNEL);
2414 +       if (index == NULL) {
2415 +               ERROR("Failed to allocate squashfs_dir_index\n");
2416 +               goto out;
2417 +       }
2418 +
2419 +       str = &index->name[SQUASHFS_NAME_LEN + 1];
2420 +       strncpy(str, name, len);
2421 +       str[len] = '\0';
2422 +
2423 +       for (i = 0; i < i_count; i++) {
2424 +               err = squashfs_read_metadata(sb, index, &index_start,
2425 +                                       &index_offset, sizeof(*index));
2426 +               if (err < 0)
2427 +                       break;
2428 +
2429 +
2430 +               size = le32_to_cpu(index->size) + 1;
2431 +
2432 +               err = squashfs_read_metadata(sb, index->name, &index_start,
2433 +                                       &index_offset, size);
2434 +               if (err < 0)
2435 +                       break;
2436 +
2437 +               index->name[size] = '\0';
2438 +
2439 +               if (strcmp(index->name, str) > 0)
2440 +                       break;
2441 +
2442 +               length = le32_to_cpu(index->index);
2443 +               *next_block = le32_to_cpu(index->start_block) +
2444 +                                       msblk->directory_table;
2445 +       }
2446 +
2447 +       *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
2448 +       kfree(index);
2449 +
2450 +out:
2451 +       /*
2452 +        * Return index (f_pos) of the looked up metadata block.  Translate
2453 +        * from internal f_pos to external f_pos which is offset by 3 because
2454 +        * we invent "." and ".." entries which are not actually stored in the
2455 +        * directory.
2456 +        */
2457 +       return length + 3;
2458 +}
2459 +
2460 +
2461 +static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
2462 +                                struct nameidata *nd)
2463 +{
2464 +       const unsigned char *name = dentry->d_name.name;
2465 +       int len = dentry->d_name.len;
2466 +       struct inode *inode = NULL;
2467 +       struct squashfs_sb_info *msblk = dir->i_sb->s_fs_info;
2468 +       struct squashfs_dir_header dirh;
2469 +       struct squashfs_dir_entry *dire;
2470 +       u64 block = squashfs_i(dir)->start + msblk->directory_table;
2471 +       int offset = squashfs_i(dir)->offset;
2472 +       int err, length = 0, dir_count, size;
2473 +
2474 +       TRACE("Entered squashfs_lookup [%llx:%x]\n", block, offset);
2475 +
2476 +       dire = kmalloc(sizeof(*dire) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL);
2477 +       if (dire == NULL) {
2478 +               ERROR("Failed to allocate squashfs_dir_entry\n");
2479 +               return ERR_PTR(-ENOMEM);
2480 +       }
2481 +
2482 +       if (len > SQUASHFS_NAME_LEN) {
2483 +               err = -ENAMETOOLONG;
2484 +               goto failed;
2485 +       }
2486 +
2487 +       length = get_dir_index_using_name(dir->i_sb, &block, &offset,
2488 +                               squashfs_i(dir)->dir_idx_start,
2489 +                               squashfs_i(dir)->dir_idx_offset,
2490 +                               squashfs_i(dir)->dir_idx_cnt, name, len);
2491 +
2492 +       while (length < i_size_read(dir)) {
2493 +               /*
2494 +                * Read directory header.
2495 +                */
2496 +               err = squashfs_read_metadata(dir->i_sb, &dirh, &block,
2497 +                               &offset, sizeof(dirh));
2498 +               if (err < 0)
2499 +                       goto read_failure;
2500 +
2501 +               length += sizeof(dirh);
2502 +
2503 +               dir_count = le32_to_cpu(dirh.count) + 1;
2504 +               while (dir_count--) {
2505 +                       /*
2506 +                        * Read directory entry.
2507 +                        */
2508 +                       err = squashfs_read_metadata(dir->i_sb, dire, &block,
2509 +                                       &offset, sizeof(*dire));
2510 +                       if (err < 0)
2511 +                               goto read_failure;
2512 +
2513 +                       size = le16_to_cpu(dire->size) + 1;
2514 +
2515 +                       err = squashfs_read_metadata(dir->i_sb, dire->name,
2516 +                                       &block, &offset, size);
2517 +                       if (err < 0)
2518 +                               goto read_failure;
2519 +
2520 +                       length += sizeof(*dire) + size;
2521 +
2522 +                       if (name[0] < dire->name[0])
2523 +                               goto exit_lookup;
2524 +
2525 +                       if (len == size && !strncmp(name, dire->name, len)) {
2526 +                               unsigned int blk, off, ino_num;
2527 +                               long long ino;
2528 +                               blk = le32_to_cpu(dirh.start_block);
2529 +                               off = le16_to_cpu(dire->offset);
2530 +                               ino_num = le32_to_cpu(dirh.inode_number) +
2531 +                                       (short) le16_to_cpu(dire->inode_number);
2532 +                               ino = SQUASHFS_MKINODE(blk, off);
2533 +
2534 +                               TRACE("calling squashfs_iget for directory "
2535 +                                       "entry %s, inode  %x:%x, %d\n", name,
2536 +                                       blk, off, ino_num);
2537 +
2538 +                               inode = squashfs_iget(dir->i_sb, ino, ino_num);
2539 +                               if (IS_ERR(inode)) {
2540 +                                       err = PTR_ERR(inode);
2541 +                                       goto failed;
2542 +                               }
2543 +
2544 +                               goto exit_lookup;
2545 +                       }
2546 +               }
2547 +       }
2548 +
2549 +exit_lookup:
2550 +       kfree(dire);
2551 +       if (inode)
2552 +               return d_splice_alias(inode, dentry);
2553 +       d_add(dentry, inode);
2554 +       return ERR_PTR(0);
2555 +
2556 +read_failure:
2557 +       ERROR("Unable to read directory block [%llx:%x]\n",
2558 +               squashfs_i(dir)->start + msblk->directory_table,
2559 +               squashfs_i(dir)->offset);
2560 +failed:
2561 +       kfree(dire);
2562 +       return ERR_PTR(err);
2563 +}
2564 +
2565 +
2566 +const struct inode_operations squashfs_dir_inode_ops = {
2567 +       .lookup = squashfs_lookup
2568 +};
2569 diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
2570 new file mode 100644
2571 index 0000000..0e9feb6
2572 --- /dev/null
2573 +++ b/fs/squashfs/squashfs.h
2574 @@ -0,0 +1,90 @@
2575 +/*
2576 + * Squashfs - a compressed read only filesystem for Linux
2577 + *
2578 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
2579 + * Phillip Lougher <phillip@lougher.demon.co.uk>
2580 + *
2581 + * This program is free software; you can redistribute it and/or
2582 + * modify it under the terms of the GNU General Public License
2583 + * as published by the Free Software Foundation; either version 2,
2584 + * or (at your option) any later version.
2585 + *
2586 + * This program is distributed in the hope that it will be useful,
2587 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2588 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2589 + * GNU General Public License for more details.
2590 + *
2591 + * You should have received a copy of the GNU General Public License
2592 + * along with this program; if not, write to the Free Software
2593 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2594 + *
2595 + * squashfs.h
2596 + */
2597 +
2598 +#define TRACE(s, args...)      pr_debug("SQUASHFS: "s, ## args)
2599 +
2600 +#define ERROR(s, args...)      pr_err("SQUASHFS error: "s, ## args)
2601 +
2602 +#define WARNING(s, args...)    pr_warning("SQUASHFS: "s, ## args)
2603 +
2604 +static inline struct squashfs_inode_info *squashfs_i(struct inode *inode)
2605 +{
2606 +       return list_entry(inode, struct squashfs_inode_info, vfs_inode);
2607 +}
2608 +
2609 +/* block.c */
2610 +extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *,
2611 +                               int, int);
2612 +
2613 +/* cache.c */
2614 +extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
2615 +extern void squashfs_cache_delete(struct squashfs_cache *);
2616 +extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *,
2617 +                               struct squashfs_cache *, u64, int);
2618 +extern void squashfs_cache_put(struct squashfs_cache_entry *);
2619 +extern int squashfs_copy_data(void *, struct squashfs_cache_entry *, int, int);
2620 +extern int squashfs_read_metadata(struct super_block *, void *, u64 *,
2621 +                               int *, int);
2622 +extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *,
2623 +                               u64, int);
2624 +extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *,
2625 +                               u64, int);
2626 +extern int squashfs_read_table(struct super_block *, void *, u64, int);
2627 +
2628 +/* export.c */
2629 +extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
2630 +                               unsigned int);
2631 +
2632 +/* fragment.c */
2633 +extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *);
2634 +extern __le64 *squashfs_read_fragment_index_table(struct super_block *,
2635 +                               u64, unsigned int);
2636 +
2637 +/* id.c */
2638 +extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
2639 +extern __le64 *squashfs_read_id_index_table(struct super_block *, u64,
2640 +                               unsigned short);
2641 +
2642 +/* inode.c */
2643 +extern struct inode *squashfs_iget(struct super_block *, long long,
2644 +                               unsigned int);
2645 +extern int squashfs_read_inode(struct inode *, long long);
2646 +
2647 +/*
2648 + * Inodes and files operations
2649 + */
2650 +
2651 +/* dir.c */
2652 +extern const struct file_operations squashfs_dir_ops;
2653 +
2654 +/* export.c */
2655 +extern const struct export_operations squashfs_export_ops;
2656 +
2657 +/* file.c */
2658 +extern const struct address_space_operations squashfs_aops;
2659 +
2660 +/* namei.c */
2661 +extern const struct inode_operations squashfs_dir_inode_ops;
2662 +
2663 +/* symlink.c */
2664 +extern const struct address_space_operations squashfs_symlink_aops;
2665 diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
2666 new file mode 100644
2667 index 0000000..70c3f39
2668 --- /dev/null
2669 +++ b/fs/squashfs/squashfs_fs.h
2670 @@ -0,0 +1,382 @@
2671 +#ifndef SQUASHFS_FS
2672 +#define SQUASHFS_FS
2673 +/*
2674 + * Squashfs
2675 + *
2676 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
2677 + * Phillip Lougher <phillip@lougher.demon.co.uk>
2678 + *
2679 + * This program is free software; you can redistribute it and/or
2680 + * modify it under the terms of the GNU General Public License
2681 + * as published by the Free Software Foundation; either version 2,
2682 + * or (at your option) any later version.
2683 + *
2684 + * This program is distributed in the hope that it will be useful,
2685 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2686 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2687 + * GNU General Public License for more details.
2688 + *
2689 + * You should have received a copy of the GNU General Public License
2690 + * along with this program; if not, write to the Free Software
2691 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2692 + *
2693 + * squashfs_fs.h
2694 + */
2695 +
2696 +#define SQUASHFS_MAGIC         0x73717368
2697 +
2698 +#define SQUASHFS_CACHED_FRAGMENTS      CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
2699 +#define SQUASHFS_MAJOR                 4
2700 +#define SQUASHFS_MINOR                 0
2701 +#define SQUASHFS_START                 0
2702 +
2703 +/* size of metadata (inode and directory) blocks */
2704 +#define SQUASHFS_METADATA_SIZE         8192
2705 +#define SQUASHFS_METADATA_LOG          13
2706 +
2707 +/* default size of data blocks */
2708 +#define SQUASHFS_FILE_SIZE             131072
2709 +#define SQUASHFS_FILE_LOG              17
2710 +
2711 +#define SQUASHFS_FILE_MAX_SIZE         1048576
2712 +#define SQUASHFS_FILE_MAX_LOG          20
2713 +
2714 +/* Max number of uids and gids */
2715 +#define SQUASHFS_IDS                   65536
2716 +
2717 +/* Max length of filename (not 255) */
2718 +#define SQUASHFS_NAME_LEN              256
2719 +
2720 +#define SQUASHFS_INVALID_FRAG          (0xffffffffU)
2721 +#define SQUASHFS_INVALID_BLK           (-1LL)
2722 +
2723 +/* Filesystem flags */
2724 +#define SQUASHFS_NOI                   0
2725 +#define SQUASHFS_NOD                   1
2726 +#define SQUASHFS_NOF                   3
2727 +#define SQUASHFS_NO_FRAG               4
2728 +#define SQUASHFS_ALWAYS_FRAG           5
2729 +#define SQUASHFS_DUPLICATE             6
2730 +#define SQUASHFS_EXPORT                        7
2731 +
2732 +#define SQUASHFS_BIT(flag, bit)                ((flag >> bit) & 1)
2733 +
2734 +#define SQUASHFS_UNCOMPRESSED_INODES(flags)    SQUASHFS_BIT(flags, \
2735 +                                               SQUASHFS_NOI)
2736 +
2737 +#define SQUASHFS_UNCOMPRESSED_DATA(flags)      SQUASHFS_BIT(flags, \
2738 +                                               SQUASHFS_NOD)
2739 +
2740 +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
2741 +                                               SQUASHFS_NOF)
2742 +
2743 +#define SQUASHFS_NO_FRAGMENTS(flags)           SQUASHFS_BIT(flags, \
2744 +                                               SQUASHFS_NO_FRAG)
2745 +
2746 +#define SQUASHFS_ALWAYS_FRAGMENTS(flags)       SQUASHFS_BIT(flags, \
2747 +                                               SQUASHFS_ALWAYS_FRAG)
2748 +
2749 +#define SQUASHFS_DUPLICATES(flags)             SQUASHFS_BIT(flags, \
2750 +                                               SQUASHFS_DUPLICATE)
2751 +
2752 +#define SQUASHFS_EXPORTABLE(flags)             SQUASHFS_BIT(flags, \
2753 +                                               SQUASHFS_EXPORT)
2754 +
2755 +/* Max number of types and file types */
2756 +#define SQUASHFS_DIR_TYPE              1
2757 +#define SQUASHFS_REG_TYPE              2
2758 +#define SQUASHFS_SYMLINK_TYPE          3
2759 +#define SQUASHFS_BLKDEV_TYPE           4
2760 +#define SQUASHFS_CHRDEV_TYPE           5
2761 +#define SQUASHFS_FIFO_TYPE             6
2762 +#define SQUASHFS_SOCKET_TYPE           7
2763 +#define SQUASHFS_LDIR_TYPE             8
2764 +#define SQUASHFS_LREG_TYPE             9
2765 +#define SQUASHFS_LSYMLINK_TYPE         10
2766 +#define SQUASHFS_LBLKDEV_TYPE          11
2767 +#define SQUASHFS_LCHRDEV_TYPE          12
2768 +#define SQUASHFS_LFIFO_TYPE            13
2769 +#define SQUASHFS_LSOCKET_TYPE          14
2770 +
2771 +/* Flag whether block is compressed or uncompressed, bit is set if block is
2772 + * uncompressed */
2773 +#define SQUASHFS_COMPRESSED_BIT                (1 << 15)
2774 +
2775 +#define SQUASHFS_COMPRESSED_SIZE(B)    (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
2776 +               (B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
2777 +
2778 +#define SQUASHFS_COMPRESSED(B)         (!((B) & SQUASHFS_COMPRESSED_BIT))
2779 +
2780 +#define SQUASHFS_COMPRESSED_BIT_BLOCK  (1 << 24)
2781 +
2782 +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)      ((B) & \
2783 +                                               ~SQUASHFS_COMPRESSED_BIT_BLOCK)
2784 +
2785 +#define SQUASHFS_COMPRESSED_BLOCK(B)   (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
2786 +
2787 +/*
2788 + * Inode number ops.  Inodes consist of a compressed block number, and an
2789 + * uncompressed offset within that block
2790 + */
2791 +#define SQUASHFS_INODE_BLK(A)          ((unsigned int) ((A) >> 16))
2792 +
2793 +#define SQUASHFS_INODE_OFFSET(A)       ((unsigned int) ((A) & 0xffff))
2794 +
2795 +#define SQUASHFS_MKINODE(A, B)         ((long long)(((long long) (A)\
2796 +                                       << 16) + (B)))
2797 +
2798 +/* Translate between VFS mode and squashfs mode */
2799 +#define SQUASHFS_MODE(A)               ((A) & 0xfff)
2800 +
2801 +/* fragment and fragment table defines */
2802 +#define SQUASHFS_FRAGMENT_BYTES(A)     \
2803 +                               ((A) * sizeof(struct squashfs_fragment_entry))
2804 +
2805 +#define SQUASHFS_FRAGMENT_INDEX(A)     (SQUASHFS_FRAGMENT_BYTES(A) / \
2806 +                                       SQUASHFS_METADATA_SIZE)
2807 +
2808 +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)      (SQUASHFS_FRAGMENT_BYTES(A) % \
2809 +                                               SQUASHFS_METADATA_SIZE)
2810 +
2811 +#define SQUASHFS_FRAGMENT_INDEXES(A)   ((SQUASHFS_FRAGMENT_BYTES(A) + \
2812 +                                       SQUASHFS_METADATA_SIZE - 1) / \
2813 +                                       SQUASHFS_METADATA_SIZE)
2814 +
2815 +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)       (SQUASHFS_FRAGMENT_INDEXES(A) *\
2816 +                                               sizeof(u64))
2817 +
2818 +/* inode lookup table defines */
2819 +#define SQUASHFS_LOOKUP_BYTES(A)       ((A) * sizeof(u64))
2820 +
2821 +#define SQUASHFS_LOOKUP_BLOCK(A)       (SQUASHFS_LOOKUP_BYTES(A) / \
2822 +                                       SQUASHFS_METADATA_SIZE)
2823 +
2824 +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A)        (SQUASHFS_LOOKUP_BYTES(A) % \
2825 +                                       SQUASHFS_METADATA_SIZE)
2826 +
2827 +#define SQUASHFS_LOOKUP_BLOCKS(A)      ((SQUASHFS_LOOKUP_BYTES(A) + \
2828 +                                       SQUASHFS_METADATA_SIZE - 1) / \
2829 +                                       SQUASHFS_METADATA_SIZE)
2830 +
2831 +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
2832 +                                       sizeof(u64))
2833 +
2834 +/* uid/gid lookup table defines */
2835 +#define SQUASHFS_ID_BYTES(A)           ((A) * sizeof(unsigned int))
2836 +
2837 +#define SQUASHFS_ID_BLOCK(A)           (SQUASHFS_ID_BYTES(A) / \
2838 +                                       SQUASHFS_METADATA_SIZE)
2839 +
2840 +#define SQUASHFS_ID_BLOCK_OFFSET(A)    (SQUASHFS_ID_BYTES(A) % \
2841 +                                       SQUASHFS_METADATA_SIZE)
2842 +
2843 +#define SQUASHFS_ID_BLOCKS(A)          ((SQUASHFS_ID_BYTES(A) + \
2844 +                                       SQUASHFS_METADATA_SIZE - 1) / \
2845 +                                       SQUASHFS_METADATA_SIZE)
2846 +
2847 +#define SQUASHFS_ID_BLOCK_BYTES(A)     (SQUASHFS_ID_BLOCKS(A) *\
2848 +                                       sizeof(u64))
2849 +
2850 +/* cached data constants for filesystem */
2851 +#define SQUASHFS_CACHED_BLKS           8
2852 +
2853 +#define SQUASHFS_MAX_FILE_SIZE_LOG     64
2854 +
2855 +#define SQUASHFS_MAX_FILE_SIZE         (1LL << \
2856 +                                       (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
2857 +
2858 +#define SQUASHFS_MARKER_BYTE           0xff
2859 +
2860 +/* meta index cache */
2861 +#define SQUASHFS_META_INDEXES  (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
2862 +#define SQUASHFS_META_ENTRIES  127
2863 +#define SQUASHFS_META_SLOTS    8
2864 +
2865 +struct meta_entry {
2866 +       u64                     data_block;
2867 +       unsigned int            index_block;
2868 +       unsigned short          offset;
2869 +       unsigned short          pad;
2870 +};
2871 +
2872 +struct meta_index {
2873 +       unsigned int            inode_number;
2874 +       unsigned int            offset;
2875 +       unsigned short          entries;
2876 +       unsigned short          skip;
2877 +       unsigned short          locked;
2878 +       unsigned short          pad;
2879 +       struct meta_entry       meta_entry[SQUASHFS_META_ENTRIES];
2880 +};
2881 +
2882 +
2883 +/*
2884 + * definitions for structures on disk
2885 + */
2886 +#define ZLIB_COMPRESSION        1
2887 +
2888 +struct squashfs_super_block {
2889 +       __le32                  s_magic;
2890 +       __le32                  inodes;
2891 +       __le32                  mkfs_time;
2892 +       __le32                  block_size;
2893 +       __le32                  fragments;
2894 +       __le16                  compression;
2895 +       __le16                  block_log;
2896 +       __le16                  flags;
2897 +       __le16                  no_ids;
2898 +       __le16                  s_major;
2899 +       __le16                  s_minor;
2900 +       __le64                  root_inode;
2901 +       __le64                  bytes_used;
2902 +       __le64                  id_table_start;
2903 +       __le64                  xattr_table_start;
2904 +       __le64                  inode_table_start;
2905 +       __le64                  directory_table_start;
2906 +       __le64                  fragment_table_start;
2907 +       __le64                  lookup_table_start;
2908 +};
2909 +
2910 +struct squashfs_dir_index {
2911 +       __le32                  index;
2912 +       __le32                  start_block;
2913 +       __le32                  size;
2914 +       unsigned char           name[0];
2915 +};
2916 +
2917 +struct squashfs_base_inode {
2918 +       __le16                  inode_type;
2919 +       __le16                  mode;
2920 +       __le16                  uid;
2921 +       __le16                  guid;
2922 +       __le32                  mtime;
2923 +       __le32                  inode_number;
2924 +};
2925 +
2926 +struct squashfs_ipc_inode {
2927 +       __le16                  inode_type;
2928 +       __le16                  mode;
2929 +       __le16                  uid;
2930 +       __le16                  guid;
2931 +       __le32                  mtime;
2932 +       __le32                  inode_number;
2933 +       __le32                  nlink;
2934 +};
2935 +
2936 +struct squashfs_dev_inode {
2937 +       __le16                  inode_type;
2938 +       __le16                  mode;
2939 +       __le16                  uid;
2940 +       __le16                  guid;
2941 +       __le32                  mtime;
2942 +       __le32                  inode_number;
2943 +       __le32                  nlink;
2944 +       __le32                  rdev;
2945 +};
2946 +
2947 +struct squashfs_symlink_inode {
2948 +       __le16                  inode_type;
2949 +       __le16                  mode;
2950 +       __le16                  uid;
2951 +       __le16                  guid;
2952 +       __le32                  mtime;
2953 +       __le32                  inode_number;
2954 +       __le32                  nlink;
2955 +       __le32                  symlink_size;
2956 +       char                    symlink[0];
2957 +};
2958 +
2959 +struct squashfs_reg_inode {
2960 +       __le16                  inode_type;
2961 +       __le16                  mode;
2962 +       __le16                  uid;
2963 +       __le16                  guid;
2964 +       __le32                  mtime;
2965 +       __le32                  inode_number;
2966 +       __le32                  start_block;
2967 +       __le32                  fragment;
2968 +       __le32                  offset;
2969 +       __le32                  file_size;
2970 +       __le16                  block_list[0];
2971 +};
2972 +
2973 +struct squashfs_lreg_inode {
2974 +       __le16                  inode_type;
2975 +       __le16                  mode;
2976 +       __le16                  uid;
2977 +       __le16                  guid;
2978 +       __le32                  mtime;
2979 +       __le32                  inode_number;
2980 +       __le64                  start_block;
2981 +       __le64                  file_size;
2982 +       __le64                  sparse;
2983 +       __le32                  nlink;
2984 +       __le32                  fragment;
2985 +       __le32                  offset;
2986 +       __le32                  xattr;
2987 +       __le16                  block_list[0];
2988 +};
2989 +
2990 +struct squashfs_dir_inode {
2991 +       __le16                  inode_type;
2992 +       __le16                  mode;
2993 +       __le16                  uid;
2994 +       __le16                  guid;
2995 +       __le32                  mtime;
2996 +       __le32                  inode_number;
2997 +       __le32                  start_block;
2998 +       __le32                  nlink;
2999 +       __le16                  file_size;
3000 +       __le16                  offset;
3001 +       __le32                  parent_inode;
3002 +};
3003 +
3004 +struct squashfs_ldir_inode {
3005 +       __le16                  inode_type;
3006 +       __le16                  mode;
3007 +       __le16                  uid;
3008 +       __le16                  guid;
3009 +       __le32                  mtime;
3010 +       __le32                  inode_number;
3011 +       __le32                  nlink;
3012 +       __le32                  file_size;
3013 +       __le32                  start_block;
3014 +       __le32                  parent_inode;
3015 +       __le16                  i_count;
3016 +       __le16                  offset;
3017 +       __le32                  xattr;
3018 +       struct squashfs_dir_index       index[0];
3019 +};
3020 +
3021 +union squashfs_inode {
3022 +       struct squashfs_base_inode              base;
3023 +       struct squashfs_dev_inode               dev;
3024 +       struct squashfs_symlink_inode           symlink;
3025 +       struct squashfs_reg_inode               reg;
3026 +       struct squashfs_lreg_inode              lreg;
3027 +       struct squashfs_dir_inode               dir;
3028 +       struct squashfs_ldir_inode              ldir;
3029 +       struct squashfs_ipc_inode               ipc;
3030 +};
3031 +
3032 +struct squashfs_dir_entry {
3033 +       __le16                  offset;
3034 +       __le16                  inode_number;
3035 +       __le16                  type;
3036 +       __le16                  size;
3037 +       char                    name[0];
3038 +};
3039 +
3040 +struct squashfs_dir_header {
3041 +       __le32                  count;
3042 +       __le32                  start_block;
3043 +       __le32                  inode_number;
3044 +};
3045 +
3046 +struct squashfs_fragment_entry {
3047 +       __le64                  start_block;
3048 +       __le32                  size;
3049 +       unsigned int            unused;
3050 +};
3051 +
3052 +#endif
3053 diff --git a/fs/squashfs/squashfs_fs_i.h b/fs/squashfs/squashfs_fs_i.h
3054 new file mode 100644
3055 index 0000000..fbfca30
3056 --- /dev/null
3057 +++ b/fs/squashfs/squashfs_fs_i.h
3058 @@ -0,0 +1,45 @@
3059 +#ifndef SQUASHFS_FS_I
3060 +#define SQUASHFS_FS_I
3061 +/*
3062 + * Squashfs
3063 + *
3064 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
3065 + * Phillip Lougher <phillip@lougher.demon.co.uk>
3066 + *
3067 + * This program is free software; you can redistribute it and/or
3068 + * modify it under the terms of the GNU General Public License
3069 + * as published by the Free Software Foundation; either version 2,
3070 + * or (at your option) any later version.
3071 + *
3072 + * This program is distributed in the hope that it will be useful,
3073 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3074 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3075 + * GNU General Public License for more details.
3076 + *
3077 + * You should have received a copy of the GNU General Public License
3078 + * along with this program; if not, write to the Free Software
3079 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3080 + *
3081 + * squashfs_fs_i.h
3082 + */
3083 +
3084 +struct squashfs_inode_info {
3085 +       u64             start;
3086 +       int             offset;
3087 +       union {
3088 +               struct {
3089 +                       u64             fragment_block;
3090 +                       int             fragment_size;
3091 +                       int             fragment_offset;
3092 +                       u64             block_list_start;
3093 +               };
3094 +               struct {
3095 +                       u64             dir_idx_start;
3096 +                       int             dir_idx_offset;
3097 +                       int             dir_idx_cnt;
3098 +                       int             parent;
3099 +               };
3100 +       };
3101 +       struct inode    vfs_inode;
3102 +};
3103 +#endif
3104 diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
3105 new file mode 100644
3106 index 0000000..c8c6561
3107 --- /dev/null
3108 +++ b/fs/squashfs/squashfs_fs_sb.h
3109 @@ -0,0 +1,76 @@
3110 +#ifndef SQUASHFS_FS_SB
3111 +#define SQUASHFS_FS_SB
3112 +/*
3113 + * Squashfs
3114 + *
3115 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
3116 + * Phillip Lougher <phillip@lougher.demon.co.uk>
3117 + *
3118 + * This program is free software; you can redistribute it and/or
3119 + * modify it under the terms of the GNU General Public License
3120 + * as published by the Free Software Foundation; either version 2,
3121 + * or (at your option) any later version.
3122 + *
3123 + * This program is distributed in the hope that it will be useful,
3124 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3125 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3126 + * GNU General Public License for more details.
3127 + *
3128 + * You should have received a copy of the GNU General Public License
3129 + * along with this program; if not, write to the Free Software
3130 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3131 + *
3132 + * squashfs_fs_sb.h
3133 + */
3134 +
3135 +#include "squashfs_fs.h"
3136 +
3137 +struct squashfs_cache {
3138 +       char                    *name;
3139 +       int                     entries;
3140 +       int                     next_blk;
3141 +       int                     num_waiters;
3142 +       int                     unused;
3143 +       int                     block_size;
3144 +       int                     pages;
3145 +       spinlock_t              lock;
3146 +       wait_queue_head_t       wait_queue;
3147 +       struct squashfs_cache_entry *entry;
3148 +};
3149 +
3150 +struct squashfs_cache_entry {
3151 +       u64                     block;
3152 +       int                     length;
3153 +       int                     refcount;
3154 +       u64                     next_index;
3155 +       int                     pending;
3156 +       int                     error;
3157 +       int                     num_waiters;
3158 +       wait_queue_head_t       wait_queue;
3159 +       struct squashfs_cache   *cache;
3160 +       void                    **data;
3161 +};
3162 +
3163 +struct squashfs_sb_info {
3164 +       int                     devblksize;
3165 +       int                     devblksize_log2;
3166 +       struct squashfs_cache   *block_cache;
3167 +       struct squashfs_cache   *fragment_cache;
3168 +       struct squashfs_cache   *read_page;
3169 +       int                     next_meta_index;
3170 +       __le64                  *id_table;
3171 +       __le64                  *fragment_index;
3172 +       unsigned int            *fragment_index_2;
3173 +       struct mutex            read_data_mutex;
3174 +       struct mutex            meta_index_mutex;
3175 +       struct meta_index       *meta_index;
3176 +       z_stream                stream;
3177 +       __le64                  *inode_lookup_table;
3178 +       u64                     inode_table;
3179 +       u64                     directory_table;
3180 +       unsigned int            block_size;
3181 +       unsigned short          block_log;
3182 +       long long               bytes_used;
3183 +       unsigned int            inodes;
3184 +};
3185 +#endif
3186 diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
3187 new file mode 100644
3188 index 0000000..0adc624
3189 --- /dev/null
3190 +++ b/fs/squashfs/super.c
3191 @@ -0,0 +1,454 @@
3192 +/*
3193 + * Squashfs - a compressed read only filesystem for Linux
3194 + *
3195 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
3196 + * Phillip Lougher <phillip@lougher.demon.co.uk>
3197 + *
3198 + * This program is free software; you can redistribute it and/or
3199 + * modify it under the terms of the GNU General Public License
3200 + * as published by the Free Software Foundation; either version 2,
3201 + * or (at your option) any later version.
3202 + *
3203 + * This program is distributed in the hope that it will be useful,
3204 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3205 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3206 + * GNU General Public License for more details.
3207 + *
3208 + * You should have received a copy of the GNU General Public License
3209 + * along with this program; if not, write to the Free Software
3210 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3211 + *
3212 + * super.c
3213 + */
3214 +
3215 +/*
3216 + * This file implements code to read the superblock, read and initialise
3217 + * in-memory structures at mount time, and all the VFS glue code to register
3218 + * the filesystem.
3219 + */
3220 +
3221 +#include <linux/fs.h>
3222 +#include <linux/vfs.h>
3223 +#include <linux/slab.h>
3224 +#include <linux/mutex.h>
3225 +#include <linux/pagemap.h>
3226 +#include <linux/init.h>
3227 +#include <linux/module.h>
3228 +#include <linux/zlib.h>
3229 +#include <linux/magic.h>
3230 +
3231 +#include "squashfs_fs.h"
3232 +#include "squashfs_fs_sb.h"
3233 +#include "squashfs_fs_i.h"
3234 +#include "squashfs.h"
3235 +
3236 +static struct file_system_type squashfs_fs_type;
3237 +static struct super_operations squashfs_super_ops;
3238 +
3239 +static int supported_squashfs_filesystem(short major, short minor, short comp)
3240 +{
3241 +       if (major < SQUASHFS_MAJOR) {
3242 +               ERROR("Major/Minor mismatch, older Squashfs %d.%d "
3243 +                       "filesystems are unsupported\n", major, minor);
3244 +               return -EINVAL;
3245 +       } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
3246 +               ERROR("Major/Minor mismatch, trying to mount newer "
3247 +                       "%d.%d filesystem\n", major, minor);
3248 +               ERROR("Please update your kernel\n");
3249 +               return -EINVAL;
3250 +       }
3251 +
3252 +       if (comp != ZLIB_COMPRESSION)
3253 +               return -EINVAL;
3254 +
3255 +       return 0;
3256 +}
3257 +
3258 +
3259 +static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
3260 +{
3261 +       struct squashfs_sb_info *msblk;
3262 +       struct squashfs_super_block *sblk = NULL;
3263 +       char b[BDEVNAME_SIZE];
3264 +       struct inode *root;
3265 +       long long root_inode;
3266 +       unsigned short flags;
3267 +       unsigned int fragments;
3268 +       u64 lookup_table_start;
3269 +       int err;
3270 +
3271 +       TRACE("Entered squashfs_fill_superblock\n");
3272 +
3273 +       sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL);
3274 +       if (sb->s_fs_info == NULL) {
3275 +               ERROR("Failed to allocate squashfs_sb_info\n");
3276 +               return -ENOMEM;
3277 +       }
3278 +       msblk = sb->s_fs_info;
3279 +
3280 +       msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
3281 +               GFP_KERNEL);
3282 +       if (msblk->stream.workspace == NULL) {
3283 +               ERROR("Failed to allocate zlib workspace\n");
3284 +               goto failure;
3285 +       }
3286 +
3287 +       sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
3288 +       if (sblk == NULL) {
3289 +               ERROR("Failed to allocate squashfs_super_block\n");
3290 +               goto failure;
3291 +       }
3292 +
3293 +       msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE);
3294 +       msblk->devblksize_log2 = ffz(~msblk->devblksize);
3295 +
3296 +       mutex_init(&msblk->read_data_mutex);
3297 +       mutex_init(&msblk->meta_index_mutex);
3298 +
3299 +       /*
3300 +        * msblk->bytes_used is checked in squashfs_read_table to ensure reads
3301 +        * are not beyond filesystem end.  But as we're using
3302 +        * squashfs_read_table here to read the superblock (including the value
3303 +        * of bytes_used) we need to set it to an initial sensible dummy value
3304 +        */
3305 +       msblk->bytes_used = sizeof(*sblk);
3306 +       err = squashfs_read_table(sb, sblk, SQUASHFS_START, sizeof(*sblk));
3307 +
3308 +       if (err < 0) {
3309 +               ERROR("unable to read squashfs_super_block\n");
3310 +               goto failed_mount;
3311 +       }
3312 +
3313 +       /* Check it is a SQUASHFS superblock */
3314 +       sb->s_magic = le32_to_cpu(sblk->s_magic);
3315 +       if (sb->s_magic != SQUASHFS_MAGIC) {
3316 +               if (!silent)
3317 +                       ERROR("Can't find a SQUASHFS superblock on %s\n",
3318 +                                               bdevname(sb->s_bdev, b));
3319 +               err = -EINVAL;
3320 +               goto failed_mount;
3321 +       }
3322 +
3323 +       /* Check the MAJOR & MINOR versions and compression type */
3324 +       err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
3325 +                       le16_to_cpu(sblk->s_minor),
3326 +                       le16_to_cpu(sblk->compression));
3327 +       if (err < 0)
3328 +               goto failed_mount;
3329 +
3330 +       err = -EINVAL;
3331 +
3332 +       /*
3333 +        * Check if there's xattrs in the filesystem.  These are not
3334 +        * supported in this version, so warn that they will be ignored.
3335 +        */
3336 +       if (le64_to_cpu(sblk->xattr_table_start) != SQUASHFS_INVALID_BLK)
3337 +               ERROR("Xattrs in filesystem, these will be ignored\n");
3338 +
3339 +       /* Check the filesystem does not extend beyond the end of the
3340 +          block device */
3341 +       msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
3342 +       if (msblk->bytes_used < 0 || msblk->bytes_used >
3343 +                       i_size_read(sb->s_bdev->bd_inode))
3344 +               goto failed_mount;
3345 +
3346 +       /* Check block size for sanity */
3347 +       msblk->block_size = le32_to_cpu(sblk->block_size);
3348 +       if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
3349 +               goto failed_mount;
3350 +
3351 +       /*
3352 +        * Check the system page size is not larger than the filesystem
3353 +        * block size (by default 128K).  This is currently not supported.
3354 +        */
3355 +       if (PAGE_CACHE_SIZE > msblk->block_size) {
3356 +               ERROR("Page size > filesystem block size (%d).  This is "
3357 +                       "currently not supported!\n", msblk->block_size);
3358 +               goto failed_mount;
3359 +       }
3360 +
3361 +       msblk->block_log = le16_to_cpu(sblk->block_log);
3362 +       if (msblk->block_log > SQUASHFS_FILE_MAX_LOG)
3363 +               goto failed_mount;
3364 +
3365 +       /* Check the root inode for sanity */
3366 +       root_inode = le64_to_cpu(sblk->root_inode);
3367 +       if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
3368 +               goto failed_mount;
3369 +
3370 +       msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
3371 +       msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
3372 +       msblk->inodes = le32_to_cpu(sblk->inodes);
3373 +       flags = le16_to_cpu(sblk->flags);
3374 +
3375 +       TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b));
3376 +       TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(flags)
3377 +                               ? "un" : "");
3378 +       TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(flags)
3379 +                               ? "un" : "");
3380 +       TRACE("Filesystem size %lld bytes\n", msblk->bytes_used);
3381 +       TRACE("Block size %d\n", msblk->block_size);
3382 +       TRACE("Number of inodes %d\n", msblk->inodes);
3383 +       TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments));
3384 +       TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids));
3385 +       TRACE("sblk->inode_table_start %llx\n", msblk->inode_table);
3386 +       TRACE("sblk->directory_table_start %llx\n", msblk->directory_table);
3387 +       TRACE("sblk->fragment_table_start %llx\n",
3388 +               (u64) le64_to_cpu(sblk->fragment_table_start));
3389 +       TRACE("sblk->id_table_start %llx\n",
3390 +               (u64) le64_to_cpu(sblk->id_table_start));
3391 +
3392 +       sb->s_maxbytes = MAX_LFS_FILESIZE;
3393 +       sb->s_flags |= MS_RDONLY;
3394 +       sb->s_op = &squashfs_super_ops;
3395 +
3396 +       err = -ENOMEM;
3397 +
3398 +       msblk->block_cache = squashfs_cache_init("metadata",
3399 +                       SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
3400 +       if (msblk->block_cache == NULL)
3401 +               goto failed_mount;
3402 +
3403 +       /* Allocate read_page block */
3404 +       msblk->read_page = squashfs_cache_init("data", 1, msblk->block_size);
3405 +       if (msblk->read_page == NULL) {
3406 +               ERROR("Failed to allocate read_page block\n");
3407 +               goto failed_mount;
3408 +       }
3409 +
3410 +       /* Allocate and read id index table */
3411 +       msblk->id_table = squashfs_read_id_index_table(sb,
3412 +               le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids));
3413 +       if (IS_ERR(msblk->id_table)) {
3414 +               err = PTR_ERR(msblk->id_table);
3415 +               msblk->id_table = NULL;
3416 +               goto failed_mount;
3417 +       }
3418 +
3419 +       fragments = le32_to_cpu(sblk->fragments);
3420 +       if (fragments == 0)
3421 +               goto allocate_lookup_table;
3422 +
3423 +       msblk->fragment_cache = squashfs_cache_init("fragment",
3424 +               SQUASHFS_CACHED_FRAGMENTS, msblk->block_size);
3425 +       if (msblk->fragment_cache == NULL) {
3426 +               err = -ENOMEM;
3427 +               goto failed_mount;
3428 +       }
3429 +
3430 +       /* Allocate and read fragment index table */
3431 +       msblk->fragment_index = squashfs_read_fragment_index_table(sb,
3432 +               le64_to_cpu(sblk->fragment_table_start), fragments);
3433 +       if (IS_ERR(msblk->fragment_index)) {
3434 +               err = PTR_ERR(msblk->fragment_index);
3435 +               msblk->fragment_index = NULL;
3436 +               goto failed_mount;
3437 +       }
3438 +
3439 +allocate_lookup_table:
3440 +       lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
3441 +       if (lookup_table_start == SQUASHFS_INVALID_BLK)
3442 +               goto allocate_root;
3443 +
3444 +       /* Allocate and read inode lookup table */
3445 +       msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
3446 +               lookup_table_start, msblk->inodes);
3447 +       if (IS_ERR(msblk->inode_lookup_table)) {
3448 +               err = PTR_ERR(msblk->inode_lookup_table);
3449 +               msblk->inode_lookup_table = NULL;
3450 +               goto failed_mount;
3451 +       }
3452 +
3453 +       sb->s_export_op = &squashfs_export_ops;
3454 +
3455 +allocate_root:
3456 +       root = new_inode(sb);
3457 +       if (!root) {
3458 +               err = -ENOMEM;
3459 +               goto failed_mount;
3460 +       }
3461 +
3462 +       err = squashfs_read_inode(root, root_inode);
3463 +       if (err) {
3464 +               iget_failed(root);
3465 +               goto failed_mount;
3466 +       }
3467 +       insert_inode_hash(root);
3468 +
3469 +       sb->s_root = d_alloc_root(root);
3470 +       if (sb->s_root == NULL) {
3471 +               ERROR("Root inode create failed\n");
3472 +               err = -ENOMEM;
3473 +               iput(root);
3474 +               goto failed_mount;
3475 +       }
3476 +
3477 +       TRACE("Leaving squashfs_fill_super\n");
3478 +       kfree(sblk);
3479 +       return 0;
3480 +
3481 +failed_mount:
3482 +       squashfs_cache_delete(msblk->block_cache);
3483 +       squashfs_cache_delete(msblk->fragment_cache);
3484 +       squashfs_cache_delete(msblk->read_page);
3485 +       kfree(msblk->inode_lookup_table);
3486 +       kfree(msblk->fragment_index);
3487 +       kfree(msblk->id_table);
3488 +       kfree(msblk->stream.workspace);
3489 +       kfree(sb->s_fs_info);
3490 +       sb->s_fs_info = NULL;
3491 +       kfree(sblk);
3492 +       return err;
3493 +
3494 +failure:
3495 +       kfree(msblk->stream.workspace);
3496 +       kfree(sb->s_fs_info);
3497 +       sb->s_fs_info = NULL;
3498 +       return -ENOMEM;
3499 +}
3500 +
3501 +
3502 +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
3503 +{
3504 +       struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
3505 +       u64 id = huge_encode_dev(dentry->d_sb->s_bdev->bd_dev);
3506 +
3507 +       TRACE("Entered squashfs_statfs\n");
3508 +
3509 +       buf->f_type = SQUASHFS_MAGIC;
3510 +       buf->f_bsize = msblk->block_size;
3511 +       buf->f_blocks = ((msblk->bytes_used - 1) >> msblk->block_log) + 1;
3512 +       buf->f_bfree = buf->f_bavail = 0;
3513 +       buf->f_files = msblk->inodes;
3514 +       buf->f_ffree = 0;
3515 +       buf->f_namelen = SQUASHFS_NAME_LEN;
3516 +       buf->f_fsid.val[0] = (u32)id;
3517 +       buf->f_fsid.val[1] = (u32)(id >> 32);
3518 +
3519 +       return 0;
3520 +}
3521 +
3522 +
3523 +static int squashfs_remount(struct super_block *sb, int *flags, char *data)
3524 +{
3525 +       *flags |= MS_RDONLY;
3526 +       return 0;
3527 +}
3528 +
3529 +
3530 +static void squashfs_put_super(struct super_block *sb)
3531 +{
3532 +       if (sb->s_fs_info) {
3533 +               struct squashfs_sb_info *sbi = sb->s_fs_info;
3534 +               squashfs_cache_delete(sbi->block_cache);
3535 +               squashfs_cache_delete(sbi->fragment_cache);
3536 +               squashfs_cache_delete(sbi->read_page);
3537 +               kfree(sbi->id_table);
3538 +               kfree(sbi->fragment_index);
3539 +               kfree(sbi->meta_index);
3540 +               kfree(sbi->stream.workspace);
3541 +               kfree(sb->s_fs_info);
3542 +               sb->s_fs_info = NULL;
3543 +       }
3544 +}
3545 +
3546 +
3547 +static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
3548 +                               const char *dev_name, void *data,
3549 +                               struct vfsmount *mnt)
3550 +{
3551 +       return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
3552 +                               mnt);
3553 +}
3554 +
3555 +
3556 +static struct kmem_cache *squashfs_inode_cachep;
3557 +
3558 +
3559 +static void init_once(void *foo)
3560 +{
3561 +       struct squashfs_inode_info *ei = foo;
3562 +
3563 +       inode_init_once(&ei->vfs_inode);
3564 +}
3565 +
3566 +
3567 +static int __init init_inodecache(void)
3568 +{
3569 +       squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
3570 +               sizeof(struct squashfs_inode_info), 0,
3571 +               SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once);
3572 +
3573 +       return squashfs_inode_cachep ? 0 : -ENOMEM;
3574 +}
3575 +
3576 +
3577 +static void destroy_inodecache(void)
3578 +{
3579 +       kmem_cache_destroy(squashfs_inode_cachep);
3580 +}
3581 +
3582 +
3583 +static int __init init_squashfs_fs(void)
3584 +{
3585 +       int err = init_inodecache();
3586 +
3587 +       if (err)
3588 +               return err;
3589 +
3590 +       err = register_filesystem(&squashfs_fs_type);
3591 +       if (err) {
3592 +               destroy_inodecache();
3593 +               return err;
3594 +       }
3595 +
3596 +       printk(KERN_INFO "squashfs: version 4.0 (2009/01/31) "
3597 +               "Phillip Lougher\n");
3598 +
3599 +       return 0;
3600 +}
3601 +
3602 +
3603 +static void __exit exit_squashfs_fs(void)
3604 +{
3605 +       unregister_filesystem(&squashfs_fs_type);
3606 +       destroy_inodecache();
3607 +}
3608 +
3609 +
3610 +static struct inode *squashfs_alloc_inode(struct super_block *sb)
3611 +{
3612 +       struct squashfs_inode_info *ei =
3613 +               kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
3614 +
3615 +       return ei ? &ei->vfs_inode : NULL;
3616 +}
3617 +
3618 +
3619 +static void squashfs_destroy_inode(struct inode *inode)
3620 +{
3621 +       kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode));
3622 +}
3623 +
3624 +
3625 +static struct file_system_type squashfs_fs_type = {
3626 +       .owner = THIS_MODULE,
3627 +       .name = "squashfs",
3628 +       .get_sb = squashfs_get_sb,
3629 +       .kill_sb = kill_block_super,
3630 +       .fs_flags = FS_REQUIRES_DEV
3631 +};
3632 +
3633 +static struct super_operations squashfs_super_ops = {
3634 +       .alloc_inode = squashfs_alloc_inode,
3635 +       .destroy_inode = squashfs_destroy_inode,
3636 +       .statfs = squashfs_statfs,
3637 +       .put_super = squashfs_put_super,
3638 +       .remount_fs = squashfs_remount
3639 +};
3640 +
3641 +module_init(init_squashfs_fs);
3642 +module_exit(exit_squashfs_fs);
3643 +MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem");
3644 +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
3645 +MODULE_LICENSE("GPL");
3646 diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
3647 new file mode 100644
3648 index 0000000..83d8788
3649 --- /dev/null
3650 +++ b/fs/squashfs/symlink.c
3651 @@ -0,0 +1,118 @@
3652 +/*
3653 + * Squashfs - a compressed read only filesystem for Linux
3654 + *
3655 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
3656 + * Phillip Lougher <phillip@lougher.demon.co.uk>
3657 + *
3658 + * This program is free software; you can redistribute it and/or
3659 + * modify it under the terms of the GNU General Public License
3660 + * as published by the Free Software Foundation; either version 2,
3661 + * or (at your option) any later version.
3662 + *
3663 + * This program is distributed in the hope that it will be useful,
3664 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3665 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3666 + * GNU General Public License for more details.
3667 + *
3668 + * You should have received a copy of the GNU General Public License
3669 + * along with this program; if not, write to the Free Software
3670 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
3671 + *
3672 + * symlink.c
3673 + */
3674 +
3675 +/*
3676 + * This file implements code to handle symbolic links.
3677 + *
3678 + * The data contents of symbolic links are stored inside the symbolic
3679 + * link inode within the inode table.  This allows the normally small symbolic
3680 + * link to be compressed as part of the inode table, achieving much greater
3681 + * compression than if the symbolic link was compressed individually.
3682 + */
3683 +
3684 +#include <linux/fs.h>
3685 +#include <linux/vfs.h>
3686 +#include <linux/kernel.h>
3687 +#include <linux/slab.h>
3688 +#include <linux/string.h>
3689 +#include <linux/pagemap.h>
3690 +#include <linux/zlib.h>
3691 +
3692 +#include "squashfs_fs.h"
3693 +#include "squashfs_fs_sb.h"
3694 +#include "squashfs_fs_i.h"
3695 +#include "squashfs.h"
3696 +
3697 +static int squashfs_symlink_readpage(struct file *file, struct page *page)
3698 +{
3699 +       struct inode *inode = page->mapping->host;
3700 +       struct super_block *sb = inode->i_sb;
3701 +       struct squashfs_sb_info *msblk = sb->s_fs_info;
3702 +       int index = page->index << PAGE_CACHE_SHIFT;
3703 +       u64 block = squashfs_i(inode)->start;
3704 +       int offset = squashfs_i(inode)->offset;
3705 +       int length = min_t(int, i_size_read(inode) - index, PAGE_CACHE_SIZE);
3706 +       int bytes, copied;
3707 +       void *pageaddr;
3708 +       struct squashfs_cache_entry *entry;
3709 +
3710 +       TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
3711 +                       "%llx, offset %x\n", page->index, block, offset);
3712 +
3713 +       /*
3714 +        * Skip index bytes into symlink metadata.
3715 +        */
3716 +       if (index) {
3717 +               bytes = squashfs_read_metadata(sb, NULL, &block, &offset,
3718 +                                                               index);
3719 +               if (bytes < 0) {
3720 +                       ERROR("Unable to read symlink [%llx:%x]\n",
3721 +                               squashfs_i(inode)->start,
3722 +                               squashfs_i(inode)->offset);
3723 +                       goto error_out;
3724 +               }
3725 +       }
3726 +
3727 +       /*
3728 +        * Read length bytes from symlink metadata.  Squashfs_read_metadata
3729 +        * is not used here because it can sleep and we want to use
3730 +        * kmap_atomic to map the page.  Instead call the underlying
3731 +        * squashfs_cache_get routine.  As length bytes may overlap metadata
3732 +        * blocks, we may need to call squashfs_cache_get multiple times.
3733 +        */
3734 +       for (bytes = 0; bytes < length; offset = 0, bytes += copied) {
3735 +               entry = squashfs_cache_get(sb, msblk->block_cache, block, 0);
3736 +               if (entry->error) {
3737 +                       ERROR("Unable to read symlink [%llx:%x]\n",
3738 +                               squashfs_i(inode)->start,
3739 +                               squashfs_i(inode)->offset);
3740 +                       squashfs_cache_put(entry);
3741 +                       goto error_out;
3742 +               }
3743 +
3744 +               pageaddr = kmap_atomic(page, KM_USER0);
3745 +               copied = squashfs_copy_data(pageaddr + bytes, entry, offset,
3746 +                                                               length - bytes);
3747 +               if (copied == length - bytes)
3748 +                       memset(pageaddr + length, 0, PAGE_CACHE_SIZE - length);
3749 +               else
3750 +                       block = entry->next_index;
3751 +               kunmap_atomic(pageaddr, KM_USER0);
3752 +               squashfs_cache_put(entry);
3753 +       }
3754 +
3755 +       flush_dcache_page(page);
3756 +       SetPageUptodate(page);
3757 +       unlock_page(page);
3758 +       return 0;
3759 +
3760 +error_out:
3761 +       SetPageError(page);
3762 +       unlock_page(page);
3763 +       return 0;
3764 +}
3765 +
3766 +
3767 +const struct address_space_operations squashfs_symlink_aops = {
3768 +       .readpage = squashfs_symlink_readpage
3769 +};
3770 diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
3771 index fedef93..7931b35 100644
3772 --- a/init/do_mounts_rd.c
3773 +++ b/init/do_mounts_rd.c
3774 @@ -9,6 +9,7 @@
3775  #include <linux/string.h>
3776  
3777  #include "do_mounts.h"
3778 +#include "../fs/squashfs/squashfs_fs.h"
3779  
3780  int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
3781  
3782 @@ -41,6 +42,7 @@ static int __init crd_load(int in_fd, int out_fd);
3783   *     ext2
3784   *     romfs
3785   *     cramfs
3786 + *     squashfs
3787   *     gzip
3788   */
3789  static int __init 
3790 @@ -51,6 +53,7 @@ identify_ramdisk_image(int fd, int start_block)
3791         struct ext2_super_block *ext2sb;
3792         struct romfs_super_block *romfsb;
3793         struct cramfs_super *cramfsb;
3794 +       struct squashfs_super_block *squashfsb;
3795         int nblocks = -1;
3796         unsigned char *buf;
3797  
3798 @@ -62,6 +65,7 @@ identify_ramdisk_image(int fd, int start_block)
3799         ext2sb = (struct ext2_super_block *) buf;
3800         romfsb = (struct romfs_super_block *) buf;
3801         cramfsb = (struct cramfs_super *) buf;
3802 +       squashfsb = (struct squashfs_super_block *) buf;
3803         memset(buf, 0xe5, size);
3804  
3805         /*
3806 @@ -99,6 +103,16 @@ identify_ramdisk_image(int fd, int start_block)
3807                 goto done;
3808         }
3809  
3810 +       /* squashfs is at block zero too */
3811 +       if (le32_to_cpu(squashfsb->s_magic) == SQUASHFS_MAGIC) {
3812 +               printk(KERN_NOTICE
3813 +                      "RAMDISK: squashfs filesystem found at block %d\n",
3814 +                      start_block);
3815 +               nblocks = (le64_to_cpu(squashfsb->bytes_used) + BLOCK_SIZE - 1)
3816 +                        >> BLOCK_SIZE_BITS;
3817 +               goto done;
3818 +       }
3819 +
3820         /*
3821          * Read block 1 to test for minix and ext2 superblock
3822          */
3823 -- 
3824 1.6.3.1
3825