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