summaryrefslogtreecommitdiffstats
path: root/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/squashfs3.0-2.6.15.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/squashfs3.0-2.6.15.patch')
-rw-r--r--meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/squashfs3.0-2.6.15.patch4191
1 files changed, 4191 insertions, 0 deletions
diff --git a/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/squashfs3.0-2.6.15.patch b/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/squashfs3.0-2.6.15.patch
new file mode 100644
index 0000000000..405d4ec124
--- /dev/null
+++ b/meta/packages/linux/linux-rp-2.6.19+2.6.20-rc4/squashfs3.0-2.6.15.patch
@@ -0,0 +1,4191 @@
1 fs/Kconfig | 65 +
2 fs/Makefile | 1
3 fs/squashfs/Makefile | 7
4 fs/squashfs/inode.c | 2124 +++++++++++++++++++++++++++++++++++++++++
5 fs/squashfs/squashfs.h | 86 +
6 fs/squashfs/squashfs2_0.c | 757 ++++++++++++++
7 include/linux/squashfs_fs.h | 911 +++++++++++++++++
8 include/linux/squashfs_fs_i.h | 45
9 include/linux/squashfs_fs_sb.h | 74 +
10 init/do_mounts_rd.c | 13
11 10 files changed, 4083 insertions(+)
12
13Index: git/fs/Kconfig
14===================================================================
15--- git.orig/fs/Kconfig 2006-10-31 16:09:22.000000000 +0000
16+++ git/fs/Kconfig 2006-10-31 21:26:45.000000000 +0000
17@@ -1407,6 +1407,71 @@ config CRAMFS
18
19 If unsure, say N.
20
21+config SQUASHFS
22+ tristate "SquashFS 3.0 - Squashed file system support"
23+ select ZLIB_INFLATE
24+ help
25+ Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File
26+ System). Squashfs is a highly compressed read-only filesystem for Linux.
27+ It uses zlib compression to compress both files, inodes and directories.
28+ Inodes in the system are very small and all blocks are packed to minimise
29+ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
30+ SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full
31+ uid/gid information, hard links and timestamps.
32+
33+ Squashfs is intended for general read-only filesystem use, for archival
34+ use (i.e. in cases where a .tar.gz file may be used), and in embedded
35+ systems where low overhead is needed. Further information and filesystem tools
36+ are available from http://squashfs.sourceforge.net.
37+
38+ If you want to compile this as a module ( = code which can be
39+ inserted in and removed from the running kernel whenever you want),
40+ say M here and read <file:Documentation/modules.txt>. The module
41+ will be called squashfs. Note that the root file system (the one
42+ containing the directory /) cannot be compiled as a module.
43+
44+ If unsure, say N.
45+
46+config SQUASHFS_EMBEDDED
47+
48+ bool "Additional options for memory-constrained systems"
49+ depends on SQUASHFS
50+ default n
51+ help
52+ Saying Y here allows you to specify cache sizes and how Squashfs
53+ allocates memory. This is only intended for memory constrained
54+ systems.
55+
56+ If unsure, say N.
57+
58+config SQUASHFS_FRAGMENT_CACHE_SIZE
59+ int "Number of fragments cached" if SQUASHFS_EMBEDDED
60+ depends on SQUASHFS
61+ default "3"
62+ help
63+ By default SquashFS caches the last 3 fragments read from
64+ the filesystem. Increasing this amount may mean SquashFS
65+ has to re-read fragments less often from disk, at the expense
66+ of extra system memory. Decreasing this amount will mean
67+ SquashFS uses less memory at the expense of extra reads from disk.
68+
69+ Note there must be at least one cached fragment. Anything
70+ much more than three will probably not make much difference.
71+
72+config SQUASHFS_VMALLOC
73+ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
74+ depends on SQUASHFS
75+ default n
76+ help
77+ By default SquashFS uses kmalloc to obtain fragment cache memory.
78+ Kmalloc memory is the standard kernel allocator, but it can fail
79+ on memory constrained systems. Because of the way Vmalloc works,
80+ Vmalloc can succeed when kmalloc fails. Specifying this option
81+ will make SquashFS always use Vmalloc to allocate the
82+ fragment cache memory.
83+
84+ If unsure, say N.
85+
86 config VXFS_FS
87 tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
88 depends on BLOCK
89Index: git/fs/Makefile
90===================================================================
91--- git.orig/fs/Makefile 2006-10-31 16:09:22.000000000 +0000
92+++ git/fs/Makefile 2006-10-31 21:26:45.000000000 +0000
93@@ -67,6 +67,7 @@ obj-$(CONFIG_JBD) += jbd/
94 obj-$(CONFIG_JBD2) += jbd2/
95 obj-$(CONFIG_EXT2_FS) += ext2/
96 obj-$(CONFIG_CRAMFS) += cramfs/
97+obj-$(CONFIG_SQUASHFS) += squashfs/
98 obj-$(CONFIG_RAMFS) += ramfs/
99 obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
100 obj-$(CONFIG_CODA_FS) += coda/
101Index: git/fs/squashfs/inode.c
102===================================================================
103--- /dev/null 1970-01-01 00:00:00.000000000 +0000
104+++ git/fs/squashfs/inode.c 2006-11-01 18:01:32.000000000 +0000
105@@ -0,0 +1,2124 @@
106+/*
107+ * Squashfs - a compressed read only filesystem for Linux
108+ *
109+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
110+ * Phillip Lougher <phillip@lougher.org.uk>
111+ *
112+ * This program is free software; you can redistribute it and/or
113+ * modify it under the terms of the GNU General Public License
114+ * as published by the Free Software Foundation; either version 2,
115+ * or (at your option) any later version.
116+ *
117+ * This program is distributed in the hope that it will be useful,
118+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
119+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120+ * GNU General Public License for more details.
121+ *
122+ * You should have received a copy of the GNU General Public License
123+ * along with this program; if not, write to the Free Software
124+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
125+ *
126+ * inode.c
127+ */
128+
129+#include <linux/types.h>
130+#include <linux/squashfs_fs.h>
131+#include <linux/module.h>
132+#include <linux/errno.h>
133+#include <linux/slab.h>
134+#include <linux/fs.h>
135+#include <linux/smp_lock.h>
136+#include <linux/slab.h>
137+#include <linux/squashfs_fs_sb.h>
138+#include <linux/squashfs_fs_i.h>
139+#include <linux/buffer_head.h>
140+#include <linux/vfs.h>
141+#include <linux/init.h>
142+#include <linux/dcache.h>
143+#include <linux/wait.h>
144+#include <linux/zlib.h>
145+#include <linux/blkdev.h>
146+#include <linux/vmalloc.h>
147+#include <asm/uaccess.h>
148+#include <asm/semaphore.h>
149+
150+#include "squashfs.h"
151+
152+static void squashfs_put_super(struct super_block *);
153+static int squashfs_statfs(struct dentry *, struct kstatfs *);
154+static int squashfs_symlink_readpage(struct file *file, struct page *page);
155+static int squashfs_readpage(struct file *file, struct page *page);
156+static int squashfs_readpage4K(struct file *file, struct page *page);
157+static int squashfs_readdir(struct file *, void *, filldir_t);
158+static struct inode *squashfs_alloc_inode(struct super_block *sb);
159+static void squashfs_destroy_inode(struct inode *inode);
160+static int init_inodecache(void);
161+static void destroy_inodecache(void);
162+static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
163+ struct nameidata *);
164+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
165+static long long read_blocklist(struct inode *inode, int index,
166+ int readahead_blks, char *block_list,
167+ unsigned short **block_p, unsigned int *bsize);
168+static int squashfs_get_sb(struct file_system_type *, int,
169+ const char *, void *, struct vfsmount *);
170+
171+
172+static z_stream stream;
173+
174+static struct file_system_type squashfs_fs_type = {
175+ .owner = THIS_MODULE,
176+ .name = "squashfs",
177+ .get_sb = squashfs_get_sb,
178+ .kill_sb = kill_block_super,
179+ .fs_flags = FS_REQUIRES_DEV
180+};
181+
182+static unsigned char squashfs_filetype_table[] = {
183+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
184+};
185+
186+static struct super_operations squashfs_ops = {
187+ .alloc_inode = squashfs_alloc_inode,
188+ .destroy_inode = squashfs_destroy_inode,
189+ .statfs = squashfs_statfs,
190+ .put_super = squashfs_put_super,
191+};
192+
193+SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
194+ .readpage = squashfs_symlink_readpage
195+};
196+
197+SQSH_EXTERN struct address_space_operations squashfs_aops = {
198+ .readpage = squashfs_readpage
199+};
200+
201+SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
202+ .readpage = squashfs_readpage4K
203+};
204+
205+static struct file_operations squashfs_dir_ops = {
206+ .read = generic_read_dir,
207+ .readdir = squashfs_readdir
208+};
209+
210+SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
211+ .lookup = squashfs_lookup
212+};
213+
214+
215+static struct buffer_head *get_block_length(struct super_block *s,
216+ int *cur_index, int *offset, int *c_byte)
217+{
218+ struct squashfs_sb_info *msblk = s->s_fs_info;
219+ unsigned short temp;
220+ struct buffer_head *bh;
221+
222+ if (!(bh = sb_bread(s, *cur_index)))
223+ goto out;
224+
225+ if (msblk->devblksize - *offset == 1) {
226+ if (msblk->swap)
227+ ((unsigned char *) &temp)[1] = *((unsigned char *)
228+ (bh->b_data + *offset));
229+ else
230+ ((unsigned char *) &temp)[0] = *((unsigned char *)
231+ (bh->b_data + *offset));
232+ brelse(bh);
233+ if (!(bh = sb_bread(s, ++(*cur_index))))
234+ goto out;
235+ if (msblk->swap)
236+ ((unsigned char *) &temp)[0] = *((unsigned char *)
237+ bh->b_data);
238+ else
239+ ((unsigned char *) &temp)[1] = *((unsigned char *)
240+ bh->b_data);
241+ *c_byte = temp;
242+ *offset = 1;
243+ } else {
244+ if (msblk->swap) {
245+ ((unsigned char *) &temp)[1] = *((unsigned char *)
246+ (bh->b_data + *offset));
247+ ((unsigned char *) &temp)[0] = *((unsigned char *)
248+ (bh->b_data + *offset + 1));
249+ } else {
250+ ((unsigned char *) &temp)[0] = *((unsigned char *)
251+ (bh->b_data + *offset));
252+ ((unsigned char *) &temp)[1] = *((unsigned char *)
253+ (bh->b_data + *offset + 1));
254+ }
255+ *c_byte = temp;
256+ *offset += 2;
257+ }
258+
259+ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
260+ if (*offset == msblk->devblksize) {
261+ brelse(bh);
262+ if (!(bh = sb_bread(s, ++(*cur_index))))
263+ goto out;
264+ *offset = 0;
265+ }
266+ if (*((unsigned char *) (bh->b_data + *offset)) !=
267+ SQUASHFS_MARKER_BYTE) {
268+ ERROR("Metadata block marker corrupt @ %x\n",
269+ *cur_index);
270+ brelse(bh);
271+ goto out;
272+ }
273+ (*offset)++;
274+ }
275+ return bh;
276+
277+out:
278+ return NULL;
279+}
280+
281+
282+SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
283+ long long index, unsigned int length,
284+ long long *next_index)
285+{
286+ struct squashfs_sb_info *msblk = s->s_fs_info;
287+ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
288+ msblk->devblksize_log2) + 2];
289+ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
290+ unsigned int cur_index = index >> msblk->devblksize_log2;
291+ int bytes, avail_bytes, b = 0, k;
292+ char *c_buffer;
293+ unsigned int compressed;
294+ unsigned int c_byte = length;
295+
296+ if (c_byte) {
297+ bytes = msblk->devblksize - offset;
298+ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
299+ c_buffer = compressed ? msblk->read_data : buffer;
300+ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
301+
302+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
303+ ? "" : "un", (unsigned int) c_byte);
304+
305+ if (!(bh[0] = sb_getblk(s, cur_index)))
306+ goto block_release;
307+
308+ for (b = 1; bytes < c_byte; b++) {
309+ if (!(bh[b] = sb_getblk(s, ++cur_index)))
310+ goto block_release;
311+ bytes += msblk->devblksize;
312+ }
313+ ll_rw_block(READ, b, bh);
314+ } else {
315+ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
316+ &c_byte)))
317+ goto read_failure;
318+
319+ bytes = msblk->devblksize - offset;
320+ compressed = SQUASHFS_COMPRESSED(c_byte);
321+ c_buffer = compressed ? msblk->read_data : buffer;
322+ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
323+
324+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
325+ ? "" : "un", (unsigned int) c_byte);
326+
327+ for (b = 1; bytes < c_byte; b++) {
328+ if (!(bh[b] = sb_getblk(s, ++cur_index)))
329+ goto block_release;
330+ bytes += msblk->devblksize;
331+ }
332+ ll_rw_block(READ, b - 1, bh + 1);
333+ }
334+
335+ if (compressed)
336+ down(&msblk->read_data_mutex);
337+
338+ for (bytes = 0, k = 0; k < b; k++) {
339+ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
340+ msblk->devblksize - offset :
341+ c_byte - bytes;
342+ wait_on_buffer(bh[k]);
343+ if (!buffer_uptodate(bh[k]))
344+ goto block_release;
345+ memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
346+ bytes += avail_bytes;
347+ offset = 0;
348+ brelse(bh[k]);
349+ }
350+
351+ /*
352+ * uncompress block
353+ */
354+ if (compressed) {
355+ int zlib_err;
356+
357+ stream.next_in = c_buffer;
358+ stream.avail_in = c_byte;
359+ stream.next_out = buffer;
360+ stream.avail_out = msblk->read_size;
361+
362+ if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
363+ ((zlib_err = zlib_inflate(&stream, Z_FINISH))
364+ != Z_STREAM_END) || ((zlib_err =
365+ zlib_inflateEnd(&stream)) != Z_OK)) {
366+ ERROR("zlib_fs returned unexpected result 0x%x\n",
367+ zlib_err);
368+ bytes = 0;
369+ } else
370+ bytes = stream.total_out;
371+
372+ up(&msblk->read_data_mutex);
373+ }
374+
375+ if (next_index)
376+ *next_index = index + c_byte + (length ? 0 :
377+ (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
378+ ? 3 : 2));
379+ return bytes;
380+
381+block_release:
382+ while (--b >= 0)
383+ brelse(bh[b]);
384+
385+read_failure:
386+ ERROR("sb_bread failed reading block 0x%x\n", cur_index);
387+ return 0;
388+}
389+
390+
391+SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
392+ long long block, unsigned int offset,
393+ int length, long long *next_block,
394+ unsigned int *next_offset)
395+{
396+ struct squashfs_sb_info *msblk = s->s_fs_info;
397+ int n, i, bytes, return_length = length;
398+ long long next_index;
399+
400+ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
401+
402+ while ( 1 ) {
403+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
404+ if (msblk->block_cache[i].block == block)
405+ break;
406+
407+ down(&msblk->block_cache_mutex);
408+
409+ if (i == SQUASHFS_CACHED_BLKS) {
410+ /* read inode header block */
411+ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
412+ n ; n --, i = (i + 1) %
413+ SQUASHFS_CACHED_BLKS)
414+ if (msblk->block_cache[i].block !=
415+ SQUASHFS_USED_BLK)
416+ break;
417+
418+ if (n == 0) {
419+ wait_queue_t wait;
420+
421+ init_waitqueue_entry(&wait, current);
422+ add_wait_queue(&msblk->waitq, &wait);
423+ set_current_state(TASK_UNINTERRUPTIBLE);
424+ up(&msblk->block_cache_mutex);
425+ schedule();
426+ set_current_state(TASK_RUNNING);
427+ remove_wait_queue(&msblk->waitq, &wait);
428+ continue;
429+ }
430+ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
431+
432+ if (msblk->block_cache[i].block ==
433+ SQUASHFS_INVALID_BLK) {
434+ if (!(msblk->block_cache[i].data =
435+ kmalloc(SQUASHFS_METADATA_SIZE,
436+ GFP_KERNEL))) {
437+ ERROR("Failed to allocate cache"
438+ "block\n");
439+ up(&msblk->block_cache_mutex);
440+ goto out;
441+ }
442+ }
443+
444+ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
445+ up(&msblk->block_cache_mutex);
446+
447+ if (!(msblk->block_cache[i].length =
448+ squashfs_read_data(s,
449+ msblk->block_cache[i].data,
450+ block, 0, &next_index))) {
451+ ERROR("Unable to read cache block [%llx:%x]\n",
452+ block, offset);
453+ goto out;
454+ }
455+
456+ down(&msblk->block_cache_mutex);
457+ wake_up(&msblk->waitq);
458+ msblk->block_cache[i].block = block;
459+ msblk->block_cache[i].next_index = next_index;
460+ TRACE("Read cache block [%llx:%x]\n", block, offset);
461+ }
462+
463+ if (msblk->block_cache[i].block != block) {
464+ up(&msblk->block_cache_mutex);
465+ continue;
466+ }
467+
468+ if ((bytes = msblk->block_cache[i].length - offset) >= length) {
469+ if (buffer)
470+ memcpy(buffer, msblk->block_cache[i].data +
471+ offset, length);
472+ if (msblk->block_cache[i].length - offset == length) {
473+ *next_block = msblk->block_cache[i].next_index;
474+ *next_offset = 0;
475+ } else {
476+ *next_block = block;
477+ *next_offset = offset + length;
478+ }
479+ up(&msblk->block_cache_mutex);
480+ goto finish;
481+ } else {
482+ if (buffer) {
483+ memcpy(buffer, msblk->block_cache[i].data +
484+ offset, bytes);
485+ buffer += bytes;
486+ }
487+ block = msblk->block_cache[i].next_index;
488+ up(&msblk->block_cache_mutex);
489+ length -= bytes;
490+ offset = 0;
491+ }
492+ }
493+
494+finish:
495+ return return_length;
496+out:
497+ return 0;
498+}
499+
500+
501+static int get_fragment_location(struct super_block *s, unsigned int fragment,
502+ long long *fragment_start_block,
503+ unsigned int *fragment_size)
504+{
505+ struct squashfs_sb_info *msblk = s->s_fs_info;
506+ long long start_block =
507+ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
508+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
509+ struct squashfs_fragment_entry fragment_entry;
510+
511+ if (msblk->swap) {
512+ struct squashfs_fragment_entry sfragment_entry;
513+
514+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
515+ start_block, offset,
516+ sizeof(sfragment_entry), &start_block,
517+ &offset))
518+ goto out;
519+ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
520+ } else
521+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
522+ start_block, offset,
523+ sizeof(fragment_entry), &start_block,
524+ &offset))
525+ goto out;
526+
527+ *fragment_start_block = fragment_entry.start_block;
528+ *fragment_size = fragment_entry.size;
529+
530+ return 1;
531+
532+out:
533+ return 0;
534+}
535+
536+
537+SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
538+ squashfs_fragment_cache *fragment)
539+{
540+ down(&msblk->fragment_mutex);
541+ fragment->locked --;
542+ wake_up(&msblk->fragment_wait_queue);
543+ up(&msblk->fragment_mutex);
544+}
545+
546+
547+SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
548+ *s, long long start_block,
549+ int length)
550+{
551+ int i, n, nf;
552+ struct squashfs_sb_info *msblk = s->s_fs_info;
553+
554+ while ( 1 ) {
555+ down(&msblk->fragment_mutex);
556+
557+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
558+ msblk->fragment[i].block != start_block; i++);
559+
560+ if (i == SQUASHFS_CACHED_FRAGMENTS) {
561+ nf = (msblk->next_fragment + 1) %
562+ SQUASHFS_CACHED_FRAGMENTS;
563+ for (i = msblk->next_fragment, n =
564+ SQUASHFS_CACHED_FRAGMENTS; n &&
565+ msblk->fragment[i].locked; n--, i = (i + 1) %
566+ SQUASHFS_CACHED_FRAGMENTS);
567+
568+ if (n == 0) {
569+ wait_queue_t wait;
570+
571+ init_waitqueue_entry(&wait, current);
572+ add_wait_queue(&msblk->fragment_wait_queue,
573+ &wait);
574+ set_current_state(TASK_UNINTERRUPTIBLE);
575+ up(&msblk->fragment_mutex);
576+ schedule();
577+ set_current_state(TASK_RUNNING);
578+ remove_wait_queue(&msblk->fragment_wait_queue,
579+ &wait);
580+ continue;
581+ }
582+ msblk->next_fragment = nf;
583+
584+ if (msblk->fragment[i].data == NULL)
585+ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
586+ (SQUASHFS_FILE_MAX_SIZE))) {
587+ ERROR("Failed to allocate fragment "
588+ "cache block\n");
589+ up(&msblk->fragment_mutex);
590+ goto out;
591+ }
592+
593+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
594+ msblk->fragment[i].locked = 1;
595+ up(&msblk->fragment_mutex);
596+
597+ if (!(msblk->fragment[i].length = squashfs_read_data(s,
598+ msblk->fragment[i].data,
599+ start_block, length, NULL))) {
600+ ERROR("Unable to read fragment cache block "
601+ "[%llx]\n", start_block);
602+ msblk->fragment[i].locked = 0;
603+ goto out;
604+ }
605+
606+ msblk->fragment[i].block = start_block;
607+ TRACE("New fragment %d, start block %lld, locked %d\n",
608+ i, msblk->fragment[i].block,
609+ msblk->fragment[i].locked);
610+ break;
611+ }
612+
613+ msblk->fragment[i].locked++;
614+ up(&msblk->fragment_mutex);
615+ TRACE("Got fragment %d, start block %lld, locked %d\n", i,
616+ msblk->fragment[i].block,
617+ msblk->fragment[i].locked);
618+ break;
619+ }
620+
621+ return &msblk->fragment[i];
622+
623+out:
624+ return NULL;
625+}
626+
627+
628+static struct inode *squashfs_new_inode(struct super_block *s,
629+ struct squashfs_base_inode_header *inodeb)
630+{
631+ struct squashfs_sb_info *msblk = s->s_fs_info;
632+ struct inode *i = new_inode(s);
633+
634+ if (i) {
635+ i->i_ino = inodeb->inode_number;
636+ i->i_mtime.tv_sec = inodeb->mtime;
637+ i->i_atime.tv_sec = inodeb->mtime;
638+ i->i_ctime.tv_sec = inodeb->mtime;
639+ i->i_uid = msblk->uid[inodeb->uid];
640+ i->i_mode = inodeb->mode;
641+ i->i_size = 0;
642+ if (inodeb->guid == SQUASHFS_GUIDS)
643+ i->i_gid = i->i_uid;
644+ else
645+ i->i_gid = msblk->guid[inodeb->guid];
646+ }
647+
648+ return i;
649+}
650+
651+
652+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
653+{
654+ struct inode *i;
655+ struct squashfs_sb_info *msblk = s->s_fs_info;
656+ struct squashfs_super_block *sblk = &msblk->sblk;
657+ long long block = SQUASHFS_INODE_BLK(inode) +
658+ sblk->inode_table_start;
659+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
660+ long long next_block;
661+ unsigned int next_offset;
662+ union squashfs_inode_header id, sid;
663+ struct squashfs_base_inode_header *inodeb = &id.base,
664+ *sinodeb = &sid.base;
665+
666+ TRACE("Entered squashfs_iget\n");
667+
668+ if (msblk->swap) {
669+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
670+ offset, sizeof(*sinodeb), &next_block,
671+ &next_offset))
672+ goto failed_read;
673+ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
674+ sizeof(*sinodeb));
675+ } else
676+ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
677+ offset, sizeof(*inodeb), &next_block,
678+ &next_offset))
679+ goto failed_read;
680+
681+ switch(inodeb->inode_type) {
682+ case SQUASHFS_FILE_TYPE: {
683+ unsigned int frag_size;
684+ long long frag_blk;
685+ struct squashfs_reg_inode_header *inodep = &id.reg;
686+ struct squashfs_reg_inode_header *sinodep = &sid.reg;
687+
688+ if (msblk->swap) {
689+ if (!squashfs_get_cached_block(s, (char *)
690+ sinodep, block, offset,
691+ sizeof(*sinodep), &next_block,
692+ &next_offset))
693+ goto failed_read;
694+ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
695+ } else
696+ if (!squashfs_get_cached_block(s, (char *)
697+ inodep, block, offset,
698+ sizeof(*inodep), &next_block,
699+ &next_offset))
700+ goto failed_read;
701+
702+ frag_blk = SQUASHFS_INVALID_BLK;
703+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
704+ !get_fragment_location(s,
705+ inodep->fragment, &frag_blk, &frag_size))
706+ goto failed_read;
707+
708+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
709+ goto failed_read1;
710+
711+ i->i_nlink = 1;
712+ i->i_size = inodep->file_size;
713+ i->i_fop = &generic_ro_fops;
714+ i->i_mode |= S_IFREG;
715+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
716+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
717+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
718+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
719+ SQUASHFS_I(i)->start_block = inodep->start_block;
720+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
721+ SQUASHFS_I(i)->offset = next_offset;
722+ if (sblk->block_size > 4096)
723+ i->i_data.a_ops = &squashfs_aops;
724+ else
725+ i->i_data.a_ops = &squashfs_aops_4K;
726+
727+ TRACE("File inode %x:%x, start_block %llx, "
728+ "block_list_start %llx, offset %x\n",
729+ SQUASHFS_INODE_BLK(inode), offset,
730+ inodep->start_block, next_block,
731+ next_offset);
732+ break;
733+ }
734+ case SQUASHFS_LREG_TYPE: {
735+ unsigned int frag_size;
736+ long long frag_blk;
737+ struct squashfs_lreg_inode_header *inodep = &id.lreg;
738+ struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
739+
740+ if (msblk->swap) {
741+ if (!squashfs_get_cached_block(s, (char *)
742+ sinodep, block, offset,
743+ sizeof(*sinodep), &next_block,
744+ &next_offset))
745+ goto failed_read;
746+ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
747+ } else
748+ if (!squashfs_get_cached_block(s, (char *)
749+ inodep, block, offset,
750+ sizeof(*inodep), &next_block,
751+ &next_offset))
752+ goto failed_read;
753+
754+ frag_blk = SQUASHFS_INVALID_BLK;
755+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
756+ !get_fragment_location(s,
757+ inodep->fragment, &frag_blk, &frag_size))
758+ goto failed_read;
759+
760+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
761+ goto failed_read1;
762+
763+ i->i_nlink = inodep->nlink;
764+ i->i_size = inodep->file_size;
765+ i->i_fop = &generic_ro_fops;
766+ i->i_mode |= S_IFREG;
767+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
768+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
769+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
770+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
771+ SQUASHFS_I(i)->start_block = inodep->start_block;
772+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
773+ SQUASHFS_I(i)->offset = next_offset;
774+ if (sblk->block_size > 4096)
775+ i->i_data.a_ops = &squashfs_aops;
776+ else
777+ i->i_data.a_ops = &squashfs_aops_4K;
778+
779+ TRACE("File inode %x:%x, start_block %llx, "
780+ "block_list_start %llx, offset %x\n",
781+ SQUASHFS_INODE_BLK(inode), offset,
782+ inodep->start_block, next_block,
783+ next_offset);
784+ break;
785+ }
786+ case SQUASHFS_DIR_TYPE: {
787+ struct squashfs_dir_inode_header *inodep = &id.dir;
788+ struct squashfs_dir_inode_header *sinodep = &sid.dir;
789+
790+ if (msblk->swap) {
791+ if (!squashfs_get_cached_block(s, (char *)
792+ sinodep, block, offset,
793+ sizeof(*sinodep), &next_block,
794+ &next_offset))
795+ goto failed_read;
796+ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
797+ } else
798+ if (!squashfs_get_cached_block(s, (char *)
799+ inodep, block, offset,
800+ sizeof(*inodep), &next_block,
801+ &next_offset))
802+ goto failed_read;
803+
804+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
805+ goto failed_read1;
806+
807+ i->i_nlink = inodep->nlink;
808+ i->i_size = inodep->file_size;
809+ i->i_op = &squashfs_dir_inode_ops;
810+ i->i_fop = &squashfs_dir_ops;
811+ i->i_mode |= S_IFDIR;
812+ SQUASHFS_I(i)->start_block = inodep->start_block;
813+ SQUASHFS_I(i)->offset = inodep->offset;
814+ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
815+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
816+
817+ TRACE("Directory inode %x:%x, start_block %x, offset "
818+ "%x\n", SQUASHFS_INODE_BLK(inode),
819+ offset, inodep->start_block,
820+ inodep->offset);
821+ break;
822+ }
823+ case SQUASHFS_LDIR_TYPE: {
824+ struct squashfs_ldir_inode_header *inodep = &id.ldir;
825+ struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
826+
827+ if (msblk->swap) {
828+ if (!squashfs_get_cached_block(s, (char *)
829+ sinodep, block, offset,
830+ sizeof(*sinodep), &next_block,
831+ &next_offset))
832+ goto failed_read;
833+ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
834+ sinodep);
835+ } else
836+ if (!squashfs_get_cached_block(s, (char *)
837+ inodep, block, offset,
838+ sizeof(*inodep), &next_block,
839+ &next_offset))
840+ goto failed_read;
841+
842+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
843+ goto failed_read1;
844+
845+ i->i_nlink = inodep->nlink;
846+ i->i_size = inodep->file_size;
847+ i->i_op = &squashfs_dir_inode_ops;
848+ i->i_fop = &squashfs_dir_ops;
849+ i->i_mode |= S_IFDIR;
850+ SQUASHFS_I(i)->start_block = inodep->start_block;
851+ SQUASHFS_I(i)->offset = inodep->offset;
852+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
853+ SQUASHFS_I(i)->u.s2.directory_index_offset =
854+ next_offset;
855+ SQUASHFS_I(i)->u.s2.directory_index_count =
856+ inodep->i_count;
857+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
858+
859+ TRACE("Long directory inode %x:%x, start_block %x, "
860+ "offset %x\n",
861+ SQUASHFS_INODE_BLK(inode), offset,
862+ inodep->start_block, inodep->offset);
863+ break;
864+ }
865+ case SQUASHFS_SYMLINK_TYPE: {
866+ struct squashfs_symlink_inode_header *inodep =
867+ &id.symlink;
868+ struct squashfs_symlink_inode_header *sinodep =
869+ &sid.symlink;
870+
871+ if (msblk->swap) {
872+ if (!squashfs_get_cached_block(s, (char *)
873+ sinodep, block, offset,
874+ sizeof(*sinodep), &next_block,
875+ &next_offset))
876+ goto failed_read;
877+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
878+ sinodep);
879+ } else
880+ if (!squashfs_get_cached_block(s, (char *)
881+ inodep, block, offset,
882+ sizeof(*inodep), &next_block,
883+ &next_offset))
884+ goto failed_read;
885+
886+ if((i = squashfs_new_inode(s, inodeb)) == NULL)
887+ goto failed_read1;
888+
889+ i->i_nlink = inodep->nlink;
890+ i->i_size = inodep->symlink_size;
891+ i->i_op = &page_symlink_inode_operations;
892+ i->i_data.a_ops = &squashfs_symlink_aops;
893+ i->i_mode |= S_IFLNK;
894+ SQUASHFS_I(i)->start_block = next_block;
895+ SQUASHFS_I(i)->offset = next_offset;
896+
897+ TRACE("Symbolic link inode %x:%x, start_block %llx, "
898+ "offset %x\n",
899+ SQUASHFS_INODE_BLK(inode), offset,
900+ next_block, next_offset);
901+ break;
902+ }
903+ case SQUASHFS_BLKDEV_TYPE:
904+ case SQUASHFS_CHRDEV_TYPE: {
905+ struct squashfs_dev_inode_header *inodep = &id.dev;
906+ struct squashfs_dev_inode_header *sinodep = &sid.dev;
907+
908+ if (msblk->swap) {
909+ if (!squashfs_get_cached_block(s, (char *)
910+ sinodep, block, offset,
911+ sizeof(*sinodep), &next_block,
912+ &next_offset))
913+ goto failed_read;
914+ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
915+ } else
916+ if (!squashfs_get_cached_block(s, (char *)
917+ inodep, block, offset,
918+ sizeof(*inodep), &next_block,
919+ &next_offset))
920+ goto failed_read;
921+
922+ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
923+ goto failed_read1;
924+
925+ i->i_nlink = inodep->nlink;
926+ i->i_mode |= (inodeb->inode_type ==
927+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
928+ S_IFBLK;
929+ init_special_inode(i, i->i_mode,
930+ old_decode_dev(inodep->rdev));
931+
932+ TRACE("Device inode %x:%x, rdev %x\n",
933+ SQUASHFS_INODE_BLK(inode), offset,
934+ inodep->rdev);
935+ break;
936+ }
937+ case SQUASHFS_FIFO_TYPE:
938+ case SQUASHFS_SOCKET_TYPE: {
939+ struct squashfs_ipc_inode_header *inodep = &id.ipc;
940+ struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
941+
942+ if (msblk->swap) {
943+ if (!squashfs_get_cached_block(s, (char *)
944+ sinodep, block, offset,
945+ sizeof(*sinodep), &next_block,
946+ &next_offset))
947+ goto failed_read;
948+ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
949+ } else
950+ if (!squashfs_get_cached_block(s, (char *)
951+ inodep, block, offset,
952+ sizeof(*inodep), &next_block,
953+ &next_offset))
954+ goto failed_read;
955+
956+ if ((i = squashfs_new_inode(s, inodeb)) == NULL)
957+ goto failed_read1;
958+
959+ i->i_nlink = inodep->nlink;
960+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
961+ ? S_IFIFO : S_IFSOCK;
962+ init_special_inode(i, i->i_mode, 0);
963+ break;
964+ }
965+ default:
966+ ERROR("Unknown inode type %d in squashfs_iget!\n",
967+ inodeb->inode_type);
968+ goto failed_read1;
969+ }
970+
971+ insert_inode_hash(i);
972+ return i;
973+
974+failed_read:
975+ ERROR("Unable to read inode [%llx:%x]\n", block, offset);
976+
977+failed_read1:
978+ return NULL;
979+}
980+
981+
982+static int read_fragment_index_table(struct super_block *s)
983+{
984+ struct squashfs_sb_info *msblk = s->s_fs_info;
985+ struct squashfs_super_block *sblk = &msblk->sblk;
986+
987+ /* Allocate fragment index table */
988+ if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
989+ (sblk->fragments), GFP_KERNEL))) {
990+ ERROR("Failed to allocate uid/gid table\n");
991+ return 0;
992+ }
993+
994+ if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
995+ !squashfs_read_data(s, (char *)
996+ msblk->fragment_index,
997+ sblk->fragment_table_start,
998+ SQUASHFS_FRAGMENT_INDEX_BYTES
999+ (sblk->fragments) |
1000+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1001+ ERROR("unable to read fragment index table\n");
1002+ return 0;
1003+ }
1004+
1005+ if (msblk->swap) {
1006+ int i;
1007+ long long fragment;
1008+
1009+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
1010+ i++) {
1011+ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
1012+ &msblk->fragment_index[i], 1);
1013+ msblk->fragment_index[i] = fragment;
1014+ }
1015+ }
1016+
1017+ return 1;
1018+}
1019+
1020+
1021+static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
1022+{
1023+ struct squashfs_super_block *sblk = &msblk->sblk;
1024+
1025+ msblk->iget = squashfs_iget;
1026+ msblk->read_blocklist = read_blocklist;
1027+ msblk->read_fragment_index_table = read_fragment_index_table;
1028+
1029+ if (sblk->s_major == 1) {
1030+ if (!squashfs_1_0_supported(msblk)) {
1031+ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
1032+ "are unsupported\n");
1033+ SERROR("Please recompile with "
1034+ "Squashfs 1.0 support enabled\n");
1035+ return 0;
1036+ }
1037+ } else if (sblk->s_major == 2) {
1038+ if (!squashfs_2_0_supported(msblk)) {
1039+ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
1040+ "are unsupported\n");
1041+ SERROR("Please recompile with "
1042+ "Squashfs 2.0 support enabled\n");
1043+ return 0;
1044+ }
1045+ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
1046+ SQUASHFS_MINOR) {
1047+ SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
1048+ "filesystem\n", sblk->s_major, sblk->s_minor);
1049+ SERROR("Please update your kernel\n");
1050+ return 0;
1051+ }
1052+
1053+ return 1;
1054+}
1055+
1056+
1057+static int squashfs_fill_super(struct super_block *s, void *data, int silent)
1058+{
1059+ struct squashfs_sb_info *msblk;
1060+ struct squashfs_super_block *sblk;
1061+ int i;
1062+ char b[BDEVNAME_SIZE];
1063+ struct inode *root;
1064+
1065+ TRACE("Entered squashfs_read_superblock\n");
1066+
1067+ if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
1068+ GFP_KERNEL))) {
1069+ ERROR("Failed to allocate superblock\n");
1070+ goto failure;
1071+ }
1072+ memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
1073+ msblk = s->s_fs_info;
1074+ sblk = &msblk->sblk;
1075+
1076+ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
1077+ msblk->devblksize_log2 = ffz(~msblk->devblksize);
1078+
1079+ init_MUTEX(&msblk->read_data_mutex);
1080+ init_MUTEX(&msblk->read_page_mutex);
1081+ init_MUTEX(&msblk->block_cache_mutex);
1082+ init_MUTEX(&msblk->fragment_mutex);
1083+ init_MUTEX(&msblk->meta_index_mutex);
1084+
1085+ init_waitqueue_head(&msblk->waitq);
1086+ init_waitqueue_head(&msblk->fragment_wait_queue);
1087+
1088+ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
1089+ sizeof(struct squashfs_super_block) |
1090+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1091+ SERROR("unable to read superblock\n");
1092+ goto failed_mount;
1093+ }
1094+
1095+ /* Check it is a SQUASHFS superblock */
1096+ msblk->swap = 0;
1097+ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
1098+ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
1099+ struct squashfs_super_block ssblk;
1100+
1101+ WARNING("Mounting a different endian SQUASHFS "
1102+ "filesystem on %s\n", bdevname(s->s_bdev, b));
1103+
1104+ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
1105+ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
1106+ msblk->swap = 1;
1107+ } else {
1108+ SERROR("Can't find a SQUASHFS superblock on %s\n",
1109+ bdevname(s->s_bdev, b));
1110+ goto failed_mount;
1111+ }
1112+ }
1113+
1114+ /* Check the MAJOR & MINOR versions */
1115+ if(!supported_squashfs_filesystem(msblk, silent))
1116+ goto failed_mount;
1117+
1118+ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
1119+ TRACE("Inodes are %scompressed\n",
1120+ SQUASHFS_UNCOMPRESSED_INODES
1121+ (sblk->flags) ? "un" : "");
1122+ TRACE("Data is %scompressed\n",
1123+ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
1124+ ? "un" : "");
1125+ TRACE("Check data is %s present in the filesystem\n",
1126+ SQUASHFS_CHECK_DATA(sblk->flags) ?
1127+ "" : "not");
1128+ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
1129+ TRACE("Block size %d\n", sblk->block_size);
1130+ TRACE("Number of inodes %d\n", sblk->inodes);
1131+ if (sblk->s_major > 1)
1132+ TRACE("Number of fragments %d\n", sblk->fragments);
1133+ TRACE("Number of uids %d\n", sblk->no_uids);
1134+ TRACE("Number of gids %d\n", sblk->no_guids);
1135+ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
1136+ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
1137+ if (sblk->s_major > 1)
1138+ TRACE("sblk->fragment_table_start %llx\n",
1139+ sblk->fragment_table_start);
1140+ TRACE("sblk->uid_start %llx\n", sblk->uid_start);
1141+
1142+ s->s_flags |= MS_RDONLY;
1143+ s->s_op = &squashfs_ops;
1144+
1145+ /* Init inode_table block pointer array */
1146+ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
1147+ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
1148+ ERROR("Failed to allocate block cache\n");
1149+ goto failed_mount;
1150+ }
1151+
1152+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
1153+ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
1154+
1155+ msblk->next_cache = 0;
1156+
1157+ /* Allocate read_data block */
1158+ msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
1159+ SQUASHFS_METADATA_SIZE :
1160+ sblk->block_size;
1161+
1162+ if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
1163+ ERROR("Failed to allocate read_data block\n");
1164+ goto failed_mount;
1165+ }
1166+
1167+ /* Allocate read_page block */
1168+ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
1169+ ERROR("Failed to allocate read_page block\n");
1170+ goto failed_mount;
1171+ }
1172+
1173+ /* Allocate uid and gid tables */
1174+ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
1175+ sizeof(unsigned int), GFP_KERNEL))) {
1176+ ERROR("Failed to allocate uid/gid table\n");
1177+ goto failed_mount;
1178+ }
1179+ msblk->guid = msblk->uid + sblk->no_uids;
1180+
1181+ if (msblk->swap) {
1182+ unsigned int suid[sblk->no_uids + sblk->no_guids];
1183+
1184+ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
1185+ ((sblk->no_uids + sblk->no_guids) *
1186+ sizeof(unsigned int)) |
1187+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1188+ ERROR("unable to read uid/gid table\n");
1189+ goto failed_mount;
1190+ }
1191+
1192+ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
1193+ sblk->no_guids), (sizeof(unsigned int) * 8));
1194+ } else
1195+ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
1196+ ((sblk->no_uids + sblk->no_guids) *
1197+ sizeof(unsigned int)) |
1198+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1199+ ERROR("unable to read uid/gid table\n");
1200+ goto failed_mount;
1201+ }
1202+
1203+
1204+ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
1205+ goto allocate_root;
1206+
1207+ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
1208+ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
1209+ ERROR("Failed to allocate fragment block cache\n");
1210+ goto failed_mount;
1211+ }
1212+
1213+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
1214+ msblk->fragment[i].locked = 0;
1215+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
1216+ msblk->fragment[i].data = NULL;
1217+ }
1218+
1219+ msblk->next_fragment = 0;
1220+
1221+ /* Allocate fragment index table */
1222+ if (msblk->read_fragment_index_table(s) == 0)
1223+ goto failed_mount;
1224+
1225+allocate_root:
1226+ if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
1227+ goto failed_mount;
1228+
1229+ if ((s->s_root = d_alloc_root(root)) == NULL) {
1230+ ERROR("Root inode create failed\n");
1231+ iput(root);
1232+ goto failed_mount;
1233+ }
1234+
1235+ TRACE("Leaving squashfs_read_super\n");
1236+ return 0;
1237+
1238+failed_mount:
1239+ kfree(msblk->fragment_index);
1240+ kfree(msblk->fragment);
1241+ kfree(msblk->uid);
1242+ kfree(msblk->read_page);
1243+ kfree(msblk->read_data);
1244+ kfree(msblk->block_cache);
1245+ kfree(msblk->fragment_index_2);
1246+ kfree(s->s_fs_info);
1247+ s->s_fs_info = NULL;
1248+ return -EINVAL;
1249+
1250+failure:
1251+ return -ENOMEM;
1252+}
1253+
1254+
1255+static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1256+{
1257+ struct super_block *s = dentry->d_sb;
1258+ struct squashfs_sb_info *msblk = s->s_fs_info;
1259+ struct squashfs_super_block *sblk = &msblk->sblk;
1260+
1261+ TRACE("Entered squashfs_statfs\n");
1262+
1263+ buf->f_type = SQUASHFS_MAGIC;
1264+ buf->f_bsize = sblk->block_size;
1265+ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
1266+ buf->f_bfree = buf->f_bavail = 0;
1267+ buf->f_files = sblk->inodes;
1268+ buf->f_ffree = 0;
1269+ buf->f_namelen = SQUASHFS_NAME_LEN;
1270+
1271+ return 0;
1272+}
1273+
1274+
1275+static int squashfs_symlink_readpage(struct file *file, struct page *page)
1276+{
1277+ struct inode *inode = page->mapping->host;
1278+ int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
1279+ long long block = SQUASHFS_I(inode)->start_block;
1280+ int offset = SQUASHFS_I(inode)->offset;
1281+ void *pageaddr = kmap(page);
1282+
1283+ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
1284+ "%llx, offset %x\n", page->index,
1285+ SQUASHFS_I(inode)->start_block,
1286+ SQUASHFS_I(inode)->offset);
1287+
1288+ for (length = 0; length < index; length += bytes) {
1289+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
1290+ block, offset, PAGE_CACHE_SIZE, &block,
1291+ &offset))) {
1292+ ERROR("Unable to read symbolic link [%llx:%x]\n", block,
1293+ offset);
1294+ goto skip_read;
1295+ }
1296+ }
1297+
1298+ if (length != index) {
1299+ ERROR("(squashfs_symlink_readpage) length != index\n");
1300+ bytes = 0;
1301+ goto skip_read;
1302+ }
1303+
1304+ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
1305+ i_size_read(inode) - length;
1306+
1307+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
1308+ offset, bytes, &block, &offset)))
1309+ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
1310+
1311+skip_read:
1312+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1313+ kunmap(page);
1314+ SetPageUptodate(page);
1315+ unlock_page(page);
1316+
1317+ return 0;
1318+}
1319+
1320+
1321+struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
1322+{
1323+ struct meta_index *meta = NULL;
1324+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1325+ int i;
1326+
1327+ down(&msblk->meta_index_mutex);
1328+
1329+ TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
1330+
1331+ if(msblk->meta_index == NULL)
1332+ goto not_allocated;
1333+
1334+ for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
1335+ if (msblk->meta_index[i].inode_number == inode->i_ino &&
1336+ msblk->meta_index[i].offset >= offset &&
1337+ msblk->meta_index[i].offset <= index &&
1338+ msblk->meta_index[i].locked == 0) {
1339+ TRACE("locate_meta_index: entry %d, offset %d\n", i,
1340+ msblk->meta_index[i].offset);
1341+ meta = &msblk->meta_index[i];
1342+ offset = meta->offset;
1343+ }
1344+
1345+ if (meta)
1346+ meta->locked = 1;
1347+
1348+not_allocated:
1349+ up(&msblk->meta_index_mutex);
1350+
1351+ return meta;
1352+}
1353+
1354+
1355+struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
1356+{
1357+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1358+ struct meta_index *meta = NULL;
1359+ int i;
1360+
1361+ down(&msblk->meta_index_mutex);
1362+
1363+ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
1364+
1365+ if(msblk->meta_index == NULL) {
1366+ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
1367+ SQUASHFS_META_NUMBER, GFP_KERNEL))) {
1368+ ERROR("Failed to allocate meta_index\n");
1369+ goto failed;
1370+ }
1371+ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
1372+ msblk->meta_index[i].inode_number = 0;
1373+ msblk->meta_index[i].locked = 0;
1374+ }
1375+ msblk->next_meta_index = 0;
1376+ }
1377+
1378+ for(i = SQUASHFS_META_NUMBER; i &&
1379+ msblk->meta_index[msblk->next_meta_index].locked; i --)
1380+ msblk->next_meta_index = (msblk->next_meta_index + 1) %
1381+ SQUASHFS_META_NUMBER;
1382+
1383+ if(i == 0) {
1384+ TRACE("empty_meta_index: failed!\n");
1385+ goto failed;
1386+ }
1387+
1388+ TRACE("empty_meta_index: returned meta entry %d, %p\n",
1389+ msblk->next_meta_index,
1390+ &msblk->meta_index[msblk->next_meta_index]);
1391+
1392+ meta = &msblk->meta_index[msblk->next_meta_index];
1393+ msblk->next_meta_index = (msblk->next_meta_index + 1) %
1394+ SQUASHFS_META_NUMBER;
1395+
1396+ meta->inode_number = inode->i_ino;
1397+ meta->offset = offset;
1398+ meta->skip = skip;
1399+ meta->entries = 0;
1400+ meta->locked = 1;
1401+
1402+failed:
1403+ up(&msblk->meta_index_mutex);
1404+ return meta;
1405+}
1406+
1407+
1408+void release_meta_index(struct inode *inode, struct meta_index *meta)
1409+{
1410+ meta->locked = 0;
1411+}
1412+
1413+
1414+static int read_block_index(struct super_block *s, int blocks, char *block_list,
1415+ long long *start_block, int *offset)
1416+{
1417+ struct squashfs_sb_info *msblk = s->s_fs_info;
1418+ unsigned int *block_listp;
1419+ int block = 0;
1420+
1421+ if (msblk->swap) {
1422+ char sblock_list[blocks << 2];
1423+
1424+ if (!squashfs_get_cached_block(s, sblock_list, *start_block,
1425+ *offset, blocks << 2, start_block, offset)) {
1426+ ERROR("Unable to read block list [%llx:%x]\n",
1427+ *start_block, *offset);
1428+ goto failure;
1429+ }
1430+ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
1431+ ((unsigned int *)sblock_list), blocks);
1432+ } else
1433+ if (!squashfs_get_cached_block(s, block_list, *start_block,
1434+ *offset, blocks << 2, start_block, offset)) {
1435+ ERROR("Unable to read block list [%llx:%x]\n",
1436+ *start_block, *offset);
1437+ goto failure;
1438+ }
1439+
1440+ for (block_listp = (unsigned int *) block_list; blocks;
1441+ block_listp++, blocks --)
1442+ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
1443+
1444+ return block;
1445+
1446+failure:
1447+ return -1;
1448+}
1449+
1450+
1451+#define SIZE 256
1452+
1453+static inline int calculate_skip(int blocks) {
1454+ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
1455+ return skip >= 7 ? 7 : skip + 1;
1456+}
1457+
1458+
1459+static int get_meta_index(struct inode *inode, int index,
1460+ long long *index_block, int *index_offset,
1461+ long long *data_block, char *block_list)
1462+{
1463+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1464+ struct squashfs_super_block *sblk = &msblk->sblk;
1465+ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
1466+ int offset = 0;
1467+ struct meta_index *meta;
1468+ struct meta_entry *meta_entry;
1469+ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
1470+ int cur_offset = SQUASHFS_I(inode)->offset;
1471+ long long cur_data_block = SQUASHFS_I(inode)->start_block;
1472+ int i;
1473+
1474+ index /= SQUASHFS_META_INDEXES * skip;
1475+
1476+ while ( offset < index ) {
1477+ meta = locate_meta_index(inode, index, offset + 1);
1478+
1479+ if (meta == NULL) {
1480+ if ((meta = empty_meta_index(inode, offset + 1,
1481+ skip)) == NULL)
1482+ goto all_done;
1483+ } else {
1484+ offset = index < meta->offset + meta->entries ? index :
1485+ meta->offset + meta->entries - 1;
1486+ meta_entry = &meta->meta_entry[offset - meta->offset];
1487+ cur_index_block = meta_entry->index_block + sblk->inode_table_start;
1488+ cur_offset = meta_entry->offset;
1489+ cur_data_block = meta_entry->data_block;
1490+ TRACE("get_meta_index: offset %d, meta->offset %d, "
1491+ "meta->entries %d\n", offset, meta->offset,
1492+ meta->entries);
1493+ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
1494+ " data_block 0x%llx\n", cur_index_block,
1495+ cur_offset, cur_data_block);
1496+ }
1497+
1498+ for (i = meta->offset + meta->entries; i <= index &&
1499+ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
1500+ int blocks = skip * SQUASHFS_META_INDEXES;
1501+
1502+ while (blocks) {
1503+ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
1504+ blocks;
1505+ int res = read_block_index(inode->i_sb, block,
1506+ block_list, &cur_index_block,
1507+ &cur_offset);
1508+
1509+ if (res == -1)
1510+ goto failed;
1511+
1512+ cur_data_block += res;
1513+ blocks -= block;
1514+ }
1515+
1516+ meta_entry = &meta->meta_entry[i - meta->offset];
1517+ meta_entry->index_block = cur_index_block - sblk->inode_table_start;
1518+ meta_entry->offset = cur_offset;
1519+ meta_entry->data_block = cur_data_block;
1520+ meta->entries ++;
1521+ offset ++;
1522+ }
1523+
1524+ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
1525+ meta->offset, meta->entries);
1526+
1527+ release_meta_index(inode, meta);
1528+ }
1529+
1530+all_done:
1531+ *index_block = cur_index_block;
1532+ *index_offset = cur_offset;
1533+ *data_block = cur_data_block;
1534+
1535+ return offset * SQUASHFS_META_INDEXES * skip;
1536+
1537+failed:
1538+ release_meta_index(inode, meta);
1539+ return -1;
1540+}
1541+
1542+
1543+static long long read_blocklist(struct inode *inode, int index,
1544+ int readahead_blks, char *block_list,
1545+ unsigned short **block_p, unsigned int *bsize)
1546+{
1547+ long long block_ptr;
1548+ int offset;
1549+ long long block;
1550+ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
1551+ block_list);
1552+
1553+ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
1554+ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
1555+ block);
1556+
1557+ if(res == -1)
1558+ goto failure;
1559+
1560+ index -= res;
1561+
1562+ while ( index ) {
1563+ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
1564+ int res = read_block_index(inode->i_sb, blocks, block_list,
1565+ &block_ptr, &offset);
1566+ if (res == -1)
1567+ goto failure;
1568+ block += res;
1569+ index -= blocks;
1570+ }
1571+
1572+ if (read_block_index(inode->i_sb, 1, block_list,
1573+ &block_ptr, &offset) == -1)
1574+ goto failure;
1575+ *bsize = *((unsigned int *) block_list);
1576+
1577+ return block;
1578+
1579+failure:
1580+ return 0;
1581+}
1582+
1583+
1584+static int squashfs_readpage(struct file *file, struct page *page)
1585+{
1586+ struct inode *inode = page->mapping->host;
1587+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1588+ struct squashfs_super_block *sblk = &msblk->sblk;
1589+ unsigned char block_list[SIZE];
1590+ long long block;
1591+ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
1592+ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
1593+ void *pageaddr;
1594+ struct squashfs_fragment_cache *fragment = NULL;
1595+ char *data_ptr = msblk->read_page;
1596+
1597+ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
1598+ int start_index = page->index & ~mask;
1599+ int end_index = start_index | mask;
1600+
1601+ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
1602+ page->index,
1603+ SQUASHFS_I(inode)->start_block);
1604+
1605+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1606+ PAGE_CACHE_SHIFT))
1607+ goto skip_read;
1608+
1609+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1610+ || index < (i_size_read(inode) >>
1611+ sblk->block_log)) {
1612+ if ((block = (msblk->read_blocklist)(inode, index, 1,
1613+ block_list, NULL, &bsize)) == 0)
1614+ goto skip_read;
1615+
1616+ down(&msblk->read_page_mutex);
1617+
1618+ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
1619+ block, bsize, NULL))) {
1620+ ERROR("Unable to read page, block %llx, size %x\n", block,
1621+ bsize);
1622+ up(&msblk->read_page_mutex);
1623+ goto skip_read;
1624+ }
1625+ } else {
1626+ if ((fragment = get_cached_fragment(inode->i_sb,
1627+ SQUASHFS_I(inode)->
1628+ u.s1.fragment_start_block,
1629+ SQUASHFS_I(inode)->u.s1.fragment_size))
1630+ == NULL) {
1631+ ERROR("Unable to read page, block %llx, size %x\n",
1632+ SQUASHFS_I(inode)->
1633+ u.s1.fragment_start_block,
1634+ (int) SQUASHFS_I(inode)->
1635+ u.s1.fragment_size);
1636+ goto skip_read;
1637+ }
1638+ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
1639+ (i_size_read(inode) & (sblk->block_size
1640+ - 1));
1641+ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
1642+ data_ptr = fragment->data;
1643+ }
1644+
1645+ for (i = start_index; i <= end_index && byte_offset < bytes;
1646+ i++, byte_offset += PAGE_CACHE_SIZE) {
1647+ struct page *push_page;
1648+ int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
1649+ PAGE_CACHE_SIZE : bytes - byte_offset;
1650+
1651+ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
1652+ bytes, i, byte_offset, available_bytes);
1653+
1654+ if (i == page->index) {
1655+ pageaddr = kmap_atomic(page, KM_USER0);
1656+ memcpy(pageaddr, data_ptr + byte_offset,
1657+ available_bytes);
1658+ memset(pageaddr + available_bytes, 0,
1659+ PAGE_CACHE_SIZE - available_bytes);
1660+ kunmap_atomic(pageaddr, KM_USER0);
1661+ flush_dcache_page(page);
1662+ SetPageUptodate(page);
1663+ unlock_page(page);
1664+ } else if ((push_page =
1665+ grab_cache_page_nowait(page->mapping, i))) {
1666+ pageaddr = kmap_atomic(push_page, KM_USER0);
1667+
1668+ memcpy(pageaddr, data_ptr + byte_offset,
1669+ available_bytes);
1670+ memset(pageaddr + available_bytes, 0,
1671+ PAGE_CACHE_SIZE - available_bytes);
1672+ kunmap_atomic(pageaddr, KM_USER0);
1673+ flush_dcache_page(push_page);
1674+ SetPageUptodate(push_page);
1675+ unlock_page(push_page);
1676+ page_cache_release(push_page);
1677+ }
1678+ }
1679+
1680+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1681+ || index < (i_size_read(inode) >>
1682+ sblk->block_log))
1683+ up(&msblk->read_page_mutex);
1684+ else
1685+ release_cached_fragment(msblk, fragment);
1686+
1687+ return 0;
1688+
1689+skip_read:
1690+ pageaddr = kmap_atomic(page, KM_USER0);
1691+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1692+ kunmap_atomic(pageaddr, KM_USER0);
1693+ flush_dcache_page(page);
1694+ SetPageUptodate(page);
1695+ unlock_page(page);
1696+
1697+ return 0;
1698+}
1699+
1700+
1701+static int squashfs_readpage4K(struct file *file, struct page *page)
1702+{
1703+ struct inode *inode = page->mapping->host;
1704+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1705+ struct squashfs_super_block *sblk = &msblk->sblk;
1706+ unsigned char block_list[SIZE];
1707+ long long block;
1708+ unsigned int bsize, bytes = 0;
1709+ void *pageaddr;
1710+
1711+ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
1712+ page->index,
1713+ SQUASHFS_I(inode)->start_block);
1714+
1715+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1716+ PAGE_CACHE_SHIFT)) {
1717+ pageaddr = kmap_atomic(page, KM_USER0);
1718+ goto skip_read;
1719+ }
1720+
1721+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1722+ || page->index < (i_size_read(inode) >>
1723+ sblk->block_log)) {
1724+ block = (msblk->read_blocklist)(inode, page->index, 1,
1725+ block_list, NULL, &bsize);
1726+
1727+ down(&msblk->read_page_mutex);
1728+ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
1729+ bsize, NULL);
1730+ pageaddr = kmap_atomic(page, KM_USER0);
1731+ if (bytes)
1732+ memcpy(pageaddr, msblk->read_page, bytes);
1733+ else
1734+ ERROR("Unable to read page, block %llx, size %x\n",
1735+ block, bsize);
1736+ up(&msblk->read_page_mutex);
1737+ } else {
1738+ struct squashfs_fragment_cache *fragment =
1739+ get_cached_fragment(inode->i_sb,
1740+ SQUASHFS_I(inode)->
1741+ u.s1.fragment_start_block,
1742+ SQUASHFS_I(inode)-> u.s1.fragment_size);
1743+ pageaddr = kmap_atomic(page, KM_USER0);
1744+ if (fragment) {
1745+ bytes = i_size_read(inode) & (sblk->block_size - 1);
1746+ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
1747+ u.s1.fragment_offset, bytes);
1748+ release_cached_fragment(msblk, fragment);
1749+ } else
1750+ ERROR("Unable to read page, block %llx, size %x\n",
1751+ SQUASHFS_I(inode)->
1752+ u.s1.fragment_start_block, (int)
1753+ SQUASHFS_I(inode)-> u.s1.fragment_size);
1754+ }
1755+
1756+skip_read:
1757+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1758+ kunmap_atomic(pageaddr, KM_USER0);
1759+ flush_dcache_page(page);
1760+ SetPageUptodate(page);
1761+ unlock_page(page);
1762+
1763+ return 0;
1764+}
1765+
1766+
1767+static int get_dir_index_using_offset(struct super_block *s, long long
1768+ *next_block, unsigned int *next_offset,
1769+ long long index_start,
1770+ unsigned int index_offset, int i_count,
1771+ long long f_pos)
1772+{
1773+ struct squashfs_sb_info *msblk = s->s_fs_info;
1774+ struct squashfs_super_block *sblk = &msblk->sblk;
1775+ int i, length = 0;
1776+ struct squashfs_dir_index index;
1777+
1778+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
1779+ i_count, (unsigned int) f_pos);
1780+
1781+ f_pos =- 3;
1782+ if (f_pos == 0)
1783+ goto finish;
1784+
1785+ for (i = 0; i < i_count; i++) {
1786+ if (msblk->swap) {
1787+ struct squashfs_dir_index sindex;
1788+ squashfs_get_cached_block(s, (char *) &sindex,
1789+ index_start, index_offset,
1790+ sizeof(sindex), &index_start,
1791+ &index_offset);
1792+ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
1793+ } else
1794+ squashfs_get_cached_block(s, (char *) &index,
1795+ index_start, index_offset,
1796+ sizeof(index), &index_start,
1797+ &index_offset);
1798+
1799+ if (index.index > f_pos)
1800+ break;
1801+
1802+ squashfs_get_cached_block(s, NULL, index_start, index_offset,
1803+ index.size + 1, &index_start,
1804+ &index_offset);
1805+
1806+ length = index.index;
1807+ *next_block = index.start_block + sblk->directory_table_start;
1808+ }
1809+
1810+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
1811+
1812+finish:
1813+ return length + 3;
1814+}
1815+
1816+
1817+static int get_dir_index_using_name(struct super_block *s, long long
1818+ *next_block, unsigned int *next_offset,
1819+ long long index_start,
1820+ unsigned int index_offset, int i_count,
1821+ const char *name, int size)
1822+{
1823+ struct squashfs_sb_info *msblk = s->s_fs_info;
1824+ struct squashfs_super_block *sblk = &msblk->sblk;
1825+ int i, length = 0;
1826+ char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
1827+ struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
1828+ char str[SQUASHFS_NAME_LEN + 1];
1829+
1830+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
1831+
1832+ strncpy(str, name, size);
1833+ str[size] = '\0';
1834+
1835+ for (i = 0; i < i_count; i++) {
1836+ if (msblk->swap) {
1837+ struct squashfs_dir_index sindex;
1838+ squashfs_get_cached_block(s, (char *) &sindex,
1839+ index_start, index_offset,
1840+ sizeof(sindex), &index_start,
1841+ &index_offset);
1842+ SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
1843+ } else
1844+ squashfs_get_cached_block(s, (char *) index,
1845+ index_start, index_offset,
1846+ sizeof(struct squashfs_dir_index),
1847+ &index_start, &index_offset);
1848+
1849+ squashfs_get_cached_block(s, index->name, index_start,
1850+ index_offset, index->size + 1,
1851+ &index_start, &index_offset);
1852+
1853+ index->name[index->size + 1] = '\0';
1854+
1855+ if (strcmp(index->name, str) > 0)
1856+ break;
1857+
1858+ length = index->index;
1859+ *next_block = index->start_block + sblk->directory_table_start;
1860+ }
1861+
1862+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
1863+ return length + 3;
1864+}
1865+
1866+
1867+static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
1868+{
1869+ struct inode *i = file->f_dentry->d_inode;
1870+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
1871+ struct squashfs_super_block *sblk = &msblk->sblk;
1872+ long long next_block = SQUASHFS_I(i)->start_block +
1873+ sblk->directory_table_start;
1874+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
1875+ dir_count;
1876+ struct squashfs_dir_header dirh;
1877+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
1878+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
1879+
1880+ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
1881+
1882+ while(file->f_pos < 3) {
1883+ char *name;
1884+ int size, i_ino;
1885+
1886+ if(file->f_pos == 0) {
1887+ name = ".";
1888+ size = 1;
1889+ i_ino = i->i_ino;
1890+ } else {
1891+ name = "..";
1892+ size = 2;
1893+ i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
1894+ }
1895+ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
1896+ (unsigned int) dirent, name, size, (int)
1897+ file->f_pos, i_ino,
1898+ squashfs_filetype_table[1]);
1899+
1900+ if (filldir(dirent, name, size,
1901+ file->f_pos, i_ino,
1902+ squashfs_filetype_table[1]) < 0) {
1903+ TRACE("Filldir returned less than 0\n");
1904+ goto finish;
1905+ }
1906+ file->f_pos += size;
1907+ dirs_read++;
1908+ }
1909+
1910+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
1911+ SQUASHFS_I(i)->u.s2.directory_index_start,
1912+ SQUASHFS_I(i)->u.s2.directory_index_offset,
1913+ SQUASHFS_I(i)->u.s2.directory_index_count,
1914+ file->f_pos);
1915+
1916+ while (length < i_size_read(i)) {
1917+ /* read directory header */
1918+ if (msblk->swap) {
1919+ struct squashfs_dir_header sdirh;
1920+
1921+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
1922+ next_block, next_offset, sizeof(sdirh),
1923+ &next_block, &next_offset))
1924+ goto failed_read;
1925+
1926+ length += sizeof(sdirh);
1927+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
1928+ } else {
1929+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
1930+ next_block, next_offset, sizeof(dirh),
1931+ &next_block, &next_offset))
1932+ goto failed_read;
1933+
1934+ length += sizeof(dirh);
1935+ }
1936+
1937+ dir_count = dirh.count + 1;
1938+ while (dir_count--) {
1939+ if (msblk->swap) {
1940+ struct squashfs_dir_entry sdire;
1941+ if (!squashfs_get_cached_block(i->i_sb, (char *)
1942+ &sdire, next_block, next_offset,
1943+ sizeof(sdire), &next_block,
1944+ &next_offset))
1945+ goto failed_read;
1946+
1947+ length += sizeof(sdire);
1948+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
1949+ } else {
1950+ if (!squashfs_get_cached_block(i->i_sb, (char *)
1951+ dire, next_block, next_offset,
1952+ sizeof(*dire), &next_block,
1953+ &next_offset))
1954+ goto failed_read;
1955+
1956+ length += sizeof(*dire);
1957+ }
1958+
1959+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
1960+ next_block, next_offset,
1961+ dire->size + 1, &next_block,
1962+ &next_offset))
1963+ goto failed_read;
1964+
1965+ length += dire->size + 1;
1966+
1967+ if (file->f_pos >= length)
1968+ continue;
1969+
1970+ dire->name[dire->size + 1] = '\0';
1971+
1972+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
1973+ (unsigned int) dirent, dire->name,
1974+ dire->size + 1, (int) file->f_pos,
1975+ dirh.start_block, dire->offset,
1976+ dirh.inode_number + dire->inode_number,
1977+ squashfs_filetype_table[dire->type]);
1978+
1979+ if (filldir(dirent, dire->name, dire->size + 1,
1980+ file->f_pos,
1981+ dirh.inode_number + dire->inode_number,
1982+ squashfs_filetype_table[dire->type])
1983+ < 0) {
1984+ TRACE("Filldir returned less than 0\n");
1985+ goto finish;
1986+ }
1987+ file->f_pos = length;
1988+ dirs_read++;
1989+ }
1990+ }
1991+
1992+finish:
1993+ return dirs_read;
1994+
1995+failed_read:
1996+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
1997+ next_offset);
1998+ return 0;
1999+}
2000+
2001+
2002+static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
2003+ struct nameidata *nd)
2004+{
2005+ const unsigned char *name = dentry->d_name.name;
2006+ int len = dentry->d_name.len;
2007+ struct inode *inode = NULL;
2008+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
2009+ struct squashfs_super_block *sblk = &msblk->sblk;
2010+ long long next_block = SQUASHFS_I(i)->start_block +
2011+ sblk->directory_table_start;
2012+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
2013+ dir_count;
2014+ struct squashfs_dir_header dirh;
2015+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
2016+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
2017+
2018+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
2019+
2020+ if (len > SQUASHFS_NAME_LEN)
2021+ goto exit_loop;
2022+
2023+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
2024+ SQUASHFS_I(i)->u.s2.directory_index_start,
2025+ SQUASHFS_I(i)->u.s2.directory_index_offset,
2026+ SQUASHFS_I(i)->u.s2.directory_index_count, name,
2027+ len);
2028+
2029+ while (length < i_size_read(i)) {
2030+ /* read directory header */
2031+ if (msblk->swap) {
2032+ struct squashfs_dir_header sdirh;
2033+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
2034+ next_block, next_offset, sizeof(sdirh),
2035+ &next_block, &next_offset))
2036+ goto failed_read;
2037+
2038+ length += sizeof(sdirh);
2039+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
2040+ } else {
2041+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
2042+ next_block, next_offset, sizeof(dirh),
2043+ &next_block, &next_offset))
2044+ goto failed_read;
2045+
2046+ length += sizeof(dirh);
2047+ }
2048+
2049+ dir_count = dirh.count + 1;
2050+ while (dir_count--) {
2051+ if (msblk->swap) {
2052+ struct squashfs_dir_entry sdire;
2053+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2054+ &sdire, next_block,next_offset,
2055+ sizeof(sdire), &next_block,
2056+ &next_offset))
2057+ goto failed_read;
2058+
2059+ length += sizeof(sdire);
2060+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
2061+ } else {
2062+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2063+ dire, next_block,next_offset,
2064+ sizeof(*dire), &next_block,
2065+ &next_offset))
2066+ goto failed_read;
2067+
2068+ length += sizeof(*dire);
2069+ }
2070+
2071+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
2072+ next_block, next_offset, dire->size + 1,
2073+ &next_block, &next_offset))
2074+ goto failed_read;
2075+
2076+ length += dire->size + 1;
2077+
2078+ if (name[0] < dire->name[0])
2079+ goto exit_loop;
2080+
2081+ if ((len == dire->size + 1) && !strncmp(name,
2082+ dire->name, len)) {
2083+ squashfs_inode_t ino =
2084+ SQUASHFS_MKINODE(dirh.start_block,
2085+ dire->offset);
2086+
2087+ TRACE("calling squashfs_iget for directory "
2088+ "entry %s, inode %x:%x, %d\n", name,
2089+ dirh.start_block, dire->offset,
2090+ dirh.inode_number + dire->inode_number);
2091+
2092+ inode = (msblk->iget)(i->i_sb, ino);
2093+
2094+ goto exit_loop;
2095+ }
2096+ }
2097+ }
2098+
2099+exit_loop:
2100+ d_add(dentry, inode);
2101+ return ERR_PTR(0);
2102+
2103+failed_read:
2104+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
2105+ next_offset);
2106+ goto exit_loop;
2107+}
2108+
2109+
2110+static void squashfs_put_super(struct super_block *s)
2111+{
2112+ int i;
2113+
2114+ if (s->s_fs_info) {
2115+ struct squashfs_sb_info *sbi = s->s_fs_info;
2116+ if (sbi->block_cache)
2117+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
2118+ if (sbi->block_cache[i].block !=
2119+ SQUASHFS_INVALID_BLK)
2120+ kfree(sbi->block_cache[i].data);
2121+ if (sbi->fragment)
2122+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
2123+ SQUASHFS_FREE(sbi->fragment[i].data);
2124+ kfree(sbi->fragment);
2125+ kfree(sbi->block_cache);
2126+ kfree(sbi->read_data);
2127+ kfree(sbi->read_page);
2128+ kfree(sbi->uid);
2129+ kfree(sbi->fragment_index);
2130+ kfree(sbi->fragment_index_2);
2131+ kfree(sbi->meta_index);
2132+ kfree(s->s_fs_info);
2133+ s->s_fs_info = NULL;
2134+ }
2135+}
2136+
2137+
2138+static int squashfs_get_sb(struct file_system_type *fs_type,
2139+ int flags, const char *dev_name, void *data, struct vfsmount *mnt)
2140+{
2141+ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, mnt);
2142+}
2143+
2144+
2145+static int __init init_squashfs_fs(void)
2146+{
2147+ int err = init_inodecache();
2148+ if (err)
2149+ goto out;
2150+
2151+ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
2152+ "Phillip Lougher\n");
2153+
2154+ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
2155+ ERROR("Failed to allocate zlib workspace\n");
2156+ destroy_inodecache();
2157+ err = -ENOMEM;
2158+ goto out;
2159+ }
2160+
2161+ if ((err = register_filesystem(&squashfs_fs_type))) {
2162+ vfree(stream.workspace);
2163+ destroy_inodecache();
2164+ }
2165+
2166+out:
2167+ return err;
2168+}
2169+
2170+
2171+static void __exit exit_squashfs_fs(void)
2172+{
2173+ vfree(stream.workspace);
2174+ unregister_filesystem(&squashfs_fs_type);
2175+ destroy_inodecache();
2176+}
2177+
2178+
2179+static kmem_cache_t * squashfs_inode_cachep;
2180+
2181+
2182+static struct inode *squashfs_alloc_inode(struct super_block *sb)
2183+{
2184+ struct squashfs_inode_info *ei;
2185+ ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
2186+ if (!ei)
2187+ return NULL;
2188+ return &ei->vfs_inode;
2189+}
2190+
2191+
2192+static void squashfs_destroy_inode(struct inode *inode)
2193+{
2194+ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
2195+}
2196+
2197+
2198+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
2199+{
2200+ struct squashfs_inode_info *ei = foo;
2201+
2202+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
2203+ SLAB_CTOR_CONSTRUCTOR)
2204+ inode_init_once(&ei->vfs_inode);
2205+}
2206+
2207+
2208+static int __init init_inodecache(void)
2209+{
2210+ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
2211+ sizeof(struct squashfs_inode_info),
2212+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
2213+ init_once, NULL);
2214+ if (squashfs_inode_cachep == NULL)
2215+ return -ENOMEM;
2216+ return 0;
2217+}
2218+
2219+
2220+static void destroy_inodecache(void)
2221+{
2222+ kmem_cache_destroy(squashfs_inode_cachep);
2223+}
2224+
2225+
2226+module_init(init_squashfs_fs);
2227+module_exit(exit_squashfs_fs);
2228+MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
2229+MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
2230Index: git/fs/squashfs/Makefile
2231===================================================================
2232--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2233+++ git/fs/squashfs/Makefile 2006-10-31 21:26:45.000000000 +0000
2234@@ -0,0 +1,7 @@
2235+#
2236+# Makefile for the linux squashfs routines.
2237+#
2238+
2239+obj-$(CONFIG_SQUASHFS) += squashfs.o
2240+squashfs-y += inode.o
2241+squashfs-y += squashfs2_0.o
2242Index: git/fs/squashfs/squashfs2_0.c
2243===================================================================
2244--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2245+++ git/fs/squashfs/squashfs2_0.c 2006-11-01 18:01:49.000000000 +0000
2246@@ -0,0 +1,757 @@
2247+/*
2248+ * Squashfs - a compressed read only filesystem for Linux
2249+ *
2250+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
2251+ * Phillip Lougher <phillip@lougher.org.uk>
2252+ *
2253+ * This program is free software; you can redistribute it and/or
2254+ * modify it under the terms of the GNU General Public License
2255+ * as published by the Free Software Foundation; either version 2,
2256+ * or (at your option) any later version.
2257+ *
2258+ * This program is distributed in the hope that it will be useful,
2259+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2260+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2261+ * GNU General Public License for more details.
2262+ *
2263+ * You should have received a copy of the GNU General Public License
2264+ * along with this program; if not, write to the Free Software
2265+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2266+ *
2267+ * squashfs2_0.c
2268+ */
2269+
2270+#include <linux/types.h>
2271+#include <linux/squashfs_fs.h>
2272+#include <linux/module.h>
2273+#include <linux/errno.h>
2274+#include <linux/slab.h>
2275+#include <linux/fs.h>
2276+#include <linux/smp_lock.h>
2277+#include <linux/slab.h>
2278+#include <linux/squashfs_fs_sb.h>
2279+#include <linux/squashfs_fs_i.h>
2280+#include <linux/buffer_head.h>
2281+#include <linux/vfs.h>
2282+#include <linux/init.h>
2283+#include <linux/dcache.h>
2284+#include <linux/wait.h>
2285+#include <linux/zlib.h>
2286+#include <linux/blkdev.h>
2287+#include <linux/vmalloc.h>
2288+#include <asm/uaccess.h>
2289+#include <asm/semaphore.h>
2290+
2291+#include "squashfs.h"
2292+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
2293+static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
2294+ struct nameidata *);
2295+
2296+static struct file_operations squashfs_dir_ops_2 = {
2297+ .read = generic_read_dir,
2298+ .readdir = squashfs_readdir_2
2299+};
2300+
2301+static struct inode_operations squashfs_dir_inode_ops_2 = {
2302+ .lookup = squashfs_lookup_2
2303+};
2304+
2305+static unsigned char squashfs_filetype_table[] = {
2306+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
2307+};
2308+
2309+static int read_fragment_index_table_2(struct super_block *s)
2310+{
2311+ struct squashfs_sb_info *msblk = s->s_fs_info;
2312+ struct squashfs_super_block *sblk = &msblk->sblk;
2313+
2314+ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
2315+ (sblk->fragments), GFP_KERNEL))) {
2316+ ERROR("Failed to allocate uid/gid table\n");
2317+ return 0;
2318+ }
2319+
2320+ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
2321+ !squashfs_read_data(s, (char *)
2322+ msblk->fragment_index_2,
2323+ sblk->fragment_table_start,
2324+ SQUASHFS_FRAGMENT_INDEX_BYTES_2
2325+ (sblk->fragments) |
2326+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
2327+ ERROR("unable to read fragment index table\n");
2328+ return 0;
2329+ }
2330+
2331+ if (msblk->swap) {
2332+ int i;
2333+ unsigned int fragment;
2334+
2335+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
2336+ i++) {
2337+ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
2338+ &msblk->fragment_index_2[i], 1);
2339+ msblk->fragment_index_2[i] = fragment;
2340+ }
2341+ }
2342+
2343+ return 1;
2344+}
2345+
2346+
2347+static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
2348+ long long *fragment_start_block,
2349+ unsigned int *fragment_size)
2350+{
2351+ struct squashfs_sb_info *msblk = s->s_fs_info;
2352+ long long start_block =
2353+ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
2354+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
2355+ struct squashfs_fragment_entry_2 fragment_entry;
2356+
2357+ if (msblk->swap) {
2358+ struct squashfs_fragment_entry_2 sfragment_entry;
2359+
2360+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
2361+ start_block, offset,
2362+ sizeof(sfragment_entry), &start_block,
2363+ &offset))
2364+ goto out;
2365+ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
2366+ } else
2367+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
2368+ start_block, offset,
2369+ sizeof(fragment_entry), &start_block,
2370+ &offset))
2371+ goto out;
2372+
2373+ *fragment_start_block = fragment_entry.start_block;
2374+ *fragment_size = fragment_entry.size;
2375+
2376+ return 1;
2377+
2378+out:
2379+ return 0;
2380+}
2381+
2382+
2383+static struct inode *squashfs_new_inode(struct super_block *s,
2384+ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
2385+{
2386+ struct squashfs_sb_info *msblk = s->s_fs_info;
2387+ struct squashfs_super_block *sblk = &msblk->sblk;
2388+ struct inode *i = new_inode(s);
2389+
2390+ if (i) {
2391+ i->i_ino = ino;
2392+ i->i_mtime.tv_sec = sblk->mkfs_time;
2393+ i->i_atime.tv_sec = sblk->mkfs_time;
2394+ i->i_ctime.tv_sec = sblk->mkfs_time;
2395+ i->i_uid = msblk->uid[inodeb->uid];
2396+ i->i_mode = inodeb->mode;
2397+ i->i_nlink = 1;
2398+ i->i_size = 0;
2399+ if (inodeb->guid == SQUASHFS_GUIDS)
2400+ i->i_gid = i->i_uid;
2401+ else
2402+ i->i_gid = msblk->guid[inodeb->guid];
2403+ }
2404+
2405+ return i;
2406+}
2407+
2408+
2409+static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
2410+{
2411+ struct inode *i;
2412+ struct squashfs_sb_info *msblk = s->s_fs_info;
2413+ struct squashfs_super_block *sblk = &msblk->sblk;
2414+ unsigned int block = SQUASHFS_INODE_BLK(inode) +
2415+ sblk->inode_table_start;
2416+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
2417+ unsigned int ino = SQUASHFS_MK_VFS_INODE(block
2418+ - sblk->inode_table_start, offset);
2419+ long long next_block;
2420+ unsigned int next_offset;
2421+ union squashfs_inode_header_2 id, sid;
2422+ struct squashfs_base_inode_header_2 *inodeb = &id.base,
2423+ *sinodeb = &sid.base;
2424+
2425+ TRACE("Entered squashfs_iget\n");
2426+
2427+ if (msblk->swap) {
2428+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
2429+ offset, sizeof(*sinodeb), &next_block,
2430+ &next_offset))
2431+ goto failed_read;
2432+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
2433+ sizeof(*sinodeb));
2434+ } else
2435+ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
2436+ offset, sizeof(*inodeb), &next_block,
2437+ &next_offset))
2438+ goto failed_read;
2439+
2440+ switch(inodeb->inode_type) {
2441+ case SQUASHFS_FILE_TYPE: {
2442+ struct squashfs_reg_inode_header_2 *inodep = &id.reg;
2443+ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
2444+ long long frag_blk;
2445+ unsigned int frag_size;
2446+
2447+ if (msblk->swap) {
2448+ if (!squashfs_get_cached_block(s, (char *)
2449+ sinodep, block, offset,
2450+ sizeof(*sinodep), &next_block,
2451+ &next_offset))
2452+ goto failed_read;
2453+ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
2454+ } else
2455+ if (!squashfs_get_cached_block(s, (char *)
2456+ inodep, block, offset,
2457+ sizeof(*inodep), &next_block,
2458+ &next_offset))
2459+ goto failed_read;
2460+
2461+ frag_blk = SQUASHFS_INVALID_BLK;
2462+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
2463+ !get_fragment_location_2(s,
2464+ inodep->fragment, &frag_blk, &frag_size))
2465+ goto failed_read;
2466+
2467+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
2468+ goto failed_read1;
2469+
2470+ i->i_size = inodep->file_size;
2471+ i->i_fop = &generic_ro_fops;
2472+ i->i_mode |= S_IFREG;
2473+ i->i_mtime.tv_sec = inodep->mtime;
2474+ i->i_atime.tv_sec = inodep->mtime;
2475+ i->i_ctime.tv_sec = inodep->mtime;
2476+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
2477+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
2478+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
2479+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
2480+ SQUASHFS_I(i)->start_block = inodep->start_block;
2481+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
2482+ SQUASHFS_I(i)->offset = next_offset;
2483+ if (sblk->block_size > 4096)
2484+ i->i_data.a_ops = &squashfs_aops;
2485+ else
2486+ i->i_data.a_ops = &squashfs_aops_4K;
2487+
2488+ TRACE("File inode %x:%x, start_block %x, "
2489+ "block_list_start %llx, offset %x\n",
2490+ SQUASHFS_INODE_BLK(inode), offset,
2491+ inodep->start_block, next_block,
2492+ next_offset);
2493+ break;
2494+ }
2495+ case SQUASHFS_DIR_TYPE: {
2496+ struct squashfs_dir_inode_header_2 *inodep = &id.dir;
2497+ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
2498+
2499+ if (msblk->swap) {
2500+ if (!squashfs_get_cached_block(s, (char *)
2501+ sinodep, block, offset,
2502+ sizeof(*sinodep), &next_block,
2503+ &next_offset))
2504+ goto failed_read;
2505+ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
2506+ } else
2507+ if (!squashfs_get_cached_block(s, (char *)
2508+ inodep, block, offset,
2509+ sizeof(*inodep), &next_block,
2510+ &next_offset))
2511+ goto failed_read;
2512+
2513+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
2514+ goto failed_read1;
2515+
2516+ i->i_size = inodep->file_size;
2517+ i->i_op = &squashfs_dir_inode_ops_2;
2518+ i->i_fop = &squashfs_dir_ops_2;
2519+ i->i_mode |= S_IFDIR;
2520+ i->i_mtime.tv_sec = inodep->mtime;
2521+ i->i_atime.tv_sec = inodep->mtime;
2522+ i->i_ctime.tv_sec = inodep->mtime;
2523+ SQUASHFS_I(i)->start_block = inodep->start_block;
2524+ SQUASHFS_I(i)->offset = inodep->offset;
2525+ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
2526+ SQUASHFS_I(i)->u.s2.parent_inode = 0;
2527+
2528+ TRACE("Directory inode %x:%x, start_block %x, offset "
2529+ "%x\n", SQUASHFS_INODE_BLK(inode),
2530+ offset, inodep->start_block,
2531+ inodep->offset);
2532+ break;
2533+ }
2534+ case SQUASHFS_LDIR_TYPE: {
2535+ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
2536+ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
2537+
2538+ if (msblk->swap) {
2539+ if (!squashfs_get_cached_block(s, (char *)
2540+ sinodep, block, offset,
2541+ sizeof(*sinodep), &next_block,
2542+ &next_offset))
2543+ goto failed_read;
2544+ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
2545+ sinodep);
2546+ } else
2547+ if (!squashfs_get_cached_block(s, (char *)
2548+ inodep, block, offset,
2549+ sizeof(*inodep), &next_block,
2550+ &next_offset))
2551+ goto failed_read;
2552+
2553+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
2554+ goto failed_read1;
2555+
2556+ i->i_size = inodep->file_size;
2557+ i->i_op = &squashfs_dir_inode_ops_2;
2558+ i->i_fop = &squashfs_dir_ops_2;
2559+ i->i_mode |= S_IFDIR;
2560+ i->i_mtime.tv_sec = inodep->mtime;
2561+ i->i_atime.tv_sec = inodep->mtime;
2562+ i->i_ctime.tv_sec = inodep->mtime;
2563+ SQUASHFS_I(i)->start_block = inodep->start_block;
2564+ SQUASHFS_I(i)->offset = inodep->offset;
2565+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
2566+ SQUASHFS_I(i)->u.s2.directory_index_offset =
2567+ next_offset;
2568+ SQUASHFS_I(i)->u.s2.directory_index_count =
2569+ inodep->i_count;
2570+ SQUASHFS_I(i)->u.s2.parent_inode = 0;
2571+
2572+ TRACE("Long directory inode %x:%x, start_block %x, "
2573+ "offset %x\n",
2574+ SQUASHFS_INODE_BLK(inode), offset,
2575+ inodep->start_block, inodep->offset);
2576+ break;
2577+ }
2578+ case SQUASHFS_SYMLINK_TYPE: {
2579+ struct squashfs_symlink_inode_header_2 *inodep =
2580+ &id.symlink;
2581+ struct squashfs_symlink_inode_header_2 *sinodep =
2582+ &sid.symlink;
2583+
2584+ if (msblk->swap) {
2585+ if (!squashfs_get_cached_block(s, (char *)
2586+ sinodep, block, offset,
2587+ sizeof(*sinodep), &next_block,
2588+ &next_offset))
2589+ goto failed_read;
2590+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
2591+ sinodep);
2592+ } else
2593+ if (!squashfs_get_cached_block(s, (char *)
2594+ inodep, block, offset,
2595+ sizeof(*inodep), &next_block,
2596+ &next_offset))
2597+ goto failed_read;
2598+
2599+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
2600+ goto failed_read1;
2601+
2602+ i->i_size = inodep->symlink_size;
2603+ i->i_op = &page_symlink_inode_operations;
2604+ i->i_data.a_ops = &squashfs_symlink_aops;
2605+ i->i_mode |= S_IFLNK;
2606+ SQUASHFS_I(i)->start_block = next_block;
2607+ SQUASHFS_I(i)->offset = next_offset;
2608+
2609+ TRACE("Symbolic link inode %x:%x, start_block %llx, "
2610+ "offset %x\n",
2611+ SQUASHFS_INODE_BLK(inode), offset,
2612+ next_block, next_offset);
2613+ break;
2614+ }
2615+ case SQUASHFS_BLKDEV_TYPE:
2616+ case SQUASHFS_CHRDEV_TYPE: {
2617+ struct squashfs_dev_inode_header_2 *inodep = &id.dev;
2618+ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
2619+
2620+ if (msblk->swap) {
2621+ if (!squashfs_get_cached_block(s, (char *)
2622+ sinodep, block, offset,
2623+ sizeof(*sinodep), &next_block,
2624+ &next_offset))
2625+ goto failed_read;
2626+ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
2627+ } else
2628+ if (!squashfs_get_cached_block(s, (char *)
2629+ inodep, block, offset,
2630+ sizeof(*inodep), &next_block,
2631+ &next_offset))
2632+ goto failed_read;
2633+
2634+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
2635+ goto failed_read1;
2636+
2637+ i->i_mode |= (inodeb->inode_type ==
2638+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
2639+ S_IFBLK;
2640+ init_special_inode(i, i->i_mode,
2641+ old_decode_dev(inodep->rdev));
2642+
2643+ TRACE("Device inode %x:%x, rdev %x\n",
2644+ SQUASHFS_INODE_BLK(inode), offset,
2645+ inodep->rdev);
2646+ break;
2647+ }
2648+ case SQUASHFS_FIFO_TYPE:
2649+ case SQUASHFS_SOCKET_TYPE: {
2650+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
2651+ goto failed_read1;
2652+
2653+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
2654+ ? S_IFIFO : S_IFSOCK;
2655+ init_special_inode(i, i->i_mode, 0);
2656+ break;
2657+ }
2658+ default:
2659+ ERROR("Unknown inode type %d in squashfs_iget!\n",
2660+ inodeb->inode_type);
2661+ goto failed_read1;
2662+ }
2663+
2664+ insert_inode_hash(i);
2665+ return i;
2666+
2667+failed_read:
2668+ ERROR("Unable to read inode [%x:%x]\n", block, offset);
2669+
2670+failed_read1:
2671+ return NULL;
2672+}
2673+
2674+
2675+static int get_dir_index_using_offset(struct super_block *s, long long
2676+ *next_block, unsigned int *next_offset,
2677+ long long index_start,
2678+ unsigned int index_offset, int i_count,
2679+ long long f_pos)
2680+{
2681+ struct squashfs_sb_info *msblk = s->s_fs_info;
2682+ struct squashfs_super_block *sblk = &msblk->sblk;
2683+ int i, length = 0;
2684+ struct squashfs_dir_index_2 index;
2685+
2686+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
2687+ i_count, (unsigned int) f_pos);
2688+
2689+ if (f_pos == 0)
2690+ goto finish;
2691+
2692+ for (i = 0; i < i_count; i++) {
2693+ if (msblk->swap) {
2694+ struct squashfs_dir_index_2 sindex;
2695+ squashfs_get_cached_block(s, (char *) &sindex,
2696+ index_start, index_offset,
2697+ sizeof(sindex), &index_start,
2698+ &index_offset);
2699+ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
2700+ } else
2701+ squashfs_get_cached_block(s, (char *) &index,
2702+ index_start, index_offset,
2703+ sizeof(index), &index_start,
2704+ &index_offset);
2705+
2706+ if (index.index > f_pos)
2707+ break;
2708+
2709+ squashfs_get_cached_block(s, NULL, index_start, index_offset,
2710+ index.size + 1, &index_start,
2711+ &index_offset);
2712+
2713+ length = index.index;
2714+ *next_block = index.start_block + sblk->directory_table_start;
2715+ }
2716+
2717+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
2718+
2719+finish:
2720+ return length;
2721+}
2722+
2723+
2724+static int get_dir_index_using_name(struct super_block *s, long long
2725+ *next_block, unsigned int *next_offset,
2726+ long long index_start,
2727+ unsigned int index_offset, int i_count,
2728+ const char *name, int size)
2729+{
2730+ struct squashfs_sb_info *msblk = s->s_fs_info;
2731+ struct squashfs_super_block *sblk = &msblk->sblk;
2732+ int i, length = 0;
2733+ char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
2734+ struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
2735+ char str[SQUASHFS_NAME_LEN + 1];
2736+
2737+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
2738+
2739+ strncpy(str, name, size);
2740+ str[size] = '\0';
2741+
2742+ for (i = 0; i < i_count; i++) {
2743+ if (msblk->swap) {
2744+ struct squashfs_dir_index_2 sindex;
2745+ squashfs_get_cached_block(s, (char *) &sindex,
2746+ index_start, index_offset,
2747+ sizeof(sindex), &index_start,
2748+ &index_offset);
2749+ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
2750+ } else
2751+ squashfs_get_cached_block(s, (char *) index,
2752+ index_start, index_offset,
2753+ sizeof(struct squashfs_dir_index_2),
2754+ &index_start, &index_offset);
2755+
2756+ squashfs_get_cached_block(s, index->name, index_start,
2757+ index_offset, index->size + 1,
2758+ &index_start, &index_offset);
2759+
2760+ index->name[index->size + 1] = '\0';
2761+
2762+ if (strcmp(index->name, str) > 0)
2763+ break;
2764+
2765+ length = index->index;
2766+ *next_block = index->start_block + sblk->directory_table_start;
2767+ }
2768+
2769+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
2770+ return length;
2771+}
2772+
2773+
2774+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
2775+{
2776+ struct inode *i = file->f_dentry->d_inode;
2777+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
2778+ struct squashfs_super_block *sblk = &msblk->sblk;
2779+ long long next_block = SQUASHFS_I(i)->start_block +
2780+ sblk->directory_table_start;
2781+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
2782+ dir_count;
2783+ struct squashfs_dir_header_2 dirh;
2784+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
2785+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
2786+
2787+ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
2788+
2789+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
2790+ SQUASHFS_I(i)->u.s2.directory_index_start,
2791+ SQUASHFS_I(i)->u.s2.directory_index_offset,
2792+ SQUASHFS_I(i)->u.s2.directory_index_count,
2793+ file->f_pos);
2794+
2795+ while (length < i_size_read(i)) {
2796+ /* read directory header */
2797+ if (msblk->swap) {
2798+ struct squashfs_dir_header_2 sdirh;
2799+
2800+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
2801+ next_block, next_offset, sizeof(sdirh),
2802+ &next_block, &next_offset))
2803+ goto failed_read;
2804+
2805+ length += sizeof(sdirh);
2806+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
2807+ } else {
2808+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
2809+ next_block, next_offset, sizeof(dirh),
2810+ &next_block, &next_offset))
2811+ goto failed_read;
2812+
2813+ length += sizeof(dirh);
2814+ }
2815+
2816+ dir_count = dirh.count + 1;
2817+ while (dir_count--) {
2818+ if (msblk->swap) {
2819+ struct squashfs_dir_entry_2 sdire;
2820+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2821+ &sdire, next_block, next_offset,
2822+ sizeof(sdire), &next_block,
2823+ &next_offset))
2824+ goto failed_read;
2825+
2826+ length += sizeof(sdire);
2827+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
2828+ } else {
2829+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2830+ dire, next_block, next_offset,
2831+ sizeof(*dire), &next_block,
2832+ &next_offset))
2833+ goto failed_read;
2834+
2835+ length += sizeof(*dire);
2836+ }
2837+
2838+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
2839+ next_block, next_offset,
2840+ dire->size + 1, &next_block,
2841+ &next_offset))
2842+ goto failed_read;
2843+
2844+ length += dire->size + 1;
2845+
2846+ if (file->f_pos >= length)
2847+ continue;
2848+
2849+ dire->name[dire->size + 1] = '\0';
2850+
2851+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
2852+ (unsigned int) dirent, dire->name,
2853+ dire->size + 1, (int) file->f_pos,
2854+ dirh.start_block, dire->offset,
2855+ squashfs_filetype_table[dire->type]);
2856+
2857+ if (filldir(dirent, dire->name, dire->size + 1,
2858+ file->f_pos, SQUASHFS_MK_VFS_INODE(
2859+ dirh.start_block, dire->offset),
2860+ squashfs_filetype_table[dire->type])
2861+ < 0) {
2862+ TRACE("Filldir returned less than 0\n");
2863+ goto finish;
2864+ }
2865+ file->f_pos = length;
2866+ dirs_read++;
2867+ }
2868+ }
2869+
2870+finish:
2871+ return dirs_read;
2872+
2873+failed_read:
2874+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
2875+ next_offset);
2876+ return 0;
2877+}
2878+
2879+
2880+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
2881+ struct nameidata *nd)
2882+{
2883+ const unsigned char *name = dentry->d_name.name;
2884+ int len = dentry->d_name.len;
2885+ struct inode *inode = NULL;
2886+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
2887+ struct squashfs_super_block *sblk = &msblk->sblk;
2888+ long long next_block = SQUASHFS_I(i)->start_block +
2889+ sblk->directory_table_start;
2890+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
2891+ dir_count;
2892+ struct squashfs_dir_header_2 dirh;
2893+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
2894+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
2895+ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
2896+
2897+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
2898+
2899+ if (len > SQUASHFS_NAME_LEN)
2900+ goto exit_loop;
2901+
2902+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
2903+ SQUASHFS_I(i)->u.s2.directory_index_start,
2904+ SQUASHFS_I(i)->u.s2.directory_index_offset,
2905+ SQUASHFS_I(i)->u.s2.directory_index_count, name,
2906+ len);
2907+
2908+ while (length < i_size_read(i)) {
2909+ /* read directory header */
2910+ if (msblk->swap) {
2911+ struct squashfs_dir_header_2 sdirh;
2912+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
2913+ next_block, next_offset, sizeof(sdirh),
2914+ &next_block, &next_offset))
2915+ goto failed_read;
2916+
2917+ length += sizeof(sdirh);
2918+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
2919+ } else {
2920+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
2921+ next_block, next_offset, sizeof(dirh),
2922+ &next_block, &next_offset))
2923+ goto failed_read;
2924+
2925+ length += sizeof(dirh);
2926+ }
2927+
2928+ dir_count = dirh.count + 1;
2929+ while (dir_count--) {
2930+ if (msblk->swap) {
2931+ struct squashfs_dir_entry_2 sdire;
2932+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2933+ &sdire, next_block,next_offset,
2934+ sizeof(sdire), &next_block,
2935+ &next_offset))
2936+ goto failed_read;
2937+
2938+ length += sizeof(sdire);
2939+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
2940+ } else {
2941+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2942+ dire, next_block,next_offset,
2943+ sizeof(*dire), &next_block,
2944+ &next_offset))
2945+ goto failed_read;
2946+
2947+ length += sizeof(*dire);
2948+ }
2949+
2950+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
2951+ next_block, next_offset, dire->size + 1,
2952+ &next_block, &next_offset))
2953+ goto failed_read;
2954+
2955+ length += dire->size + 1;
2956+
2957+ if (sorted && name[0] < dire->name[0])
2958+ goto exit_loop;
2959+
2960+ if ((len == dire->size + 1) && !strncmp(name,
2961+ dire->name, len)) {
2962+ squashfs_inode_t ino =
2963+ SQUASHFS_MKINODE(dirh.start_block,
2964+ dire->offset);
2965+
2966+ TRACE("calling squashfs_iget for directory "
2967+ "entry %s, inode %x:%x, %lld\n", name,
2968+ dirh.start_block, dire->offset, ino);
2969+
2970+ inode = (msblk->iget)(i->i_sb, ino);
2971+
2972+ goto exit_loop;
2973+ }
2974+ }
2975+ }
2976+
2977+exit_loop:
2978+ d_add(dentry, inode);
2979+ return ERR_PTR(0);
2980+
2981+failed_read:
2982+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
2983+ next_offset);
2984+ goto exit_loop;
2985+}
2986+
2987+
2988+int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
2989+{
2990+ struct squashfs_super_block *sblk = &msblk->sblk;
2991+
2992+ msblk->iget = squashfs_iget_2;
2993+ msblk->read_fragment_index_table = read_fragment_index_table_2;
2994+
2995+ sblk->bytes_used = sblk->bytes_used_2;
2996+ sblk->uid_start = sblk->uid_start_2;
2997+ sblk->guid_start = sblk->guid_start_2;
2998+ sblk->inode_table_start = sblk->inode_table_start_2;
2999+ sblk->directory_table_start = sblk->directory_table_start_2;
3000+ sblk->fragment_table_start = sblk->fragment_table_start_2;
3001+
3002+ return 1;
3003+}
3004Index: git/fs/squashfs/squashfs.h
3005===================================================================
3006--- /dev/null 1970-01-01 00:00:00.000000000 +0000
3007+++ git/fs/squashfs/squashfs.h 2006-10-31 21:26:45.000000000 +0000
3008@@ -0,0 +1,86 @@
3009+/*
3010+ * Squashfs - a compressed read only filesystem for Linux
3011+ *
3012+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
3013+ * Phillip Lougher <phillip@lougher.org.uk>
3014+ *
3015+ * This program is free software; you can redistribute it and/or
3016+ * modify it under the terms of the GNU General Public License
3017+ * as published by the Free Software Foundation; either version 2,
3018+ * or (at your option) any later version.
3019+ *
3020+ * This program is distributed in the hope that it will be useful,
3021+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3022+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3023+ * GNU General Public License for more details.
3024+ *
3025+ * You should have received a copy of the GNU General Public License
3026+ * along with this program; if not, write to the Free Software
3027+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
3028+ *
3029+ * squashfs.h
3030+ */
3031+
3032+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3033+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3034+#endif
3035+
3036+#ifdef SQUASHFS_TRACE
3037+#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
3038+#else
3039+#define TRACE(s, args...) {}
3040+#endif
3041+
3042+#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
3043+
3044+#define SERROR(s, args...) do { \
3045+ if (!silent) \
3046+ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
3047+ } while(0)
3048+
3049+#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
3050+
3051+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
3052+{
3053+ return list_entry(inode, struct squashfs_inode_info, vfs_inode);
3054+}
3055+
3056+#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
3057+#define SQSH_EXTERN
3058+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
3059+ long long index, unsigned int length,
3060+ long long *next_index);
3061+extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
3062+ long long block, unsigned int offset,
3063+ int length, long long *next_block,
3064+ unsigned int *next_offset);
3065+extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
3066+ squashfs_fragment_cache *fragment);
3067+extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
3068+ *s, long long start_block,
3069+ int length);
3070+extern struct address_space_operations squashfs_symlink_aops;
3071+extern struct address_space_operations squashfs_aops;
3072+extern struct address_space_operations squashfs_aops_4K;
3073+extern struct inode_operations squashfs_dir_inode_ops;
3074+#else
3075+#define SQSH_EXTERN static
3076+#endif
3077+
3078+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3079+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
3080+#else
3081+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
3082+{
3083+ return 0;
3084+}
3085+#endif
3086+
3087+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
3088+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
3089+#else
3090+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
3091+{
3092+ return 0;
3093+}
3094+#endif
3095Index: git/include/linux/squashfs_fs.h
3096===================================================================
3097--- /dev/null 1970-01-01 00:00:00.000000000 +0000
3098+++ git/include/linux/squashfs_fs.h 2006-10-31 21:26:45.000000000 +0000
3099@@ -0,0 +1,911 @@
3100+#ifndef SQUASHFS_FS
3101+#define SQUASHFS_FS
3102+
3103+/*
3104+ * Squashfs
3105+ *
3106+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
3107+ * Phillip Lougher <phillip@lougher.org.uk>
3108+ *
3109+ * This program is free software; you can redistribute it and/or
3110+ * modify it under the terms of the GNU General Public License
3111+ * as published by the Free Software Foundation; either version 2,
3112+ * or (at your option) any later version.
3113+ *
3114+ * This program is distributed in the hope that it will be useful,
3115+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3116+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3117+ * GNU General Public License for more details.
3118+ *
3119+ * You should have received a copy of the GNU General Public License
3120+ * along with this program; if not, write to the Free Software
3121+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
3122+ *
3123+ * squashfs_fs.h
3124+ */
3125+
3126+#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
3127+#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
3128+#endif
3129+
3130+#ifdef CONFIG_SQUASHFS_VMALLOC
3131+#define SQUASHFS_ALLOC(a) vmalloc(a)
3132+#define SQUASHFS_FREE(a) vfree(a)
3133+#else
3134+#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
3135+#define SQUASHFS_FREE(a) kfree(a)
3136+#endif
3137+#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
3138+#define SQUASHFS_MAJOR 3
3139+#define SQUASHFS_MINOR 0
3140+#define SQUASHFS_MAGIC 0x73717368
3141+#define SQUASHFS_MAGIC_SWAP 0x68737173
3142+#define SQUASHFS_START 0
3143+
3144+/* size of metadata (inode and directory) blocks */
3145+#define SQUASHFS_METADATA_SIZE 8192
3146+#define SQUASHFS_METADATA_LOG 13
3147+
3148+/* default size of data blocks */
3149+#define SQUASHFS_FILE_SIZE 65536
3150+#define SQUASHFS_FILE_LOG 16
3151+
3152+#define SQUASHFS_FILE_MAX_SIZE 65536
3153+
3154+/* Max number of uids and gids */
3155+#define SQUASHFS_UIDS 256
3156+#define SQUASHFS_GUIDS 255
3157+
3158+/* Max length of filename (not 255) */
3159+#define SQUASHFS_NAME_LEN 256
3160+
3161+#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
3162+#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
3163+#define SQUASHFS_INVALID_BLK ((long long) -1)
3164+#define SQUASHFS_USED_BLK ((long long) -2)
3165+
3166+/* Filesystem flags */
3167+#define SQUASHFS_NOI 0
3168+#define SQUASHFS_NOD 1
3169+#define SQUASHFS_CHECK 2
3170+#define SQUASHFS_NOF 3
3171+#define SQUASHFS_NO_FRAG 4
3172+#define SQUASHFS_ALWAYS_FRAG 5
3173+#define SQUASHFS_DUPLICATE 6
3174+
3175+#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
3176+
3177+#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
3178+ SQUASHFS_NOI)
3179+
3180+#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
3181+ SQUASHFS_NOD)
3182+
3183+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
3184+ SQUASHFS_NOF)
3185+
3186+#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
3187+ SQUASHFS_NO_FRAG)
3188+
3189+#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
3190+ SQUASHFS_ALWAYS_FRAG)
3191+
3192+#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
3193+ SQUASHFS_DUPLICATE)
3194+
3195+#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
3196+ SQUASHFS_CHECK)
3197+
3198+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
3199+ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \
3200+ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
3201+ (duplicate_checking << 6))
3202+
3203+/* Max number of types and file types */
3204+#define SQUASHFS_DIR_TYPE 1
3205+#define SQUASHFS_FILE_TYPE 2
3206+#define SQUASHFS_SYMLINK_TYPE 3
3207+#define SQUASHFS_BLKDEV_TYPE 4
3208+#define SQUASHFS_CHRDEV_TYPE 5
3209+#define SQUASHFS_FIFO_TYPE 6
3210+#define SQUASHFS_SOCKET_TYPE 7
3211+#define SQUASHFS_LDIR_TYPE 8
3212+#define SQUASHFS_LREG_TYPE 9
3213+
3214+/* 1.0 filesystem type definitions */
3215+#define SQUASHFS_TYPES 5
3216+#define SQUASHFS_IPC_TYPE 0
3217+
3218+/* Flag whether block is compressed or uncompressed, bit is set if block is
3219+ * uncompressed */
3220+#define SQUASHFS_COMPRESSED_BIT (1 << 15)
3221+
3222+#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
3223+ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
3224+
3225+#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
3226+
3227+#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
3228+
3229+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
3230+ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
3231+ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
3232+
3233+#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
3234+
3235+/*
3236+ * Inode number ops. Inodes consist of a compressed block number, and an
3237+ * uncompressed offset within that block
3238+ */
3239+#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
3240+
3241+#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
3242+
3243+#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
3244+ << 16) + (B)))
3245+
3246+/* Compute 32 bit VFS inode number from squashfs inode number */
3247+#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
3248+ ((b) >> 2) + 1))
3249+/* XXX */
3250+
3251+/* Translate between VFS mode and squashfs mode */
3252+#define SQUASHFS_MODE(a) ((a) & 0xfff)
3253+
3254+/* fragment and fragment table defines */
3255+#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry))
3256+
3257+#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
3258+ SQUASHFS_METADATA_SIZE)
3259+
3260+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
3261+ SQUASHFS_METADATA_SIZE)
3262+
3263+#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
3264+ SQUASHFS_METADATA_SIZE - 1) / \
3265+ SQUASHFS_METADATA_SIZE)
3266+
3267+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
3268+ sizeof(long long))
3269+
3270+/* cached data constants for filesystem */
3271+#define SQUASHFS_CACHED_BLKS 8
3272+
3273+#define SQUASHFS_MAX_FILE_SIZE_LOG 64
3274+
3275+#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
3276+ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
3277+
3278+#define SQUASHFS_MARKER_BYTE 0xff
3279+
3280+/* meta index cache */
3281+#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
3282+#define SQUASHFS_META_ENTRIES 31
3283+#define SQUASHFS_META_NUMBER 8
3284+#define SQUASHFS_SLOTS 4
3285+
3286+struct meta_entry {
3287+ long long data_block;
3288+ unsigned int index_block;
3289+ unsigned short offset;
3290+ unsigned short pad;
3291+};
3292+
3293+struct meta_index {
3294+ unsigned int inode_number;
3295+ unsigned int offset;
3296+ unsigned short entries;
3297+ unsigned short skip;
3298+ unsigned short locked;
3299+ unsigned short pad;
3300+ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
3301+};
3302+
3303+
3304+/*
3305+ * definitions for structures on disk
3306+ */
3307+
3308+typedef long long squashfs_block_t;
3309+typedef long long squashfs_inode_t;
3310+
3311+struct squashfs_super_block {
3312+ unsigned int s_magic;
3313+ unsigned int inodes;
3314+ unsigned int bytes_used_2;
3315+ unsigned int uid_start_2;
3316+ unsigned int guid_start_2;
3317+ unsigned int inode_table_start_2;
3318+ unsigned int directory_table_start_2;
3319+ unsigned int s_major:16;
3320+ unsigned int s_minor:16;
3321+ unsigned int block_size_1:16;
3322+ unsigned int block_log:16;
3323+ unsigned int flags:8;
3324+ unsigned int no_uids:8;
3325+ unsigned int no_guids:8;
3326+ unsigned int mkfs_time /* time of filesystem creation */;
3327+ squashfs_inode_t root_inode;
3328+ unsigned int block_size;
3329+ unsigned int fragments;
3330+ unsigned int fragment_table_start_2;
3331+ long long bytes_used;
3332+ long long uid_start;
3333+ long long guid_start;
3334+ long long inode_table_start;
3335+ long long directory_table_start;
3336+ long long fragment_table_start;
3337+ long long unused;
3338+} __attribute__ ((packed));
3339+
3340+struct squashfs_dir_index {
3341+ unsigned int index;
3342+ unsigned int start_block;
3343+ unsigned char size;
3344+ unsigned char name[0];
3345+} __attribute__ ((packed));
3346+
3347+#define SQUASHFS_BASE_INODE_HEADER \
3348+ unsigned int inode_type:4; \
3349+ unsigned int mode:12; \
3350+ unsigned int uid:8; \
3351+ unsigned int guid:8; \
3352+ unsigned int mtime; \
3353+ unsigned int inode_number;
3354+
3355+struct squashfs_base_inode_header {
3356+ SQUASHFS_BASE_INODE_HEADER;
3357+} __attribute__ ((packed));
3358+
3359+struct squashfs_ipc_inode_header {
3360+ SQUASHFS_BASE_INODE_HEADER;
3361+ unsigned int nlink;
3362+} __attribute__ ((packed));
3363+
3364+struct squashfs_dev_inode_header {
3365+ SQUASHFS_BASE_INODE_HEADER;
3366+ unsigned int nlink;
3367+ unsigned short rdev;
3368+} __attribute__ ((packed));
3369+
3370+struct squashfs_symlink_inode_header {
3371+ SQUASHFS_BASE_INODE_HEADER;
3372+ unsigned int nlink;
3373+ unsigned short symlink_size;
3374+ char symlink[0];
3375+} __attribute__ ((packed));
3376+
3377+struct squashfs_reg_inode_header {
3378+ SQUASHFS_BASE_INODE_HEADER;
3379+ squashfs_block_t start_block;
3380+ unsigned int fragment;
3381+ unsigned int offset;
3382+ unsigned int file_size;
3383+ unsigned short block_list[0];
3384+} __attribute__ ((packed));
3385+
3386+struct squashfs_lreg_inode_header {
3387+ SQUASHFS_BASE_INODE_HEADER;
3388+ unsigned int nlink;
3389+ squashfs_block_t start_block;
3390+ unsigned int fragment;
3391+ unsigned int offset;
3392+ long long file_size;
3393+ unsigned short block_list[0];
3394+} __attribute__ ((packed));
3395+
3396+struct squashfs_dir_inode_header {
3397+ SQUASHFS_BASE_INODE_HEADER;
3398+ unsigned int nlink;
3399+ unsigned int file_size:19;
3400+ unsigned int offset:13;
3401+ unsigned int start_block;
3402+ unsigned int parent_inode;
3403+} __attribute__ ((packed));
3404+
3405+struct squashfs_ldir_inode_header {
3406+ SQUASHFS_BASE_INODE_HEADER;
3407+ unsigned int nlink;
3408+ unsigned int file_size:27;
3409+ unsigned int offset:13;
3410+ unsigned int start_block;
3411+ unsigned int i_count:16;
3412+ unsigned int parent_inode;
3413+ struct squashfs_dir_index index[0];
3414+} __attribute__ ((packed));
3415+
3416+union squashfs_inode_header {
3417+ struct squashfs_base_inode_header base;
3418+ struct squashfs_dev_inode_header dev;
3419+ struct squashfs_symlink_inode_header symlink;
3420+ struct squashfs_reg_inode_header reg;
3421+ struct squashfs_lreg_inode_header lreg;
3422+ struct squashfs_dir_inode_header dir;
3423+ struct squashfs_ldir_inode_header ldir;
3424+ struct squashfs_ipc_inode_header ipc;
3425+};
3426+
3427+struct squashfs_dir_entry {
3428+ unsigned int offset:13;
3429+ unsigned int type:3;
3430+ unsigned int size:8;
3431+ int inode_number:16;
3432+ char name[0];
3433+} __attribute__ ((packed));
3434+
3435+struct squashfs_dir_header {
3436+ unsigned int count:8;
3437+ unsigned int start_block;
3438+ unsigned int inode_number;
3439+} __attribute__ ((packed));
3440+
3441+struct squashfs_fragment_entry {
3442+ long long start_block;
3443+ unsigned int size;
3444+ unsigned int unused;
3445+} __attribute__ ((packed));
3446+
3447+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
3448+extern int squashfs_uncompress_init(void);
3449+extern int squashfs_uncompress_exit(void);
3450+
3451+/*
3452+ * macros to convert each packed bitfield structure from little endian to big
3453+ * endian and vice versa. These are needed when creating or using a filesystem
3454+ * on a machine with different byte ordering to the target architecture.
3455+ *
3456+ */
3457+
3458+#define SQUASHFS_SWAP_START \
3459+ int bits;\
3460+ int b_pos;\
3461+ unsigned long long val;\
3462+ unsigned char *s;\
3463+ unsigned char *d;
3464+
3465+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
3466+ SQUASHFS_SWAP_START\
3467+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
3468+ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
3469+ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
3470+ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
3471+ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
3472+ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
3473+ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
3474+ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
3475+ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
3476+ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
3477+ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
3478+ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
3479+ SQUASHFS_SWAP((s)->flags, d, 288, 8);\
3480+ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
3481+ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
3482+ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
3483+ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
3484+ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
3485+ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
3486+ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
3487+ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
3488+ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
3489+ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
3490+ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
3491+ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
3492+ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
3493+ SQUASHFS_SWAP((s)->unused, d, 888, 64);\
3494+}
3495+
3496+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
3497+ SQUASHFS_MEMSET(s, d, n);\
3498+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
3499+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
3500+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
3501+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
3502+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
3503+ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
3504+
3505+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
3506+ SQUASHFS_SWAP_START\
3507+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
3508+}
3509+
3510+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
3511+ SQUASHFS_SWAP_START\
3512+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3513+ sizeof(struct squashfs_ipc_inode_header))\
3514+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3515+}
3516+
3517+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
3518+ SQUASHFS_SWAP_START\
3519+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3520+ sizeof(struct squashfs_dev_inode_header)); \
3521+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3522+ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
3523+}
3524+
3525+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
3526+ SQUASHFS_SWAP_START\
3527+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3528+ sizeof(struct squashfs_symlink_inode_header));\
3529+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3530+ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
3531+}
3532+
3533+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
3534+ SQUASHFS_SWAP_START\
3535+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3536+ sizeof(struct squashfs_reg_inode_header));\
3537+ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
3538+ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
3539+ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
3540+ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
3541+}
3542+
3543+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
3544+ SQUASHFS_SWAP_START\
3545+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3546+ sizeof(struct squashfs_lreg_inode_header));\
3547+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3548+ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
3549+ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
3550+ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
3551+ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
3552+}
3553+
3554+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
3555+ SQUASHFS_SWAP_START\
3556+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3557+ sizeof(struct squashfs_dir_inode_header));\
3558+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3559+ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
3560+ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
3561+ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
3562+ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
3563+}
3564+
3565+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
3566+ SQUASHFS_SWAP_START\
3567+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3568+ sizeof(struct squashfs_ldir_inode_header));\
3569+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3570+ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
3571+ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
3572+ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
3573+ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
3574+ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
3575+}
3576+
3577+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
3578+ SQUASHFS_SWAP_START\
3579+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
3580+ SQUASHFS_SWAP((s)->index, d, 0, 32);\
3581+ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
3582+ SQUASHFS_SWAP((s)->size, d, 64, 8);\
3583+}
3584+
3585+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
3586+ SQUASHFS_SWAP_START\
3587+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
3588+ SQUASHFS_SWAP((s)->count, d, 0, 8);\
3589+ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
3590+ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
3591+}
3592+
3593+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
3594+ SQUASHFS_SWAP_START\
3595+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
3596+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
3597+ SQUASHFS_SWAP((s)->type, d, 13, 3);\
3598+ SQUASHFS_SWAP((s)->size, d, 16, 8);\
3599+ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
3600+}
3601+
3602+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
3603+ SQUASHFS_SWAP_START\
3604+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
3605+ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
3606+ SQUASHFS_SWAP((s)->size, d, 64, 32);\
3607+}
3608+
3609+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
3610+ int entry;\
3611+ int bit_position;\
3612+ SQUASHFS_SWAP_START\
3613+ SQUASHFS_MEMSET(s, d, n * 2);\
3614+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3615+ 16)\
3616+ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
3617+}
3618+
3619+#define SQUASHFS_SWAP_INTS(s, d, n) {\
3620+ int entry;\
3621+ int bit_position;\
3622+ SQUASHFS_SWAP_START\
3623+ SQUASHFS_MEMSET(s, d, n * 4);\
3624+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3625+ 32)\
3626+ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
3627+}
3628+
3629+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
3630+ int entry;\
3631+ int bit_position;\
3632+ SQUASHFS_SWAP_START\
3633+ SQUASHFS_MEMSET(s, d, n * 8);\
3634+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3635+ 64)\
3636+ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
3637+}
3638+
3639+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
3640+ int entry;\
3641+ int bit_position;\
3642+ SQUASHFS_SWAP_START\
3643+ SQUASHFS_MEMSET(s, d, n * bits / 8);\
3644+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3645+ bits)\
3646+ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
3647+}
3648+
3649+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
3650+
3651+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3652+
3653+struct squashfs_base_inode_header_1 {
3654+ unsigned int inode_type:4;
3655+ unsigned int mode:12; /* protection */
3656+ unsigned int uid:4; /* index into uid table */
3657+ unsigned int guid:4; /* index into guid table */
3658+} __attribute__ ((packed));
3659+
3660+struct squashfs_ipc_inode_header_1 {
3661+ unsigned int inode_type:4;
3662+ unsigned int mode:12; /* protection */
3663+ unsigned int uid:4; /* index into uid table */
3664+ unsigned int guid:4; /* index into guid table */
3665+ unsigned int type:4;
3666+ unsigned int offset:4;
3667+} __attribute__ ((packed));
3668+
3669+struct squashfs_dev_inode_header_1 {
3670+ unsigned int inode_type:4;
3671+ unsigned int mode:12; /* protection */
3672+ unsigned int uid:4; /* index into uid table */
3673+ unsigned int guid:4; /* index into guid table */
3674+ unsigned short rdev;
3675+} __attribute__ ((packed));
3676+
3677+struct squashfs_symlink_inode_header_1 {
3678+ unsigned int inode_type:4;
3679+ unsigned int mode:12; /* protection */
3680+ unsigned int uid:4; /* index into uid table */
3681+ unsigned int guid:4; /* index into guid table */
3682+ unsigned short symlink_size;
3683+ char symlink[0];
3684+} __attribute__ ((packed));
3685+
3686+struct squashfs_reg_inode_header_1 {
3687+ unsigned int inode_type:4;
3688+ unsigned int mode:12; /* protection */
3689+ unsigned int uid:4; /* index into uid table */
3690+ unsigned int guid:4; /* index into guid table */
3691+ unsigned int mtime;
3692+ unsigned int start_block;
3693+ unsigned int file_size:32;
3694+ unsigned short block_list[0];
3695+} __attribute__ ((packed));
3696+
3697+struct squashfs_dir_inode_header_1 {
3698+ unsigned int inode_type:4;
3699+ unsigned int mode:12; /* protection */
3700+ unsigned int uid:4; /* index into uid table */
3701+ unsigned int guid:4; /* index into guid table */
3702+ unsigned int file_size:19;
3703+ unsigned int offset:13;
3704+ unsigned int mtime;
3705+ unsigned int start_block:24;
3706+} __attribute__ ((packed));
3707+
3708+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
3709+ SQUASHFS_MEMSET(s, d, n);\
3710+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
3711+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
3712+ SQUASHFS_SWAP((s)->uid, d, 16, 4);\
3713+ SQUASHFS_SWAP((s)->guid, d, 20, 4);
3714+
3715+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
3716+ SQUASHFS_SWAP_START\
3717+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
3718+}
3719+
3720+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
3721+ SQUASHFS_SWAP_START\
3722+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3723+ sizeof(struct squashfs_ipc_inode_header_1));\
3724+ SQUASHFS_SWAP((s)->type, d, 24, 4);\
3725+ SQUASHFS_SWAP((s)->offset, d, 28, 4);\
3726+}
3727+
3728+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
3729+ SQUASHFS_SWAP_START\
3730+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3731+ sizeof(struct squashfs_dev_inode_header_1));\
3732+ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
3733+}
3734+
3735+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
3736+ SQUASHFS_SWAP_START\
3737+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3738+ sizeof(struct squashfs_symlink_inode_header_1));\
3739+ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
3740+}
3741+
3742+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
3743+ SQUASHFS_SWAP_START\
3744+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3745+ sizeof(struct squashfs_reg_inode_header_1));\
3746+ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
3747+ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
3748+ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
3749+}
3750+
3751+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
3752+ SQUASHFS_SWAP_START\
3753+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3754+ sizeof(struct squashfs_dir_inode_header_1));\
3755+ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
3756+ SQUASHFS_SWAP((s)->offset, d, 43, 13);\
3757+ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
3758+ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
3759+}
3760+
3761+#endif
3762+
3763+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
3764+
3765+struct squashfs_dir_index_2 {
3766+ unsigned int index:27;
3767+ unsigned int start_block:29;
3768+ unsigned char size;
3769+ unsigned char name[0];
3770+} __attribute__ ((packed));
3771+
3772+struct squashfs_base_inode_header_2 {
3773+ unsigned int inode_type:4;
3774+ unsigned int mode:12; /* protection */
3775+ unsigned int uid:8; /* index into uid table */
3776+ unsigned int guid:8; /* index into guid table */
3777+} __attribute__ ((packed));
3778+
3779+struct squashfs_ipc_inode_header_2 {
3780+ unsigned int inode_type:4;
3781+ unsigned int mode:12; /* protection */
3782+ unsigned int uid:8; /* index into uid table */
3783+ unsigned int guid:8; /* index into guid table */
3784+} __attribute__ ((packed));
3785+
3786+struct squashfs_dev_inode_header_2 {
3787+ unsigned int inode_type:4;
3788+ unsigned int mode:12; /* protection */
3789+ unsigned int uid:8; /* index into uid table */
3790+ unsigned int guid:8; /* index into guid table */
3791+ unsigned short rdev;
3792+} __attribute__ ((packed));
3793+
3794+struct squashfs_symlink_inode_header_2 {
3795+ unsigned int inode_type:4;
3796+ unsigned int mode:12; /* protection */
3797+ unsigned int uid:8; /* index into uid table */
3798+ unsigned int guid:8; /* index into guid table */
3799+ unsigned short symlink_size;
3800+ char symlink[0];
3801+} __attribute__ ((packed));
3802+
3803+struct squashfs_reg_inode_header_2 {
3804+ unsigned int inode_type:4;
3805+ unsigned int mode:12; /* protection */
3806+ unsigned int uid:8; /* index into uid table */
3807+ unsigned int guid:8; /* index into guid table */
3808+ unsigned int mtime;
3809+ unsigned int start_block;
3810+ unsigned int fragment;
3811+ unsigned int offset;
3812+ unsigned int file_size:32;
3813+ unsigned short block_list[0];
3814+} __attribute__ ((packed));
3815+
3816+struct squashfs_dir_inode_header_2 {
3817+ unsigned int inode_type:4;
3818+ unsigned int mode:12; /* protection */
3819+ unsigned int uid:8; /* index into uid table */
3820+ unsigned int guid:8; /* index into guid table */
3821+ unsigned int file_size:19;
3822+ unsigned int offset:13;
3823+ unsigned int mtime;
3824+ unsigned int start_block:24;
3825+} __attribute__ ((packed));
3826+
3827+struct squashfs_ldir_inode_header_2 {
3828+ unsigned int inode_type:4;
3829+ unsigned int mode:12; /* protection */
3830+ unsigned int uid:8; /* index into uid table */
3831+ unsigned int guid:8; /* index into guid table */
3832+ unsigned int file_size:27;
3833+ unsigned int offset:13;
3834+ unsigned int mtime;
3835+ unsigned int start_block:24;
3836+ unsigned int i_count:16;
3837+ struct squashfs_dir_index_2 index[0];
3838+} __attribute__ ((packed));
3839+
3840+union squashfs_inode_header_2 {
3841+ struct squashfs_base_inode_header_2 base;
3842+ struct squashfs_dev_inode_header_2 dev;
3843+ struct squashfs_symlink_inode_header_2 symlink;
3844+ struct squashfs_reg_inode_header_2 reg;
3845+ struct squashfs_dir_inode_header_2 dir;
3846+ struct squashfs_ldir_inode_header_2 ldir;
3847+ struct squashfs_ipc_inode_header_2 ipc;
3848+};
3849+
3850+struct squashfs_dir_header_2 {
3851+ unsigned int count:8;
3852+ unsigned int start_block:24;
3853+} __attribute__ ((packed));
3854+
3855+struct squashfs_dir_entry_2 {
3856+ unsigned int offset:13;
3857+ unsigned int type:3;
3858+ unsigned int size:8;
3859+ char name[0];
3860+} __attribute__ ((packed));
3861+
3862+struct squashfs_fragment_entry_2 {
3863+ unsigned int start_block;
3864+ unsigned int size;
3865+} __attribute__ ((packed));
3866+
3867+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
3868+ SQUASHFS_MEMSET(s, d, n);\
3869+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
3870+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
3871+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
3872+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
3873+
3874+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
3875+ SQUASHFS_SWAP_START\
3876+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
3877+}
3878+
3879+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
3880+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
3881+
3882+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
3883+ SQUASHFS_SWAP_START\
3884+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
3885+ sizeof(struct squashfs_dev_inode_header_2)); \
3886+ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
3887+}
3888+
3889+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
3890+ SQUASHFS_SWAP_START\
3891+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
3892+ sizeof(struct squashfs_symlink_inode_header_2));\
3893+ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
3894+}
3895+
3896+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
3897+ SQUASHFS_SWAP_START\
3898+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
3899+ sizeof(struct squashfs_reg_inode_header_2));\
3900+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
3901+ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
3902+ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
3903+ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
3904+ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
3905+}
3906+
3907+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
3908+ SQUASHFS_SWAP_START\
3909+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
3910+ sizeof(struct squashfs_dir_inode_header_2));\
3911+ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
3912+ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
3913+ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
3914+ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
3915+}
3916+
3917+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
3918+ SQUASHFS_SWAP_START\
3919+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
3920+ sizeof(struct squashfs_ldir_inode_header_2));\
3921+ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
3922+ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
3923+ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
3924+ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
3925+ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
3926+}
3927+
3928+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
3929+ SQUASHFS_SWAP_START\
3930+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
3931+ SQUASHFS_SWAP((s)->index, d, 0, 27);\
3932+ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
3933+ SQUASHFS_SWAP((s)->size, d, 56, 8);\
3934+}
3935+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
3936+ SQUASHFS_SWAP_START\
3937+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
3938+ SQUASHFS_SWAP((s)->count, d, 0, 8);\
3939+ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
3940+}
3941+
3942+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
3943+ SQUASHFS_SWAP_START\
3944+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
3945+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
3946+ SQUASHFS_SWAP((s)->type, d, 13, 3);\
3947+ SQUASHFS_SWAP((s)->size, d, 16, 8);\
3948+}
3949+
3950+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
3951+ SQUASHFS_SWAP_START\
3952+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
3953+ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
3954+ SQUASHFS_SWAP((s)->size, d, 32, 32);\
3955+}
3956+
3957+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
3958+
3959+/* fragment and fragment table defines */
3960+#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
3961+
3962+#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
3963+ SQUASHFS_METADATA_SIZE)
3964+
3965+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
3966+ SQUASHFS_METADATA_SIZE)
3967+
3968+#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
3969+ SQUASHFS_METADATA_SIZE - 1) / \
3970+ SQUASHFS_METADATA_SIZE)
3971+
3972+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
3973+ sizeof(int))
3974+
3975+#endif
3976+
3977+#ifdef __KERNEL__
3978+
3979+/*
3980+ * macros used to swap each structure entry, taking into account
3981+ * bitfields and different bitfield placing conventions on differing
3982+ * architectures
3983+ */
3984+
3985+#include <asm/byteorder.h>
3986+
3987+#ifdef __BIG_ENDIAN
3988+ /* convert from little endian to big endian */
3989+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
3990+ tbits, b_pos)
3991+#else
3992+ /* convert from big endian to little endian */
3993+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
3994+ tbits, 64 - tbits - b_pos)
3995+#endif
3996+
3997+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
3998+ b_pos = pos % 8;\
3999+ val = 0;\
4000+ s = (unsigned char *)p + (pos / 8);\
4001+ d = ((unsigned char *) &val) + 7;\
4002+ for(bits = 0; bits < (tbits + b_pos); bits += 8) \
4003+ *d-- = *s++;\
4004+ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
4005+}
4006+
4007+#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
4008+
4009+#endif
4010+#endif
4011Index: git/include/linux/squashfs_fs_i.h
4012===================================================================
4013--- /dev/null 1970-01-01 00:00:00.000000000 +0000
4014+++ git/include/linux/squashfs_fs_i.h 2006-10-31 21:26:45.000000000 +0000
4015@@ -0,0 +1,45 @@
4016+#ifndef SQUASHFS_FS_I
4017+#define SQUASHFS_FS_I
4018+/*
4019+ * Squashfs
4020+ *
4021+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
4022+ * Phillip Lougher <phillip@lougher.org.uk>
4023+ *
4024+ * This program is free software; you can redistribute it and/or
4025+ * modify it under the terms of the GNU General Public License
4026+ * as published by the Free Software Foundation; either version 2,
4027+ * or (at your option) any later version.
4028+ *
4029+ * This program is distributed in the hope that it will be useful,
4030+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4031+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4032+ * GNU General Public License for more details.
4033+ *
4034+ * You should have received a copy of the GNU General Public License
4035+ * along with this program; if not, write to the Free Software
4036+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4037+ *
4038+ * squashfs_fs_i.h
4039+ */
4040+
4041+struct squashfs_inode_info {
4042+ long long start_block;
4043+ unsigned int offset;
4044+ union {
4045+ struct {
4046+ long long fragment_start_block;
4047+ unsigned int fragment_size;
4048+ unsigned int fragment_offset;
4049+ long long block_list_start;
4050+ } s1;
4051+ struct {
4052+ long long directory_index_start;
4053+ unsigned int directory_index_offset;
4054+ unsigned int directory_index_count;
4055+ unsigned int parent_inode;
4056+ } s2;
4057+ } u;
4058+ struct inode vfs_inode;
4059+};
4060+#endif
4061Index: git/include/linux/squashfs_fs_sb.h
4062===================================================================
4063--- /dev/null 1970-01-01 00:00:00.000000000 +0000
4064+++ git/include/linux/squashfs_fs_sb.h 2006-10-31 21:26:45.000000000 +0000
4065@@ -0,0 +1,74 @@
4066+#ifndef SQUASHFS_FS_SB
4067+#define SQUASHFS_FS_SB
4068+/*
4069+ * Squashfs
4070+ *
4071+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
4072+ * Phillip Lougher <phillip@lougher.org.uk>
4073+ *
4074+ * This program is free software; you can redistribute it and/or
4075+ * modify it under the terms of the GNU General Public License
4076+ * as published by the Free Software Foundation; either version 2,
4077+ * or (at your option) any later version.
4078+ *
4079+ * This program is distributed in the hope that it will be useful,
4080+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4081+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4082+ * GNU General Public License for more details.
4083+ *
4084+ * You should have received a copy of the GNU General Public License
4085+ * along with this program; if not, write to the Free Software
4086+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4087+ *
4088+ * squashfs_fs_sb.h
4089+ */
4090+
4091+#include <linux/squashfs_fs.h>
4092+
4093+struct squashfs_cache {
4094+ long long block;
4095+ int length;
4096+ long long next_index;
4097+ char *data;
4098+};
4099+
4100+struct squashfs_fragment_cache {
4101+ long long block;
4102+ int length;
4103+ unsigned int locked;
4104+ char *data;
4105+};
4106+
4107+struct squashfs_sb_info {
4108+ struct squashfs_super_block sblk;
4109+ int devblksize;
4110+ int devblksize_log2;
4111+ int swap;
4112+ struct squashfs_cache *block_cache;
4113+ struct squashfs_fragment_cache *fragment;
4114+ int next_cache;
4115+ int next_fragment;
4116+ int next_meta_index;
4117+ unsigned int *uid;
4118+ unsigned int *guid;
4119+ long long *fragment_index;
4120+ unsigned int *fragment_index_2;
4121+ unsigned int read_size;
4122+ char *read_data;
4123+ char *read_page;
4124+ struct semaphore read_data_mutex;
4125+ struct semaphore read_page_mutex;
4126+ struct semaphore block_cache_mutex;
4127+ struct semaphore fragment_mutex;
4128+ struct semaphore meta_index_mutex;
4129+ wait_queue_head_t waitq;
4130+ wait_queue_head_t fragment_wait_queue;
4131+ struct meta_index *meta_index;
4132+ struct inode *(*iget)(struct super_block *s, squashfs_inode_t \
4133+ inode);
4134+ long long (*read_blocklist)(struct inode *inode, int \
4135+ index, int readahead_blks, char *block_list, \
4136+ unsigned short **block_p, unsigned int *bsize);
4137+ int (*read_fragment_index_table)(struct super_block *s);
4138+};
4139+#endif
4140Index: git/init/do_mounts_rd.c
4141===================================================================
4142--- git.orig/init/do_mounts_rd.c 2006-10-31 16:09:47.000000000 +0000
4143+++ git/init/do_mounts_rd.c 2006-10-31 21:26:45.000000000 +0000
4144@@ -5,6 +5,7 @@
4145 #include <linux/ext2_fs.h>
4146 #include <linux/romfs_fs.h>
4147 #include <linux/cramfs_fs.h>
4148+#include <linux/squashfs_fs.h>
4149 #include <linux/initrd.h>
4150 #include <linux/string.h>
4151
4152@@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in
4153 * numbers could not be found.
4154 *
4155 * We currently check for the following magic numbers:
4156+ * squashfs
4157 * minix
4158 * ext2
4159 * romfs
4160@@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start
4161 struct ext2_super_block *ext2sb;
4162 struct romfs_super_block *romfsb;
4163 struct cramfs_super *cramfsb;
4164+ struct squashfs_super_block *squashfsb;
4165 int nblocks = -1;
4166 unsigned char *buf;
4167
4168@@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start
4169 ext2sb = (struct ext2_super_block *) buf;
4170 romfsb = (struct romfs_super_block *) buf;
4171 cramfsb = (struct cramfs_super *) buf;
4172+ squashfsb = (struct squashfs_super_block *) buf;
4173 memset(buf, 0xe5, size);
4174
4175 /*
4176@@ -101,6 +105,15 @@ identify_ramdisk_image(int fd, int start
4177 goto done;
4178 }
4179
4180+ /* squashfs is at block zero too */
4181+ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
4182+ printk(KERN_NOTICE
4183+ "RAMDISK: squashfs filesystem found at block %d\n",
4184+ start_block);
4185+ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
4186+ goto done;
4187+ }
4188+
4189 /*
4190 * Read block 1 to test for minix and ext2 superblock
4191 */