diff -urN oldtree/fs/Kconfig newtree/fs/Kconfig
--- oldtree/fs/Kconfig	2006-06-07 15:35:02.249152250 +0000
+++ newtree/fs/Kconfig	2006-06-08 19:34:59.101644750 +0000
@@ -1252,6 +1252,71 @@
 
 	  If unsure, say N.
 
+config SQUASHFS
+	tristate "SquashFS 3.0 - Squashed file system support"
+	select ZLIB_INFLATE
+	help
+	  Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File
+	  System).  Squashfs is a highly compressed read-only filesystem for Linux.
+	  It uses zlib compression to compress both files, inodes and directories.
+	  Inodes in the system are very small and all blocks are packed to minimise
+	  data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
+	  SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full
+	  uid/gid information, hard links and timestamps.
+
+	  Squashfs is intended for general read-only filesystem use, for archival
+	  use (i.e. in cases where a .tar.gz file may be used), and in embedded
+	  systems where low overhead is needed.  Further information and filesystem tools
+	  are available from http://squashfs.sourceforge.net.
+
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>.  The module
+	  will be called squashfs.  Note that the root file system (the one
+	  containing the directory /) cannot be compiled as a module.
+
+	  If unsure, say N.
+
+config SQUASHFS_EMBEDDED
+
+	bool "Additional options for memory-constrained systems" 
+	depends on SQUASHFS
+	default n
+	help
+	  Saying Y here allows you to specify cache sizes and how Squashfs
+	  allocates memory.  This is only intended for memory constrained
+	  systems.
+
+	  If unsure, say N.
+
+config SQUASHFS_FRAGMENT_CACHE_SIZE
+	int "Number of fragments cached" if SQUASHFS_EMBEDDED
+	depends on SQUASHFS
+	default "3"
+	help
+	  By default SquashFS caches the last 3 fragments read from
+	  the filesystem.  Increasing this amount may mean SquashFS
+	  has to re-read fragments less often from disk, at the expense
+	  of extra system memory.  Decreasing this amount will mean
+	  SquashFS uses less memory at the expense of extra reads from disk.
+
+	  Note there must be at least one cached fragment.  Anything
+	  much more than three will probably not make much difference.
+
+config SQUASHFS_VMALLOC
+	bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
+	depends on SQUASHFS
+	default n
+	help
+	  By default SquashFS uses kmalloc to obtain fragment cache memory.
+	  Kmalloc memory is the standard kernel allocator, but it can fail
+	  on memory constrained systems.  Because of the way Vmalloc works,
+	  Vmalloc can succeed when kmalloc fails.  Specifying this option
+	  will make SquashFS always use Vmalloc to allocate the
+	  fragment cache memory.
+
+	  If unsure, say N.
+
 config VXFS_FS
 	tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
 	help
diff -urN oldtree/fs/Makefile newtree/fs/Makefile
--- oldtree/fs/Makefile	2006-06-07 15:35:02.253152500 +0000
+++ newtree/fs/Makefile	2006-06-08 19:34:59.117645750 +0000
@@ -59,6 +59,7 @@
 obj-$(CONFIG_JBD)		+= jbd/
 obj-$(CONFIG_EXT2_FS)		+= ext2/
 obj-$(CONFIG_CRAMFS)		+= cramfs/
+obj-$(CONFIG_SQUASHFS)		+= squashfs/
 obj-$(CONFIG_RAMFS)		+= ramfs/
 obj-$(CONFIG_HUGETLBFS)		+= hugetlbfs/
 obj-$(CONFIG_CODA_FS)		+= coda/
diff -urN oldtree/fs/squashfs/Makefile newtree/fs/squashfs/Makefile
--- oldtree/fs/squashfs/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ newtree/fs/squashfs/Makefile	2006-06-08 17:16:36.000000000 +0000
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux squashfs routines.
+#
+
+obj-$(CONFIG_SQUASHFS) += squashfs.o
+squashfs-y += inode.o
+squashfs-y += squashfs2_0.o
diff -urN oldtree/fs/squashfs/inode.c newtree/fs/squashfs/inode.c
--- oldtree/fs/squashfs/inode.c	1970-01-01 00:00:00.000000000 +0000
+++ newtree/fs/squashfs/inode.c	2006-06-08 17:16:36.000000000 +0000
@@ -0,0 +1,2127 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * inode.c
+ */
+
+#include <linux/types.h>
+#include <linux/squashfs_fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/squashfs_fs_sb.h>
+#include <linux/squashfs_fs_i.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/init.h>
+#include <linux/dcache.h>
+#include <linux/wait.h>
+#include <linux/zlib.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "squashfs.h"
+
+static void squashfs_put_super(struct super_block *);
+static int squashfs_statfs(struct super_block *, struct kstatfs *);
+static int squashfs_symlink_readpage(struct file *file, struct page *page);
+static int squashfs_readpage(struct file *file, struct page *page);
+static int squashfs_readpage4K(struct file *file, struct page *page);
+static int squashfs_readdir(struct file *, void *, filldir_t);
+static struct inode *squashfs_alloc_inode(struct super_block *sb);
+static void squashfs_destroy_inode(struct inode *inode);
+static int init_inodecache(void);
+static void destroy_inodecache(void);
+static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
+				struct nameidata *);
+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
+static long long read_blocklist(struct inode *inode, int index,
+				int readahead_blks, char *block_list,
+				unsigned short **block_p, unsigned int *bsize);
+static struct super_block *squashfs_get_sb(struct file_system_type *, int,
+				const char *, void *);
+
+
+static z_stream stream;
+
+static struct file_system_type squashfs_fs_type = {
+	.owner = THIS_MODULE,
+	.name = "squashfs",
+	.get_sb = squashfs_get_sb,
+	.kill_sb = kill_block_super,
+	.fs_flags = FS_REQUIRES_DEV
+};
+
+static unsigned char squashfs_filetype_table[] = {
+	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
+};
+
+static struct super_operations squashfs_ops = {
+	.alloc_inode = squashfs_alloc_inode,
+	.destroy_inode = squashfs_destroy_inode,
+	.statfs = squashfs_statfs,
+	.put_super = squashfs_put_super,
+};
+
+SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
+	.readpage = squashfs_symlink_readpage
+};
+
+SQSH_EXTERN struct address_space_operations squashfs_aops = {
+	.readpage = squashfs_readpage
+};
+
+SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
+	.readpage = squashfs_readpage4K
+};
+
+static struct file_operations squashfs_dir_ops = {
+	.read = generic_read_dir,
+	.readdir = squashfs_readdir
+};
+
+SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
+	.lookup = squashfs_lookup
+};
+
+
+static struct buffer_head *get_block_length(struct super_block *s,
+				int *cur_index, int *offset, int *c_byte)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	unsigned short temp;
+	struct buffer_head *bh;
+
+	if (!(bh = sb_bread(s, *cur_index)))
+		goto out;
+
+	if (msblk->devblksize - *offset == 1) {
+		if (msblk->swap)
+			((unsigned char *) &temp)[1] = *((unsigned char *)
+				(bh->b_data + *offset));
+		else
+			((unsigned char *) &temp)[0] = *((unsigned char *)
+				(bh->b_data + *offset));
+		brelse(bh);
+		if (!(bh = sb_bread(s, ++(*cur_index))))
+			goto out;
+		if (msblk->swap)
+			((unsigned char *) &temp)[0] = *((unsigned char *)
+				bh->b_data); 
+		else
+			((unsigned char *) &temp)[1] = *((unsigned char *)
+				bh->b_data); 
+		*c_byte = temp;
+		*offset = 1;
+	} else {
+		if (msblk->swap) {
+			((unsigned char *) &temp)[1] = *((unsigned char *)
+				(bh->b_data + *offset));
+			((unsigned char *) &temp)[0] = *((unsigned char *)
+				(bh->b_data + *offset + 1)); 
+		} else {
+			((unsigned char *) &temp)[0] = *((unsigned char *)
+				(bh->b_data + *offset));
+			((unsigned char *) &temp)[1] = *((unsigned char *)
+				(bh->b_data + *offset + 1)); 
+		}
+		*c_byte = temp;
+		*offset += 2;
+	}
+
+	if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
+		if (*offset == msblk->devblksize) {
+			brelse(bh);
+			if (!(bh = sb_bread(s, ++(*cur_index))))
+				goto out;
+			*offset = 0;
+		}
+		if (*((unsigned char *) (bh->b_data + *offset)) !=
+						SQUASHFS_MARKER_BYTE) {
+			ERROR("Metadata block marker corrupt @ %x\n",
+						*cur_index);
+			brelse(bh);
+			goto out;
+		}
+		(*offset)++;
+	}
+	return bh;
+
+out:
+	return NULL;
+}
+
+
+SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+			long long index, unsigned int length,
+			long long *next_index)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
+			msblk->devblksize_log2) + 2];
+	unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
+	unsigned int cur_index = index >> msblk->devblksize_log2;
+	int bytes, avail_bytes, b = 0, k;
+	char *c_buffer;
+	unsigned int compressed;
+	unsigned int c_byte = length;
+
+	if (c_byte) {
+		bytes = msblk->devblksize - offset;
+		compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
+		c_buffer = compressed ? msblk->read_data : buffer;
+		c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
+
+		TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
+					? "" : "un", (unsigned int) c_byte);
+
+		if (!(bh[0] = sb_getblk(s, cur_index)))
+			goto block_release;
+
+		for (b = 1; bytes < c_byte; b++) {
+			if (!(bh[b] = sb_getblk(s, ++cur_index)))
+				goto block_release;
+			bytes += msblk->devblksize;
+		}
+		ll_rw_block(READ, b, bh);
+	} else {
+		if (!(bh[0] = get_block_length(s, &cur_index, &offset,
+								&c_byte)))
+			goto read_failure;
+
+		bytes = msblk->devblksize - offset;
+		compressed = SQUASHFS_COMPRESSED(c_byte);
+		c_buffer = compressed ? msblk->read_data : buffer;
+		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
+
+		TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
+					? "" : "un", (unsigned int) c_byte);
+
+		for (b = 1; bytes < c_byte; b++) {
+			if (!(bh[b] = sb_getblk(s, ++cur_index)))
+				goto block_release;
+			bytes += msblk->devblksize;
+		}
+		ll_rw_block(READ, b - 1, bh + 1);
+	}
+
+	if (compressed)
+		down(&msblk->read_data_mutex);
+
+	for (bytes = 0, k = 0; k < b; k++) {
+		avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
+					msblk->devblksize - offset :
+					c_byte - bytes;
+		wait_on_buffer(bh[k]);
+		if (!buffer_uptodate(bh[k]))
+			goto block_release;
+		memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
+		bytes += avail_bytes;
+		offset = 0;
+		brelse(bh[k]);
+	}
+
+	/*
+	 * uncompress block
+	 */
+	if (compressed) {
+		int zlib_err;
+
+		stream.next_in = c_buffer;
+		stream.avail_in = c_byte;
+		stream.next_out = buffer;
+		stream.avail_out = msblk->read_size;
+
+		if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
+				((zlib_err = zlib_inflate(&stream, Z_FINISH))
+				 != Z_STREAM_END) || ((zlib_err =
+				zlib_inflateEnd(&stream)) != Z_OK)) {
+			ERROR("zlib_fs returned unexpected result 0x%x\n",
+				zlib_err);
+			bytes = 0;
+		} else
+			bytes = stream.total_out;
+		
+		up(&msblk->read_data_mutex);
+	}
+
+	if (next_index)
+		*next_index = index + c_byte + (length ? 0 :
+				(SQUASHFS_CHECK_DATA(msblk->sblk.flags)
+				 ? 3 : 2));
+	return bytes;
+
+block_release:
+	while (--b >= 0)
+		brelse(bh[b]);
+
+read_failure:
+	ERROR("sb_bread failed reading block 0x%x\n", cur_index);
+	return 0;
+}
+
+
+SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
+				long long block, unsigned int offset,
+				int length, long long *next_block,
+				unsigned int *next_offset)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	int n, i, bytes, return_length = length;
+	long long next_index;
+
+	TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
+
+	while ( 1 ) {
+		for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 
+			if (msblk->block_cache[i].block == block)
+				break; 
+		
+		down(&msblk->block_cache_mutex);
+
+		if (i == SQUASHFS_CACHED_BLKS) {
+			/* read inode header block */
+			for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
+					n ; n --, i = (i + 1) %
+					SQUASHFS_CACHED_BLKS)
+				if (msblk->block_cache[i].block !=
+							SQUASHFS_USED_BLK)
+					break;
+
+			if (n == 0) {
+				wait_queue_t wait;
+
+				init_waitqueue_entry(&wait, current);
+				add_wait_queue(&msblk->waitq, &wait);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+ 				up(&msblk->block_cache_mutex);
+				schedule();
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&msblk->waitq, &wait);
+				continue;
+			}
+			msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
+
+			if (msblk->block_cache[i].block ==
+							SQUASHFS_INVALID_BLK) {
+				if (!(msblk->block_cache[i].data =
+						kmalloc(SQUASHFS_METADATA_SIZE,
+						GFP_KERNEL))) {
+					ERROR("Failed to allocate cache"
+							"block\n");
+					up(&msblk->block_cache_mutex);
+					goto out;
+				}
+			}
+	
+			msblk->block_cache[i].block = SQUASHFS_USED_BLK;
+			up(&msblk->block_cache_mutex);
+
+			if (!(msblk->block_cache[i].length =
+						squashfs_read_data(s,
+						msblk->block_cache[i].data,
+						block, 0, &next_index))) {
+				ERROR("Unable to read cache block [%llx:%x]\n",
+						block, offset);
+				goto out;
+			}
+
+			down(&msblk->block_cache_mutex);
+			wake_up(&msblk->waitq);
+			msblk->block_cache[i].block = block;
+			msblk->block_cache[i].next_index = next_index;
+			TRACE("Read cache block [%llx:%x]\n", block, offset);
+		}
+
+		if (msblk->block_cache[i].block != block) {
+			up(&msblk->block_cache_mutex);
+			continue;
+		}
+
+		if ((bytes = msblk->block_cache[i].length - offset) >= length) {
+			if (buffer)
+				memcpy(buffer, msblk->block_cache[i].data +
+						offset, length);
+			if (msblk->block_cache[i].length - offset == length) {
+				*next_block = msblk->block_cache[i].next_index;
+				*next_offset = 0;
+			} else {
+				*next_block = block;
+				*next_offset = offset + length;
+			}
+			up(&msblk->block_cache_mutex);
+			goto finish;
+		} else {
+			if (buffer) {
+				memcpy(buffer, msblk->block_cache[i].data +
+						offset, bytes);
+				buffer += bytes;
+			}
+			block = msblk->block_cache[i].next_index;
+			up(&msblk->block_cache_mutex);
+			length -= bytes;
+			offset = 0;
+		}
+	}
+
+finish:
+	return return_length;
+out:
+	return 0;
+}
+
+
+static int get_fragment_location(struct super_block *s, unsigned int fragment,
+				long long *fragment_start_block,
+				unsigned int *fragment_size)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	long long start_block =
+		msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
+	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
+	struct squashfs_fragment_entry fragment_entry;
+
+	if (msblk->swap) {
+		struct squashfs_fragment_entry sfragment_entry;
+
+		if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
+					start_block, offset,
+					sizeof(sfragment_entry), &start_block,
+					&offset))
+			goto out;
+		SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
+	} else
+		if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
+					start_block, offset,
+					sizeof(fragment_entry), &start_block,
+					&offset))
+			goto out;
+
+	*fragment_start_block = fragment_entry.start_block;
+	*fragment_size = fragment_entry.size;
+
+	return 1;
+
+out:
+	return 0;
+}
+
+
+SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
+					squashfs_fragment_cache *fragment)
+{
+	down(&msblk->fragment_mutex);
+	fragment->locked --;
+	wake_up(&msblk->fragment_wait_queue);
+	up(&msblk->fragment_mutex);
+}
+
+
+SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
+					*s, long long start_block,
+					int length)
+{
+	int i, n;
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+
+	while ( 1 ) {
+		down(&msblk->fragment_mutex);
+
+		for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
+				msblk->fragment[i].block != start_block; i++);
+
+		if (i == SQUASHFS_CACHED_FRAGMENTS) {
+			for (i = msblk->next_fragment, n =
+				SQUASHFS_CACHED_FRAGMENTS; n &&
+				msblk->fragment[i].locked; n--, i = (i + 1) %
+				SQUASHFS_CACHED_FRAGMENTS);
+
+			if (n == 0) {
+				wait_queue_t wait;
+
+				init_waitqueue_entry(&wait, current);
+				add_wait_queue(&msblk->fragment_wait_queue,
+									&wait);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				up(&msblk->fragment_mutex);
+				schedule();
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&msblk->fragment_wait_queue,
+									&wait);
+				continue;
+			}
+			msblk->next_fragment = (msblk->next_fragment + 1) %
+				SQUASHFS_CACHED_FRAGMENTS;
+			
+			if (msblk->fragment[i].data == NULL)
+				if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
+						(SQUASHFS_FILE_MAX_SIZE))) {
+					ERROR("Failed to allocate fragment "
+							"cache block\n");
+					up(&msblk->fragment_mutex);
+					goto out;
+				}
+
+			msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
+			msblk->fragment[i].locked = 1;
+			up(&msblk->fragment_mutex);
+
+			if (!(msblk->fragment[i].length = squashfs_read_data(s,
+						msblk->fragment[i].data,
+						start_block, length, NULL))) {
+				ERROR("Unable to read fragment cache block "
+							"[%llx]\n", start_block);
+				msblk->fragment[i].locked = 0;
+				goto out;
+			}
+
+			msblk->fragment[i].block = start_block;
+			TRACE("New fragment %d, start block %lld, locked %d\n",
+						i, msblk->fragment[i].block,
+						msblk->fragment[i].locked);
+			break;
+		}
+
+		msblk->fragment[i].locked++;
+		up(&msblk->fragment_mutex);
+		TRACE("Got fragment %d, start block %lld, locked %d\n", i,
+						msblk->fragment[i].block,
+						msblk->fragment[i].locked);
+		break;
+	}
+
+	return &msblk->fragment[i];
+
+out:
+	return NULL;
+}
+
+
+static struct inode *squashfs_new_inode(struct super_block *s,
+		struct squashfs_base_inode_header *inodeb)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct inode *i = new_inode(s);
+
+	if (i) {
+		i->i_ino = inodeb->inode_number;
+		i->i_mtime.tv_sec = inodeb->mtime;
+		i->i_atime.tv_sec = inodeb->mtime;
+		i->i_ctime.tv_sec = inodeb->mtime;
+		i->i_uid = msblk->uid[inodeb->uid];
+		i->i_mode = inodeb->mode;
+		i->i_size = 0;
+		if (inodeb->guid == SQUASHFS_GUIDS)
+			i->i_gid = i->i_uid;
+		else
+			i->i_gid = msblk->guid[inodeb->guid];
+	}
+
+	return i;
+}
+
+
+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
+{
+	struct inode *i;
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	long long block = SQUASHFS_INODE_BLK(inode) +
+		sblk->inode_table_start;
+	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+	long long next_block;
+	unsigned int next_offset;
+	union squashfs_inode_header id, sid;
+	struct squashfs_base_inode_header *inodeb = &id.base,
+					  *sinodeb = &sid.base;
+
+	TRACE("Entered squashfs_iget\n");
+
+	if (msblk->swap) {
+		if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
+					offset, sizeof(*sinodeb), &next_block,
+					&next_offset))
+			goto failed_read;
+		SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
+					sizeof(*sinodeb));
+	} else
+		if (!squashfs_get_cached_block(s, (char *) inodeb, block,
+					offset, sizeof(*inodeb), &next_block,
+					&next_offset))
+			goto failed_read;
+
+	switch(inodeb->inode_type) {
+		case SQUASHFS_FILE_TYPE: {
+			unsigned int frag_size;
+			long long frag_blk;
+			struct squashfs_reg_inode_header *inodep = &id.reg;
+			struct squashfs_reg_inode_header *sinodep = &sid.reg;
+				
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			frag_blk = SQUASHFS_INVALID_BLK;
+			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
+					!get_fragment_location(s,
+					inodep->fragment, &frag_blk, &frag_size))
+				goto failed_read;
+				
+			if((i = squashfs_new_inode(s, inodeb)) == NULL)
+				goto failed_read1;
+
+			i->i_nlink = 1;
+			i->i_size = inodep->file_size;
+			i->i_fop = &generic_ro_fops;
+			i->i_mode |= S_IFREG;
+			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+			i->i_blksize = PAGE_CACHE_SIZE;
+			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
+			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
+			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
+			SQUASHFS_I(i)->start_block = inodep->start_block;
+			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+			if (sblk->block_size > 4096)
+				i->i_data.a_ops = &squashfs_aops;
+			else
+				i->i_data.a_ops = &squashfs_aops_4K;
+
+			TRACE("File inode %x:%x, start_block %llx, "
+					"block_list_start %llx, offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					inodep->start_block, next_block,
+					next_offset);
+			break;
+		}
+		case SQUASHFS_LREG_TYPE: {
+			unsigned int frag_size;
+			long long frag_blk;
+			struct squashfs_lreg_inode_header *inodep = &id.lreg;
+			struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
+				
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			frag_blk = SQUASHFS_INVALID_BLK;
+			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
+					!get_fragment_location(s,
+					inodep->fragment, &frag_blk, &frag_size))
+				goto failed_read;
+				
+			if((i = squashfs_new_inode(s, inodeb)) == NULL)
+				goto failed_read1;
+
+			i->i_nlink = inodep->nlink;
+			i->i_size = inodep->file_size;
+			i->i_fop = &generic_ro_fops;
+			i->i_mode |= S_IFREG;
+			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+			i->i_blksize = PAGE_CACHE_SIZE;
+			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
+			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
+			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
+			SQUASHFS_I(i)->start_block = inodep->start_block;
+			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+			if (sblk->block_size > 4096)
+				i->i_data.a_ops = &squashfs_aops;
+			else
+				i->i_data.a_ops = &squashfs_aops_4K;
+
+			TRACE("File inode %x:%x, start_block %llx, "
+					"block_list_start %llx, offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					inodep->start_block, next_block,
+					next_offset);
+			break;
+		}
+		case SQUASHFS_DIR_TYPE: {
+			struct squashfs_dir_inode_header *inodep = &id.dir;
+			struct squashfs_dir_inode_header *sinodep = &sid.dir;
+
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if((i = squashfs_new_inode(s, inodeb)) == NULL)
+				goto failed_read1;
+
+			i->i_nlink = inodep->nlink;
+			i->i_size = inodep->file_size;
+			i->i_op = &squashfs_dir_inode_ops;
+			i->i_fop = &squashfs_dir_ops;
+			i->i_mode |= S_IFDIR;
+			SQUASHFS_I(i)->start_block = inodep->start_block;
+			SQUASHFS_I(i)->offset = inodep->offset;
+			SQUASHFS_I(i)->u.s2.directory_index_count = 0;
+			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
+
+			TRACE("Directory inode %x:%x, start_block %x, offset "
+					"%x\n", SQUASHFS_INODE_BLK(inode),
+					offset, inodep->start_block,
+					inodep->offset);
+			break;
+		}
+		case SQUASHFS_LDIR_TYPE: {
+			struct squashfs_ldir_inode_header *inodep = &id.ldir;
+			struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
+
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
+						sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if((i = squashfs_new_inode(s, inodeb)) == NULL)
+				goto failed_read1;
+
+			i->i_nlink = inodep->nlink;
+			i->i_size = inodep->file_size;
+			i->i_op = &squashfs_dir_inode_ops;
+			i->i_fop = &squashfs_dir_ops;
+			i->i_mode |= S_IFDIR;
+			SQUASHFS_I(i)->start_block = inodep->start_block;
+			SQUASHFS_I(i)->offset = inodep->offset;
+			SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
+			SQUASHFS_I(i)->u.s2.directory_index_offset =
+								next_offset;
+			SQUASHFS_I(i)->u.s2.directory_index_count =
+								inodep->i_count;
+			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
+
+			TRACE("Long directory inode %x:%x, start_block %x, "
+					"offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					inodep->start_block, inodep->offset);
+			break;
+		}
+		case SQUASHFS_SYMLINK_TYPE: {
+			struct squashfs_symlink_inode_header *inodep =
+								&id.symlink;
+			struct squashfs_symlink_inode_header *sinodep =
+								&sid.symlink;
+	
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
+								sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if((i = squashfs_new_inode(s, inodeb)) == NULL)
+				goto failed_read1;
+
+			i->i_nlink = inodep->nlink;
+			i->i_size = inodep->symlink_size;
+			i->i_op = &page_symlink_inode_operations;
+			i->i_data.a_ops = &squashfs_symlink_aops;
+			i->i_mode |= S_IFLNK;
+			SQUASHFS_I(i)->start_block = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+
+			TRACE("Symbolic link inode %x:%x, start_block %llx, "
+					"offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					next_block, next_offset);
+			break;
+		 }
+		 case SQUASHFS_BLKDEV_TYPE:
+		 case SQUASHFS_CHRDEV_TYPE: {
+			struct squashfs_dev_inode_header *inodep = &id.dev;
+			struct squashfs_dev_inode_header *sinodep = &sid.dev;
+
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
+			} else	
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if ((i = squashfs_new_inode(s, inodeb)) == NULL)
+				goto failed_read1;
+
+			i->i_nlink = inodep->nlink;
+			i->i_mode |= (inodeb->inode_type ==
+					SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
+					S_IFBLK;
+			init_special_inode(i, i->i_mode,
+					old_decode_dev(inodep->rdev));
+
+			TRACE("Device inode %x:%x, rdev %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					inodep->rdev);
+			break;
+		 }
+		 case SQUASHFS_FIFO_TYPE:
+		 case SQUASHFS_SOCKET_TYPE: {
+			struct squashfs_ipc_inode_header *inodep = &id.ipc;
+			struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
+
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
+			} else	
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if ((i = squashfs_new_inode(s, inodeb)) == NULL)
+				goto failed_read1;
+
+			i->i_nlink = inodep->nlink;
+			i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
+							? S_IFIFO : S_IFSOCK;
+			init_special_inode(i, i->i_mode, 0);
+			break;
+		 }
+		 default:
+			ERROR("Unknown inode type %d in squashfs_iget!\n",
+					inodeb->inode_type);
+			goto failed_read1;
+	}
+	
+	insert_inode_hash(i);
+	return i;
+
+failed_read:
+	ERROR("Unable to read inode [%llx:%x]\n", block, offset);
+
+failed_read1:
+	return NULL;
+}
+
+
+static int read_fragment_index_table(struct super_block *s)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+
+	/* Allocate fragment index table */
+	if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
+					(sblk->fragments), GFP_KERNEL))) {
+		ERROR("Failed to allocate uid/gid table\n");
+		return 0;
+	}
+   
+	if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
+					!squashfs_read_data(s, (char *)
+					msblk->fragment_index,
+					sblk->fragment_table_start,
+					SQUASHFS_FRAGMENT_INDEX_BYTES
+					(sblk->fragments) |
+					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+		ERROR("unable to read fragment index table\n");
+		return 0;
+	}
+
+	if (msblk->swap) {
+		int i;
+		long long fragment;
+
+		for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
+									i++) {
+			SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
+						&msblk->fragment_index[i], 1);
+			msblk->fragment_index[i] = fragment;
+		}
+	}
+
+	return 1;
+}
+
+
+static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
+{
+	struct squashfs_super_block *sblk = &msblk->sblk;
+
+	msblk->iget = squashfs_iget;
+	msblk->read_blocklist = read_blocklist;
+	msblk->read_fragment_index_table = read_fragment_index_table;
+
+	if (sblk->s_major == 1) {
+		if (!squashfs_1_0_supported(msblk)) {
+			SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
+				"are unsupported\n");
+			SERROR("Please recompile with "
+				"Squashfs 1.0 support enabled\n");
+			return 0;
+		}
+	} else if (sblk->s_major == 2) {
+		if (!squashfs_2_0_supported(msblk)) {
+			SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
+				"are unsupported\n");
+			SERROR("Please recompile with "
+				"Squashfs 2.0 support enabled\n");
+			return 0;
+		}
+	} else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
+			SQUASHFS_MINOR) {
+		SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
+				"filesystem\n", sblk->s_major, sblk->s_minor);
+		SERROR("Please update your kernel\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+
+static int squashfs_fill_super(struct super_block *s, void *data, int silent)
+{
+	struct squashfs_sb_info *msblk;
+	struct squashfs_super_block *sblk;
+	int i;
+	char b[BDEVNAME_SIZE];
+	struct inode *root;
+
+	TRACE("Entered squashfs_read_superblock\n");
+
+	if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
+						GFP_KERNEL))) {
+		ERROR("Failed to allocate superblock\n");
+		goto failure;
+	}
+	memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
+	msblk = s->s_fs_info;
+	sblk = &msblk->sblk;
+	
+	msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
+	msblk->devblksize_log2 = ffz(~msblk->devblksize);
+
+	init_MUTEX(&msblk->read_data_mutex);
+	init_MUTEX(&msblk->read_page_mutex);
+	init_MUTEX(&msblk->block_cache_mutex);
+	init_MUTEX(&msblk->fragment_mutex);
+	init_MUTEX(&msblk->meta_index_mutex);
+	
+	init_waitqueue_head(&msblk->waitq);
+	init_waitqueue_head(&msblk->fragment_wait_queue);
+
+	if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
+					sizeof(struct squashfs_super_block) |
+					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+		SERROR("unable to read superblock\n");
+		goto failed_mount;
+	}
+
+	/* Check it is a SQUASHFS superblock */
+	msblk->swap = 0;
+	if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
+		if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
+			struct squashfs_super_block ssblk;
+
+			WARNING("Mounting a different endian SQUASHFS "
+				"filesystem on %s\n", bdevname(s->s_bdev, b));
+
+			SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
+			memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
+			msblk->swap = 1;
+		} else  {
+			SERROR("Can't find a SQUASHFS superblock on %s\n",
+							bdevname(s->s_bdev, b));
+			goto failed_mount;
+		}
+	}
+
+	/* Check the MAJOR & MINOR versions */
+	if(!supported_squashfs_filesystem(msblk, silent))
+		goto failed_mount;
+
+	TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
+	TRACE("Inodes are %scompressed\n",
+					SQUASHFS_UNCOMPRESSED_INODES
+					(sblk->flags) ? "un" : "");
+	TRACE("Data is %scompressed\n",
+					SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
+					? "un" : "");
+	TRACE("Check data is %s present in the filesystem\n",
+					SQUASHFS_CHECK_DATA(sblk->flags) ?
+					"" : "not");
+	TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
+	TRACE("Block size %d\n", sblk->block_size);
+	TRACE("Number of inodes %d\n", sblk->inodes);
+	if (sblk->s_major > 1)
+		TRACE("Number of fragments %d\n", sblk->fragments);
+	TRACE("Number of uids %d\n", sblk->no_uids);
+	TRACE("Number of gids %d\n", sblk->no_guids);
+	TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
+	TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
+	if (sblk->s_major > 1)
+		TRACE("sblk->fragment_table_start %llx\n",
+					sblk->fragment_table_start);
+	TRACE("sblk->uid_start %llx\n", sblk->uid_start);
+
+	s->s_flags |= MS_RDONLY;
+	s->s_op = &squashfs_ops;
+
+	/* Init inode_table block pointer array */
+	if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
+					SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
+		ERROR("Failed to allocate block cache\n");
+		goto failed_mount;
+	}
+
+	for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
+		msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
+
+	msblk->next_cache = 0;
+
+	/* Allocate read_data block */
+	msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
+					SQUASHFS_METADATA_SIZE :
+					sblk->block_size;
+
+	if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
+		ERROR("Failed to allocate read_data block\n");
+		goto failed_mount;
+	}
+
+	/* Allocate read_page block */
+	if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
+		ERROR("Failed to allocate read_page block\n");
+		goto failed_mount;
+	}
+
+	/* Allocate uid and gid tables */
+	if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
+					sizeof(unsigned int), GFP_KERNEL))) {
+		ERROR("Failed to allocate uid/gid table\n");
+		goto failed_mount;
+	}
+	msblk->guid = msblk->uid + sblk->no_uids;
+   
+	if (msblk->swap) {
+		unsigned int suid[sblk->no_uids + sblk->no_guids];
+
+		if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
+					((sblk->no_uids + sblk->no_guids) *
+					 sizeof(unsigned int)) |
+					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+			ERROR("unable to read uid/gid table\n");
+			goto failed_mount;
+		}
+
+		SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
+			sblk->no_guids), (sizeof(unsigned int) * 8));
+	} else
+		if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
+					((sblk->no_uids + sblk->no_guids) *
+					 sizeof(unsigned int)) |
+					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+			ERROR("unable to read uid/gid table\n");
+			goto failed_mount;
+		}
+
+
+	if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
+		goto allocate_root;
+
+	if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
+				SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
+		ERROR("Failed to allocate fragment block cache\n");
+		goto failed_mount;
+	}
+
+	for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
+		msblk->fragment[i].locked = 0;
+		msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
+		msblk->fragment[i].data = NULL;
+	}
+
+	msblk->next_fragment = 0;
+
+	/* Allocate fragment index table */
+	if (msblk->read_fragment_index_table(s) == 0)
+		goto failed_mount;
+
+allocate_root:
+	if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
+		goto failed_mount;
+
+	if ((s->s_root = d_alloc_root(root)) == NULL) {
+		ERROR("Root inode create failed\n");
+		iput(root);
+		goto failed_mount;
+	}
+
+	TRACE("Leaving squashfs_read_super\n");
+	return 0;
+
+failed_mount:
+	kfree(msblk->fragment_index);
+	kfree(msblk->fragment);
+	kfree(msblk->uid);
+	kfree(msblk->read_page);
+	kfree(msblk->read_data);
+	kfree(msblk->block_cache);
+	kfree(msblk->fragment_index_2);
+	kfree(s->s_fs_info);
+	s->s_fs_info = NULL;
+	return -EINVAL;
+
+failure:
+	return -ENOMEM;
+}
+
+
+static int squashfs_statfs(struct super_block *s, struct kstatfs *buf)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+
+	TRACE("Entered squashfs_statfs\n");
+
+	buf->f_type = SQUASHFS_MAGIC;
+	buf->f_bsize = sblk->block_size;
+	buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
+	buf->f_bfree = buf->f_bavail = 0;
+	buf->f_files = sblk->inodes;
+	buf->f_ffree = 0;
+	buf->f_namelen = SQUASHFS_NAME_LEN;
+
+	return 0;
+}
+
+
+static int squashfs_symlink_readpage(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
+	long long block = SQUASHFS_I(inode)->start_block;
+	int offset = SQUASHFS_I(inode)->offset;
+	void *pageaddr = kmap(page);
+
+	TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
+				"%llx, offset %x\n", page->index,
+				SQUASHFS_I(inode)->start_block,
+				SQUASHFS_I(inode)->offset);
+
+	for (length = 0; length < index; length += bytes) {
+		if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
+				block, offset, PAGE_CACHE_SIZE, &block,
+				&offset))) {
+			ERROR("Unable to read symbolic link [%llx:%x]\n", block,
+					offset);
+			goto skip_read;
+		}
+	}
+
+	if (length != index) {
+		ERROR("(squashfs_symlink_readpage) length != index\n");
+		bytes = 0;
+		goto skip_read;
+	}
+
+	bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
+					i_size_read(inode) - length;
+
+	if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
+					offset, bytes, &block, &offset)))
+		ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
+
+skip_read:
+	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
+	kunmap(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+
+	return 0;
+}
+
+
+struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
+{
+	struct meta_index *meta = NULL;
+	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	int i;
+
+	down(&msblk->meta_index_mutex);
+
+	TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
+
+	if(msblk->meta_index == NULL)
+		goto not_allocated;
+
+	for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
+		if (msblk->meta_index[i].inode_number == inode->i_ino &&
+				msblk->meta_index[i].offset >= offset &&
+				msblk->meta_index[i].offset <= index &&
+				msblk->meta_index[i].locked == 0) {
+			TRACE("locate_meta_index: entry %d, offset %d\n", i,
+					msblk->meta_index[i].offset);
+			meta = &msblk->meta_index[i];
+			offset = meta->offset;
+		}
+
+	if (meta)
+		meta->locked = 1;
+
+not_allocated:
+	up(&msblk->meta_index_mutex);
+
+	return meta;
+}
+
+
+struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
+{
+	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	struct meta_index *meta = NULL;
+	int i;
+
+	down(&msblk->meta_index_mutex);
+
+	TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
+
+	if(msblk->meta_index == NULL) {
+		if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
+					SQUASHFS_META_NUMBER, GFP_KERNEL))) {
+			ERROR("Failed to allocate meta_index\n");
+			goto failed;
+		}
+		for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
+			msblk->meta_index[i].inode_number = 0;
+			msblk->meta_index[i].locked = 0;
+		}
+		msblk->next_meta_index = 0;
+	}
+
+	for(i = SQUASHFS_META_NUMBER; i &&
+			msblk->meta_index[msblk->next_meta_index].locked; i --)
+		msblk->next_meta_index = (msblk->next_meta_index + 1) %
+			SQUASHFS_META_NUMBER;
+
+	if(i == 0) {
+		TRACE("empty_meta_index: failed!\n");
+		goto failed;
+	}
+
+	TRACE("empty_meta_index: returned meta entry %d, %p\n",
+			msblk->next_meta_index,
+			&msblk->meta_index[msblk->next_meta_index]);
+
+	meta = &msblk->meta_index[msblk->next_meta_index];
+	msblk->next_meta_index = (msblk->next_meta_index + 1) %
+			SQUASHFS_META_NUMBER;
+
+	meta->inode_number = inode->i_ino;
+	meta->offset = offset;
+	meta->skip = skip;
+	meta->entries = 0;
+	meta->locked = 1;
+
+failed:
+	up(&msblk->meta_index_mutex);
+	return meta;
+}
+
+
+void release_meta_index(struct inode *inode, struct meta_index *meta)
+{
+	meta->locked = 0;
+}
+
+
+static int read_block_index(struct super_block *s, int blocks, char *block_list,
+		long long *start_block, int *offset)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	unsigned int *block_listp;
+	int block = 0;
+	
+	if (msblk->swap) {
+		char sblock_list[blocks << 2];
+
+		if (!squashfs_get_cached_block(s, sblock_list, *start_block,
+				*offset, blocks << 2, start_block, offset)) {
+			ERROR("Unable to read block list [%llx:%x]\n",
+				*start_block, *offset);
+			goto failure;
+		}
+		SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
+				((unsigned int *)sblock_list), blocks);
+	} else
+		if (!squashfs_get_cached_block(s, block_list, *start_block,
+				*offset, blocks << 2, start_block, offset)) {
+			ERROR("Unable to read block list [%llx:%x]\n",
+				*start_block, *offset);
+			goto failure;
+		}
+
+	for (block_listp = (unsigned int *) block_list; blocks;
+				block_listp++, blocks --)
+		block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
+
+	return block;
+
+failure:
+	return -1;
+}
+
+
+#define SIZE 256
+
+static inline int calculate_skip(int blocks) {
+	int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
+	return skip >= 7 ? 7 : skip + 1;
+}
+
+
+static int get_meta_index(struct inode *inode, int index,
+		long long *index_block, int *index_offset,
+		long long *data_block, char *block_list)
+{
+	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
+	int offset = 0;
+	struct meta_index *meta;
+	struct meta_entry *meta_entry;
+	long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
+	int cur_offset = SQUASHFS_I(inode)->offset;
+	long long cur_data_block = SQUASHFS_I(inode)->start_block;
+	int i;
+ 
+	index /= SQUASHFS_META_INDEXES * skip;
+
+	while ( offset < index ) {
+		meta = locate_meta_index(inode, index, offset + 1);
+
+		if (meta == NULL) {
+			if ((meta = empty_meta_index(inode, offset + 1,
+							skip)) == NULL)
+				goto all_done;
+		} else {
+			offset = index < meta->offset + meta->entries ? index :
+				meta->offset + meta->entries - 1;
+			meta_entry = &meta->meta_entry[offset - meta->offset];
+			cur_index_block = meta_entry->index_block + sblk->inode_table_start;
+			cur_offset = meta_entry->offset;
+			cur_data_block = meta_entry->data_block;
+			TRACE("get_meta_index: offset %d, meta->offset %d, "
+				"meta->entries %d\n", offset, meta->offset,
+				meta->entries);
+			TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
+				" data_block 0x%llx\n", cur_index_block,
+				cur_offset, cur_data_block);
+		}
+
+		for (i = meta->offset + meta->entries; i <= index &&
+				i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
+			int blocks = skip * SQUASHFS_META_INDEXES;
+
+			while (blocks) {
+				int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
+					blocks;
+				int res = read_block_index(inode->i_sb, block,
+					block_list, &cur_index_block,
+					&cur_offset);
+
+				if (res == -1)
+					goto failed;
+
+				cur_data_block += res;
+				blocks -= block;
+			}
+
+			meta_entry = &meta->meta_entry[i - meta->offset];
+			meta_entry->index_block = cur_index_block - sblk->inode_table_start;
+			meta_entry->offset = cur_offset;
+			meta_entry->data_block = cur_data_block;
+			meta->entries ++;
+			offset ++;
+		}
+
+		TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
+				meta->offset, meta->entries);
+
+		release_meta_index(inode, meta);
+	}
+
+all_done:
+	*index_block = cur_index_block;
+	*index_offset = cur_offset;
+	*data_block = cur_data_block;
+
+	return offset * SQUASHFS_META_INDEXES * skip;
+
+failed:
+	release_meta_index(inode, meta);
+	return -1;
+}
+
+
+static long long read_blocklist(struct inode *inode, int index,
+				int readahead_blks, char *block_list,
+				unsigned short **block_p, unsigned int *bsize)
+{
+	long long block_ptr;
+	int offset;
+	long long block;
+	int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
+		block_list);
+
+	TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
+		       " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
+		       block);
+
+	if(res == -1)
+		goto failure;
+
+	index -= res;
+
+	while ( index ) {
+		int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
+		int res = read_block_index(inode->i_sb, blocks, block_list,
+			&block_ptr, &offset);
+		if (res == -1)
+			goto failure;
+		block += res;
+		index -= blocks;
+	}
+
+	if (read_block_index(inode->i_sb, 1, block_list,
+			&block_ptr, &offset) == -1)
+		goto failure;
+	*bsize = *((unsigned int *) block_list);
+
+	return block;
+
+failure:
+	return 0;
+}
+
+
+static int squashfs_readpage(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	unsigned char block_list[SIZE];
+	long long block;
+	unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
+	int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
+ 	void *pageaddr;
+	struct squashfs_fragment_cache *fragment = NULL;
+	char *data_ptr = msblk->read_page;
+	
+	int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
+	int start_index = page->index & ~mask;
+	int end_index = start_index | mask;
+
+	TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
+					page->index,
+					SQUASHFS_I(inode)->start_block);
+
+	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+					PAGE_CACHE_SHIFT))
+		goto skip_read;
+
+	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
+					|| index < (i_size_read(inode) >>
+					sblk->block_log)) {
+		if ((block = (msblk->read_blocklist)(inode, index, 1,
+					block_list, NULL, &bsize)) == 0)
+			goto skip_read;
+
+		down(&msblk->read_page_mutex);
+		
+		if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
+					block, bsize, NULL))) {
+			ERROR("Unable to read page, block %llx, size %x\n", block,
+					bsize);
+			up(&msblk->read_page_mutex);
+			goto skip_read;
+		}
+	} else {
+		if ((fragment = get_cached_fragment(inode->i_sb,
+					SQUASHFS_I(inode)->
+					u.s1.fragment_start_block,
+					SQUASHFS_I(inode)->u.s1.fragment_size))
+					== NULL) {
+			ERROR("Unable to read page, block %llx, size %x\n",
+					SQUASHFS_I(inode)->
+					u.s1.fragment_start_block,
+					(int) SQUASHFS_I(inode)->
+					u.s1.fragment_size);
+			goto skip_read;
+		}
+		bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
+					(i_size_read(inode) & (sblk->block_size
+					- 1));
+		byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
+		data_ptr = fragment->data;
+	}
+
+	for (i = start_index; i <= end_index && byte_offset < bytes;
+					i++, byte_offset += PAGE_CACHE_SIZE) {
+		struct page *push_page;
+		int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
+					PAGE_CACHE_SIZE : bytes - byte_offset;
+
+		TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
+					bytes, i, byte_offset, available_bytes);
+
+		if (i == page->index)  {
+			pageaddr = kmap_atomic(page, KM_USER0);
+			memcpy(pageaddr, data_ptr + byte_offset,
+					available_bytes);
+			memset(pageaddr + available_bytes, 0,
+					PAGE_CACHE_SIZE - available_bytes);
+			kunmap_atomic(pageaddr, KM_USER0);
+			flush_dcache_page(page);
+			SetPageUptodate(page);
+			unlock_page(page);
+		} else if ((push_page =
+				grab_cache_page_nowait(page->mapping, i))) {
+ 			pageaddr = kmap_atomic(push_page, KM_USER0);
+
+			memcpy(pageaddr, data_ptr + byte_offset,
+					available_bytes);
+			memset(pageaddr + available_bytes, 0,
+					PAGE_CACHE_SIZE - available_bytes);
+			kunmap_atomic(pageaddr, KM_USER0);
+			flush_dcache_page(push_page);
+			SetPageUptodate(push_page);
+			unlock_page(push_page);
+			page_cache_release(push_page);
+		}
+	}
+
+	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
+					|| index < (i_size_read(inode) >>
+					sblk->block_log))
+		up(&msblk->read_page_mutex);
+	else
+		release_cached_fragment(msblk, fragment);
+
+	return 0;
+
+skip_read:
+	pageaddr = kmap_atomic(page, KM_USER0);
+	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
+	kunmap_atomic(pageaddr, KM_USER0);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+
+	return 0;
+}
+
+
+static int squashfs_readpage4K(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	unsigned char block_list[SIZE];
+	long long block;
+	unsigned int bsize, bytes = 0;
+ 	void *pageaddr;
+	
+	TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
+					page->index,
+					SQUASHFS_I(inode)->start_block);
+
+	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+					PAGE_CACHE_SHIFT)) {
+		pageaddr = kmap_atomic(page, KM_USER0);
+		goto skip_read;
+	}
+
+	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
+					|| page->index < (i_size_read(inode) >>
+					sblk->block_log)) {
+		block = (msblk->read_blocklist)(inode, page->index, 1,
+					block_list, NULL, &bsize);
+
+		down(&msblk->read_page_mutex);
+		bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
+					bsize, NULL);
+		pageaddr = kmap_atomic(page, KM_USER0);
+		if (bytes)
+			memcpy(pageaddr, msblk->read_page, bytes);
+		else
+			ERROR("Unable to read page, block %llx, size %x\n",
+					block, bsize);
+		up(&msblk->read_page_mutex);
+	} else {
+		struct squashfs_fragment_cache *fragment =
+			get_cached_fragment(inode->i_sb,
+					SQUASHFS_I(inode)->
+					u.s1.fragment_start_block,
+					SQUASHFS_I(inode)-> u.s1.fragment_size);
+		pageaddr = kmap_atomic(page, KM_USER0);
+		if (fragment) {
+			bytes = i_size_read(inode) & (sblk->block_size - 1);
+			memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
+					u.s1.fragment_offset, bytes);
+			release_cached_fragment(msblk, fragment);
+		} else
+			ERROR("Unable to read page, block %llx, size %x\n",
+					SQUASHFS_I(inode)->
+					u.s1.fragment_start_block, (int)
+					SQUASHFS_I(inode)-> u.s1.fragment_size);
+	}
+
+skip_read:
+	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
+	kunmap_atomic(pageaddr, KM_USER0);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+
+	return 0;
+}
+
+
+static int get_dir_index_using_offset(struct super_block *s, long long 
+				*next_block, unsigned int *next_offset,
+				long long index_start,
+				unsigned int index_offset, int i_count,
+				long long f_pos)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	int i, length = 0;
+	struct squashfs_dir_index index;
+
+	TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
+					i_count, (unsigned int) f_pos);
+
+	f_pos =- 3;
+	if (f_pos == 0)
+		goto finish;
+
+	for (i = 0; i < i_count; i++) {
+		if (msblk->swap) {
+			struct squashfs_dir_index sindex;
+			squashfs_get_cached_block(s, (char *) &sindex,
+					index_start, index_offset,
+					sizeof(sindex), &index_start,
+					&index_offset);
+			SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
+		} else
+			squashfs_get_cached_block(s, (char *) &index,
+					index_start, index_offset,
+					sizeof(index), &index_start,
+					&index_offset);
+
+		if (index.index > f_pos)
+			break;
+
+		squashfs_get_cached_block(s, NULL, index_start, index_offset,
+					index.size + 1, &index_start,
+					&index_offset);
+
+		length = index.index;
+		*next_block = index.start_block + sblk->directory_table_start;
+	}
+
+	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+
+finish:
+	return length + 3;
+}
+
+
+static int get_dir_index_using_name(struct super_block *s, long long
+				*next_block, unsigned int *next_offset,
+				long long index_start,
+				unsigned int index_offset, int i_count,
+				const char *name, int size)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	int i, length = 0;
+	char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
+	struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
+	char str[SQUASHFS_NAME_LEN + 1];
+
+	TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
+
+	strncpy(str, name, size);
+	str[size] = '\0';
+
+	for (i = 0; i < i_count; i++) {
+		if (msblk->swap) {
+			struct squashfs_dir_index sindex;
+			squashfs_get_cached_block(s, (char *) &sindex,
+					index_start, index_offset,
+					sizeof(sindex), &index_start,
+					&index_offset);
+			SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
+		} else
+			squashfs_get_cached_block(s, (char *) index,
+					index_start, index_offset,
+					sizeof(struct squashfs_dir_index),
+					&index_start, &index_offset);
+
+		squashfs_get_cached_block(s, index->name, index_start,
+					index_offset, index->size + 1,
+					&index_start, &index_offset);
+
+		index->name[index->size + 1] = '\0';
+
+		if (strcmp(index->name, str) > 0)
+			break;
+
+		length = index->index;
+		*next_block = index->start_block + sblk->directory_table_start;
+	}
+
+	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+	return length + 3;
+}
+
+		
+static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+	struct inode *i = file->f_dentry->d_inode;
+	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	long long next_block = SQUASHFS_I(i)->start_block +
+		sblk->directory_table_start;
+	int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
+		dir_count;
+	struct squashfs_dir_header dirh;
+	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
+	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
+
+	TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
+
+	while(file->f_pos < 3) {
+		char *name;
+		int size, i_ino;
+
+		if(file->f_pos == 0) {
+			name = ".";
+			size = 1;
+			i_ino = i->i_ino;
+		} else {
+			name = "..";
+			size = 2;
+			i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
+		}
+		TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
+				(unsigned int) dirent, name, size, (int)
+				file->f_pos, i_ino,
+				squashfs_filetype_table[1]);
+
+		if (filldir(dirent, name, size,
+				file->f_pos, i_ino,
+				squashfs_filetype_table[1]) < 0) {
+				TRACE("Filldir returned less than 0\n");
+				goto finish;
+		}
+		file->f_pos += size;
+		dirs_read++;
+	}
+
+	length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_start,
+				SQUASHFS_I(i)->u.s2.directory_index_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_count,
+				file->f_pos);
+
+	while (length < i_size_read(i)) {
+		/* read directory header */
+		if (msblk->swap) {
+			struct squashfs_dir_header sdirh;
+			
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+					next_block, next_offset, sizeof(sdirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(sdirh);
+			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
+		} else {
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+					next_block, next_offset, sizeof(dirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(dirh);
+		}
+
+		dir_count = dirh.count + 1;
+		while (dir_count--) {
+			if (msblk->swap) {
+				struct squashfs_dir_entry sdire;
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						&sdire, next_block, next_offset,
+						sizeof(sdire), &next_block,
+						&next_offset))
+					goto failed_read;
+				
+				length += sizeof(sdire);
+				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
+			} else {
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						dire, next_block, next_offset,
+						sizeof(*dire), &next_block,
+						&next_offset))
+					goto failed_read;
+
+				length += sizeof(*dire);
+			}
+
+			if (!squashfs_get_cached_block(i->i_sb, dire->name,
+						next_block, next_offset,
+						dire->size + 1, &next_block,
+						&next_offset))
+				goto failed_read;
+
+			length += dire->size + 1;
+
+			if (file->f_pos >= length)
+				continue;
+
+			dire->name[dire->size + 1] = '\0';
+
+			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
+					(unsigned int) dirent, dire->name,
+					dire->size + 1, (int) file->f_pos,
+					dirh.start_block, dire->offset,
+					dirh.inode_number + dire->inode_number,
+					squashfs_filetype_table[dire->type]);
+
+			if (filldir(dirent, dire->name, dire->size + 1,
+					file->f_pos,
+					dirh.inode_number + dire->inode_number,
+					squashfs_filetype_table[dire->type])
+					< 0) {
+				TRACE("Filldir returned less than 0\n");
+				goto finish;
+			}
+			file->f_pos = length;
+			dirs_read++;
+		}
+	}
+
+finish:
+	return dirs_read;
+
+failed_read:
+	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+		next_offset);
+	return 0;
+}
+
+
+static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
+				struct nameidata *nd)
+{
+	const unsigned char *name = dentry->d_name.name;
+	int len = dentry->d_name.len;
+	struct inode *inode = NULL;
+	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	long long next_block = SQUASHFS_I(i)->start_block +
+				sblk->directory_table_start;
+	int next_offset = SQUASHFS_I(i)->offset, length = 0,
+				dir_count;
+	struct squashfs_dir_header dirh;
+	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
+	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
+
+	TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
+
+	if (len > SQUASHFS_NAME_LEN)
+		goto exit_loop;
+
+	length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_start,
+				SQUASHFS_I(i)->u.s2.directory_index_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_count, name,
+				len);
+
+	while (length < i_size_read(i)) {
+		/* read directory header */
+		if (msblk->swap) {
+			struct squashfs_dir_header sdirh;
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+					next_block, next_offset, sizeof(sdirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(sdirh);
+			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
+		} else {
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+					next_block, next_offset, sizeof(dirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(dirh);
+		}
+
+		dir_count = dirh.count + 1;
+		while (dir_count--) {
+			if (msblk->swap) {
+				struct squashfs_dir_entry sdire;
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						&sdire, next_block,next_offset,
+						sizeof(sdire), &next_block,
+						&next_offset))
+					goto failed_read;
+				
+				length += sizeof(sdire);
+				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
+			} else {
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						dire, next_block,next_offset,
+						sizeof(*dire), &next_block,
+						&next_offset))
+					goto failed_read;
+
+				length += sizeof(*dire);
+			}
+
+			if (!squashfs_get_cached_block(i->i_sb, dire->name,
+					next_block, next_offset, dire->size + 1,
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += dire->size + 1;
+
+			if (name[0] < dire->name[0])
+				goto exit_loop;
+
+			if ((len == dire->size + 1) && !strncmp(name,
+						dire->name, len)) {
+				squashfs_inode_t ino =
+					SQUASHFS_MKINODE(dirh.start_block,
+					dire->offset);
+
+				TRACE("calling squashfs_iget for directory "
+					"entry %s, inode %x:%x, %d\n", name,
+					dirh.start_block, dire->offset,
+					dirh.inode_number + dire->inode_number);
+
+				inode = (msblk->iget)(i->i_sb, ino);
+
+				goto exit_loop;
+			}
+		}
+	}
+
+exit_loop:
+	d_add(dentry, inode);
+	return ERR_PTR(0);
+
+failed_read:
+	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+		next_offset);
+	goto exit_loop;
+}
+
+
+static void squashfs_put_super(struct super_block *s)
+{
+	int i;
+
+	if (s->s_fs_info) {
+		struct squashfs_sb_info *sbi = s->s_fs_info;
+		if (sbi->block_cache)
+			for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
+				if (sbi->block_cache[i].block !=
+							SQUASHFS_INVALID_BLK)
+					kfree(sbi->block_cache[i].data);
+		if (sbi->fragment)
+			for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) 
+				SQUASHFS_FREE(sbi->fragment[i].data);
+		kfree(sbi->fragment);
+		kfree(sbi->block_cache);
+		kfree(sbi->read_data);
+		kfree(sbi->read_page);
+		kfree(sbi->uid);
+		kfree(sbi->fragment_index);
+		kfree(sbi->fragment_index_2);
+		kfree(sbi->meta_index);
+		kfree(s->s_fs_info);
+		s->s_fs_info = NULL;
+	}
+}
+
+
+static struct super_block *squashfs_get_sb(struct file_system_type *fs_type,
+				int flags, const char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super);
+}
+
+
+static int __init init_squashfs_fs(void)
+{
+	int err = init_inodecache();
+	if (err)
+		goto out;
+
+	printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
+		"Phillip Lougher\n");
+
+	if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
+		ERROR("Failed to allocate zlib workspace\n");
+		destroy_inodecache();
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if ((err = register_filesystem(&squashfs_fs_type))) {
+		vfree(stream.workspace);
+		destroy_inodecache();
+	}
+
+out:
+	return err;
+}
+
+
+static void __exit exit_squashfs_fs(void)
+{
+	vfree(stream.workspace);
+	unregister_filesystem(&squashfs_fs_type);
+	destroy_inodecache();
+}
+
+
+static kmem_cache_t * squashfs_inode_cachep;
+
+
+static struct inode *squashfs_alloc_inode(struct super_block *sb)
+{
+	struct squashfs_inode_info *ei;
+	ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+
+static void squashfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
+}
+
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct squashfs_inode_info *ei = foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+							SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+
+static int __init init_inodecache(void)
+{
+	squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
+	     sizeof(struct squashfs_inode_info),
+	     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+	     init_once, NULL);
+	if (squashfs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(squashfs_inode_cachep))
+		printk(KERN_INFO "squashfs_inode_cache: not all structures "
+			"were freed\n");
+}
+
+
+module_init(init_squashfs_fs);
+module_exit(exit_squashfs_fs);
+MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
+MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
+MODULE_LICENSE("GPL");
diff -urN oldtree/fs/squashfs/squashfs.h newtree/fs/squashfs/squashfs.h
--- oldtree/fs/squashfs/squashfs.h	1970-01-01 00:00:00.000000000 +0000
+++ newtree/fs/squashfs/squashfs.h	2006-06-08 17:16:36.000000000 +0000
@@ -0,0 +1,86 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs.h
+ */
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+#endif
+
+#ifdef SQUASHFS_TRACE
+#define TRACE(s, args...)	printk(KERN_NOTICE "SQUASHFS: "s, ## args)
+#else
+#define TRACE(s, args...)	{}
+#endif
+
+#define ERROR(s, args...)	printk(KERN_ERR "SQUASHFS error: "s, ## args)
+
+#define SERROR(s, args...)	do { \
+				if (!silent) \
+				printk(KERN_ERR "SQUASHFS error: "s, ## args);\
+				} while(0)
+
+#define WARNING(s, args...)	printk(KERN_WARNING "SQUASHFS: "s, ## args)
+
+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
+{
+	return list_entry(inode, struct squashfs_inode_info, vfs_inode);
+}
+
+#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
+#define SQSH_EXTERN
+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+				long long index, unsigned int length,
+				long long *next_index);
+extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
+				long long block, unsigned int offset,
+				int length, long long *next_block,
+				unsigned int *next_offset);
+extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
+					squashfs_fragment_cache *fragment);
+extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
+					*s, long long start_block,
+					int length);
+extern struct address_space_operations squashfs_symlink_aops;
+extern struct address_space_operations squashfs_aops;
+extern struct address_space_operations squashfs_aops_4K;
+extern struct inode_operations squashfs_dir_inode_ops;
+#else
+#define SQSH_EXTERN static
+#endif
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
+#else
+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
+#else
+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
+{
+	return 0;
+}
+#endif
diff -urN oldtree/fs/squashfs/squashfs2_0.c newtree/fs/squashfs/squashfs2_0.c
--- oldtree/fs/squashfs/squashfs2_0.c	1970-01-01 00:00:00.000000000 +0000
+++ newtree/fs/squashfs/squashfs2_0.c	2006-06-08 17:16:36.000000000 +0000
@@ -0,0 +1,758 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs2_0.c
+ */
+
+#include <linux/types.h>
+#include <linux/squashfs_fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/squashfs_fs_sb.h>
+#include <linux/squashfs_fs_i.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/init.h>
+#include <linux/dcache.h>
+#include <linux/wait.h>
+#include <linux/zlib.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "squashfs.h"
+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
+static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
+				struct nameidata *);
+
+static struct file_operations squashfs_dir_ops_2 = {
+	.read = generic_read_dir,
+	.readdir = squashfs_readdir_2
+};
+
+static struct inode_operations squashfs_dir_inode_ops_2 = {
+	.lookup = squashfs_lookup_2
+};
+
+static unsigned char squashfs_filetype_table[] = {
+	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
+};
+
+static int read_fragment_index_table_2(struct super_block *s)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+
+	if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
+					(sblk->fragments), GFP_KERNEL))) {
+		ERROR("Failed to allocate uid/gid table\n");
+		return 0;
+	}
+   
+	if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
+					!squashfs_read_data(s, (char *)
+					msblk->fragment_index_2,
+					sblk->fragment_table_start,
+					SQUASHFS_FRAGMENT_INDEX_BYTES_2
+					(sblk->fragments) |
+					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
+		ERROR("unable to read fragment index table\n");
+		return 0;
+	}
+
+	if (msblk->swap) {
+		int i;
+		unsigned int fragment;
+
+		for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
+									i++) {
+			SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
+						&msblk->fragment_index_2[i], 1);
+			msblk->fragment_index_2[i] = fragment;
+		}
+	}
+
+	return 1;
+}
+
+
+static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
+				long long *fragment_start_block,
+				unsigned int *fragment_size)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	long long start_block =
+		msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
+	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
+	struct squashfs_fragment_entry_2 fragment_entry;
+
+	if (msblk->swap) {
+		struct squashfs_fragment_entry_2 sfragment_entry;
+
+		if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
+					start_block, offset,
+					sizeof(sfragment_entry), &start_block,
+					&offset))
+			goto out;
+		SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
+	} else
+		if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
+					start_block, offset,
+					sizeof(fragment_entry), &start_block,
+					&offset))
+			goto out;
+
+	*fragment_start_block = fragment_entry.start_block;
+	*fragment_size = fragment_entry.size;
+
+	return 1;
+
+out:
+	return 0;
+}
+
+
+static struct inode *squashfs_new_inode(struct super_block *s,
+		struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	struct inode *i = new_inode(s);
+
+	if (i) {
+		i->i_ino = ino;
+		i->i_mtime.tv_sec = sblk->mkfs_time;
+		i->i_atime.tv_sec = sblk->mkfs_time;
+		i->i_ctime.tv_sec = sblk->mkfs_time;
+		i->i_uid = msblk->uid[inodeb->uid];
+		i->i_mode = inodeb->mode;
+		i->i_nlink = 1;
+		i->i_size = 0;
+		if (inodeb->guid == SQUASHFS_GUIDS)
+			i->i_gid = i->i_uid;
+		else
+			i->i_gid = msblk->guid[inodeb->guid];
+	}
+
+	return i;
+}
+
+
+static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode)
+{
+	struct inode *i;
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	unsigned int block = SQUASHFS_INODE_BLK(inode) +
+		sblk->inode_table_start;
+	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+	unsigned int ino = SQUASHFS_MK_VFS_INODE(block
+		- sblk->inode_table_start, offset);
+	long long next_block;
+	unsigned int next_offset;
+	union squashfs_inode_header_2 id, sid;
+	struct squashfs_base_inode_header_2 *inodeb = &id.base,
+					  *sinodeb = &sid.base;
+
+	TRACE("Entered squashfs_iget\n");
+
+	if (msblk->swap) {
+		if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
+					offset, sizeof(*sinodeb), &next_block,
+					&next_offset))
+			goto failed_read;
+		SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
+					sizeof(*sinodeb));
+	} else
+		if (!squashfs_get_cached_block(s, (char *) inodeb, block,
+					offset, sizeof(*inodeb), &next_block,
+					&next_offset))
+			goto failed_read;
+
+	switch(inodeb->inode_type) {
+		case SQUASHFS_FILE_TYPE: {
+			struct squashfs_reg_inode_header_2 *inodep = &id.reg;
+			struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
+			long long frag_blk;
+			unsigned int frag_size;
+				
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			frag_blk = SQUASHFS_INVALID_BLK;
+			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
+					!get_fragment_location_2(s,
+					inodep->fragment, &frag_blk, &frag_size))
+				goto failed_read;
+				
+			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+				goto failed_read1;
+
+			i->i_size = inodep->file_size;
+			i->i_fop = &generic_ro_fops;
+			i->i_mode |= S_IFREG;
+			i->i_mtime.tv_sec = inodep->mtime;
+			i->i_atime.tv_sec = inodep->mtime;
+			i->i_ctime.tv_sec = inodep->mtime;
+			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+			i->i_blksize = PAGE_CACHE_SIZE;
+			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
+			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
+			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
+			SQUASHFS_I(i)->start_block = inodep->start_block;
+			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+			if (sblk->block_size > 4096)
+				i->i_data.a_ops = &squashfs_aops;
+			else
+				i->i_data.a_ops = &squashfs_aops_4K;
+
+			TRACE("File inode %x:%x, start_block %x, "
+					"block_list_start %llx, offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					inodep->start_block, next_block,
+					next_offset);
+			break;
+		}
+		case SQUASHFS_DIR_TYPE: {
+			struct squashfs_dir_inode_header_2 *inodep = &id.dir;
+			struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
+
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+				goto failed_read1;
+
+			i->i_size = inodep->file_size;
+			i->i_op = &squashfs_dir_inode_ops_2;
+			i->i_fop = &squashfs_dir_ops_2;
+			i->i_mode |= S_IFDIR;
+			i->i_mtime.tv_sec = inodep->mtime;
+			i->i_atime.tv_sec = inodep->mtime;
+			i->i_ctime.tv_sec = inodep->mtime;
+			SQUASHFS_I(i)->start_block = inodep->start_block;
+			SQUASHFS_I(i)->offset = inodep->offset;
+			SQUASHFS_I(i)->u.s2.directory_index_count = 0;
+			SQUASHFS_I(i)->u.s2.parent_inode = 0;
+
+			TRACE("Directory inode %x:%x, start_block %x, offset "
+					"%x\n", SQUASHFS_INODE_BLK(inode),
+					offset, inodep->start_block,
+					inodep->offset);
+			break;
+		}
+		case SQUASHFS_LDIR_TYPE: {
+			struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
+			struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
+
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
+						sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+				goto failed_read1;
+
+			i->i_size = inodep->file_size;
+			i->i_op = &squashfs_dir_inode_ops_2;
+			i->i_fop = &squashfs_dir_ops_2;
+			i->i_mode |= S_IFDIR;
+			i->i_mtime.tv_sec = inodep->mtime;
+			i->i_atime.tv_sec = inodep->mtime;
+			i->i_ctime.tv_sec = inodep->mtime;
+			SQUASHFS_I(i)->start_block = inodep->start_block;
+			SQUASHFS_I(i)->offset = inodep->offset;
+			SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
+			SQUASHFS_I(i)->u.s2.directory_index_offset =
+								next_offset;
+			SQUASHFS_I(i)->u.s2.directory_index_count =
+								inodep->i_count;
+			SQUASHFS_I(i)->u.s2.parent_inode = 0;
+
+			TRACE("Long directory inode %x:%x, start_block %x, "
+					"offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					inodep->start_block, inodep->offset);
+			break;
+		}
+		case SQUASHFS_SYMLINK_TYPE: {
+			struct squashfs_symlink_inode_header_2 *inodep =
+								&id.symlink;
+			struct squashfs_symlink_inode_header_2 *sinodep =
+								&sid.symlink;
+	
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
+								sinodep);
+			} else
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+				goto failed_read1;
+
+			i->i_size = inodep->symlink_size;
+			i->i_op = &page_symlink_inode_operations;
+			i->i_data.a_ops = &squashfs_symlink_aops;
+			i->i_mode |= S_IFLNK;
+			SQUASHFS_I(i)->start_block = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+
+			TRACE("Symbolic link inode %x:%x, start_block %llx, "
+					"offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					next_block, next_offset);
+			break;
+		 }
+		 case SQUASHFS_BLKDEV_TYPE:
+		 case SQUASHFS_CHRDEV_TYPE: {
+			struct squashfs_dev_inode_header_2 *inodep = &id.dev;
+			struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
+
+			if (msblk->swap) {
+				if (!squashfs_get_cached_block(s, (char *)
+						sinodep, block, offset,
+						sizeof(*sinodep), &next_block,
+						&next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
+			} else	
+				if (!squashfs_get_cached_block(s, (char *)
+						inodep, block, offset,
+						sizeof(*inodep), &next_block,
+						&next_offset))
+					goto failed_read;
+
+			if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+				goto failed_read1;
+
+			i->i_mode |= (inodeb->inode_type ==
+					SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
+					S_IFBLK;
+			init_special_inode(i, i->i_mode,
+					old_decode_dev(inodep->rdev));
+
+			TRACE("Device inode %x:%x, rdev %x\n",
+					SQUASHFS_INODE_BLK(inode), offset,
+					inodep->rdev);
+			break;
+		 }
+		 case SQUASHFS_FIFO_TYPE:
+		 case SQUASHFS_SOCKET_TYPE: {
+			if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL)
+				goto failed_read1;
+
+			i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
+							? S_IFIFO : S_IFSOCK;
+			init_special_inode(i, i->i_mode, 0);
+			break;
+		 }
+		 default:
+			ERROR("Unknown inode type %d in squashfs_iget!\n",
+					inodeb->inode_type);
+			goto failed_read1;
+	}
+	
+	insert_inode_hash(i);
+	return i;
+
+failed_read:
+	ERROR("Unable to read inode [%x:%x]\n", block, offset);
+
+failed_read1:
+	return NULL;
+}
+
+
+static int get_dir_index_using_offset(struct super_block *s, long long 
+				*next_block, unsigned int *next_offset,
+				long long index_start,
+				unsigned int index_offset, int i_count,
+				long long f_pos)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	int i, length = 0;
+	struct squashfs_dir_index_2 index;
+
+	TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
+					i_count, (unsigned int) f_pos);
+
+	if (f_pos == 0)
+		goto finish;
+
+	for (i = 0; i < i_count; i++) {
+		if (msblk->swap) {
+			struct squashfs_dir_index_2 sindex;
+			squashfs_get_cached_block(s, (char *) &sindex,
+					index_start, index_offset,
+					sizeof(sindex), &index_start,
+					&index_offset);
+			SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
+		} else
+			squashfs_get_cached_block(s, (char *) &index,
+					index_start, index_offset,
+					sizeof(index), &index_start,
+					&index_offset);
+
+		if (index.index > f_pos)
+			break;
+
+		squashfs_get_cached_block(s, NULL, index_start, index_offset,
+					index.size + 1, &index_start,
+					&index_offset);
+
+		length = index.index;
+		*next_block = index.start_block + sblk->directory_table_start;
+	}
+
+	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+
+finish:
+	return length;
+}
+
+
+static int get_dir_index_using_name(struct super_block *s, long long
+				*next_block, unsigned int *next_offset,
+				long long index_start,
+				unsigned int index_offset, int i_count,
+				const char *name, int size)
+{
+	struct squashfs_sb_info *msblk = s->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	int i, length = 0;
+	char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1];
+	struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer;
+	char str[SQUASHFS_NAME_LEN + 1];
+
+	TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
+
+	strncpy(str, name, size);
+	str[size] = '\0';
+
+	for (i = 0; i < i_count; i++) {
+		if (msblk->swap) {
+			struct squashfs_dir_index_2 sindex;
+			squashfs_get_cached_block(s, (char *) &sindex,
+					index_start, index_offset,
+					sizeof(sindex), &index_start,
+					&index_offset);
+			SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
+		} else
+			squashfs_get_cached_block(s, (char *) index,
+					index_start, index_offset,
+					sizeof(struct squashfs_dir_index_2),
+					&index_start, &index_offset);
+
+		squashfs_get_cached_block(s, index->name, index_start,
+					index_offset, index->size + 1,
+					&index_start, &index_offset);
+
+		index->name[index->size + 1] = '\0';
+
+		if (strcmp(index->name, str) > 0)
+			break;
+
+		length = index->index;
+		*next_block = index->start_block + sblk->directory_table_start;
+	}
+
+	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
+	return length;
+}
+
+		
+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
+{
+	struct inode *i = file->f_dentry->d_inode;
+	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	long long next_block = SQUASHFS_I(i)->start_block +
+		sblk->directory_table_start;
+	int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0,
+		dir_count;
+	struct squashfs_dir_header_2 dirh;
+	char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1];
+	struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+
+	TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
+
+	length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_start,
+				SQUASHFS_I(i)->u.s2.directory_index_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_count,
+				file->f_pos);
+
+	while (length < i_size_read(i)) {
+		/* read directory header */
+		if (msblk->swap) {
+			struct squashfs_dir_header_2 sdirh;
+			
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+					next_block, next_offset, sizeof(sdirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(sdirh);
+			SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
+		} else {
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+					next_block, next_offset, sizeof(dirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(dirh);
+		}
+
+		dir_count = dirh.count + 1;
+		while (dir_count--) {
+			if (msblk->swap) {
+				struct squashfs_dir_entry_2 sdire;
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						&sdire, next_block, next_offset,
+						sizeof(sdire), &next_block,
+						&next_offset))
+					goto failed_read;
+				
+				length += sizeof(sdire);
+				SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
+			} else {
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						dire, next_block, next_offset,
+						sizeof(*dire), &next_block,
+						&next_offset))
+					goto failed_read;
+
+				length += sizeof(*dire);
+			}
+
+			if (!squashfs_get_cached_block(i->i_sb, dire->name,
+						next_block, next_offset,
+						dire->size + 1, &next_block,
+						&next_offset))
+				goto failed_read;
+
+			length += dire->size + 1;
+
+			if (file->f_pos >= length)
+				continue;
+
+			dire->name[dire->size + 1] = '\0';
+
+			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
+					(unsigned int) dirent, dire->name,
+					dire->size + 1, (int) file->f_pos,
+					dirh.start_block, dire->offset,
+					squashfs_filetype_table[dire->type]);
+
+			if (filldir(dirent, dire->name, dire->size + 1,
+					file->f_pos, SQUASHFS_MK_VFS_INODE(
+					dirh.start_block, dire->offset),
+					squashfs_filetype_table[dire->type])
+					< 0) {
+				TRACE("Filldir returned less than 0\n");
+				goto finish;
+			}
+			file->f_pos = length;
+			dirs_read++;
+		}
+	}
+
+finish:
+	return dirs_read;
+
+failed_read:
+	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+		next_offset);
+	return 0;
+}
+
+
+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
+				struct nameidata *nd)
+{
+	const unsigned char *name = dentry->d_name.name;
+	int len = dentry->d_name.len;
+	struct inode *inode = NULL;
+	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
+	struct squashfs_super_block *sblk = &msblk->sblk;
+	long long next_block = SQUASHFS_I(i)->start_block +
+				sblk->directory_table_start;
+	int next_offset = SQUASHFS_I(i)->offset, length = 0,
+				dir_count;
+	struct squashfs_dir_header_2 dirh;
+	char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN];
+	struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer;
+	int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
+
+	TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
+
+	if (len > SQUASHFS_NAME_LEN)
+		goto exit_loop;
+
+	length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_start,
+				SQUASHFS_I(i)->u.s2.directory_index_offset,
+				SQUASHFS_I(i)->u.s2.directory_index_count, name,
+				len);
+
+	while (length < i_size_read(i)) {
+		/* read directory header */
+		if (msblk->swap) {
+			struct squashfs_dir_header_2 sdirh;
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
+					next_block, next_offset, sizeof(sdirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(sdirh);
+			SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
+		} else {
+			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
+					next_block, next_offset, sizeof(dirh),
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += sizeof(dirh);
+		}
+
+		dir_count = dirh.count + 1;
+		while (dir_count--) {
+			if (msblk->swap) {
+				struct squashfs_dir_entry_2 sdire;
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						&sdire, next_block,next_offset,
+						sizeof(sdire), &next_block,
+						&next_offset))
+					goto failed_read;
+				
+				length += sizeof(sdire);
+				SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
+			} else {
+				if (!squashfs_get_cached_block(i->i_sb, (char *)
+						dire, next_block,next_offset,
+						sizeof(*dire), &next_block,
+						&next_offset))
+					goto failed_read;
+
+				length += sizeof(*dire);
+			}
+
+			if (!squashfs_get_cached_block(i->i_sb, dire->name,
+					next_block, next_offset, dire->size + 1,
+					&next_block, &next_offset))
+				goto failed_read;
+
+			length += dire->size + 1;
+
+			if (sorted && name[0] < dire->name[0])
+				goto exit_loop;
+
+			if ((len == dire->size + 1) && !strncmp(name,
+						dire->name, len)) {
+				squashfs_inode_t ino =
+					SQUASHFS_MKINODE(dirh.start_block,
+					dire->offset);
+
+				TRACE("calling squashfs_iget for directory "
+					"entry %s, inode %x:%x, %lld\n", name,
+					dirh.start_block, dire->offset, ino);
+
+				inode = (msblk->iget)(i->i_sb, ino);
+
+				goto exit_loop;
+			}
+		}
+	}
+
+exit_loop:
+	d_add(dentry, inode);
+	return ERR_PTR(0);
+
+failed_read:
+	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
+		next_offset);
+	goto exit_loop;
+}
+
+
+int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
+{
+	struct squashfs_super_block *sblk = &msblk->sblk;
+
+	msblk->iget = squashfs_iget_2;
+	msblk->read_fragment_index_table = read_fragment_index_table_2;
+
+	sblk->bytes_used = sblk->bytes_used_2;
+	sblk->uid_start = sblk->uid_start_2;
+	sblk->guid_start = sblk->guid_start_2;
+	sblk->inode_table_start = sblk->inode_table_start_2;
+	sblk->directory_table_start = sblk->directory_table_start_2;
+	sblk->fragment_table_start = sblk->fragment_table_start_2;
+
+	return 1;
+}
diff -urN oldtree/include/linux/dwarf2-defs.h newtree/include/linux/dwarf2-defs.h
--- oldtree/include/linux/dwarf2-defs.h	1970-01-01 00:00:00.000000000 +0000
+++ newtree/include/linux/dwarf2-defs.h	2006-06-08 19:35:49.624802250 +0000
@@ -0,0 +1,515 @@
+#ifndef  _ELF_DWARF_H
+/* Machine generated from dwarf2.h by scripts/dwarfh.awk */
+#define _ELF_DWARF2_H
+#define DW_TAG_padding	 0x00
+#define DW_TAG_array_type	 0x01
+#define DW_TAG_class_type	 0x02
+#define DW_TAG_entry_point	 0x03
+#define DW_TAG_enumeration_type	 0x04
+#define DW_TAG_formal_parameter	 0x05
+#define DW_TAG_imported_declaration	 0x08
+#define DW_TAG_label	 0x0a
+#define DW_TAG_lexical_block	 0x0b
+#define DW_TAG_member	 0x0d
+#define DW_TAG_pointer_type	 0x0f
+#define DW_TAG_reference_type	 0x10
+#define DW_TAG_compile_unit	 0x11
+#define DW_TAG_string_type	 0x12
+#define DW_TAG_structure_type	 0x13
+#define DW_TAG_subroutine_type	 0x15
+#define DW_TAG_typedef	 0x16
+#define DW_TAG_union_type	 0x17
+#define DW_TAG_unspecified_parameters	 0x18
+#define DW_TAG_variant	 0x19
+#define DW_TAG_common_block	 0x1a
+#define DW_TAG_common_inclusion	 0x1b
+#define DW_TAG_inheritance	 0x1c
+#define DW_TAG_inlined_subroutine	 0x1d
+#define DW_TAG_module	 0x1e
+#define DW_TAG_ptr_to_member_type	 0x1f
+#define DW_TAG_set_type	 0x20
+#define DW_TAG_subrange_type	 0x21
+#define DW_TAG_with_stmt	 0x22
+#define DW_TAG_access_declaration	 0x23
+#define DW_TAG_base_type	 0x24
+#define DW_TAG_catch_block	 0x25
+#define DW_TAG_const_type	 0x26
+#define DW_TAG_constant	 0x27
+#define DW_TAG_enumerator	 0x28
+#define DW_TAG_file_type	 0x29
+#define DW_TAG_friend	 0x2a
+#define DW_TAG_namelist	 0x2b
+#define DW_TAG_namelist_item	 0x2c
+#define DW_TAG_packed_type	 0x2d
+#define DW_TAG_subprogram	 0x2e
+#define DW_TAG_template_type_param	 0x2f
+#define DW_TAG_template_value_param	 0x30
+#define DW_TAG_thrown_type	 0x31
+#define DW_TAG_try_block	 0x32
+#define DW_TAG_variant_part	 0x33
+#define DW_TAG_variable	 0x34
+#define DW_TAG_volatile_type	 0x35
+#define DW_TAG_dwarf_procedure	 0x36
+#define DW_TAG_restrict_type	 0x37
+#define DW_TAG_interface_type	 0x38
+#define DW_TAG_namespace	 0x39
+#define DW_TAG_imported_module	 0x3a
+#define DW_TAG_unspecified_type	 0x3b
+#define DW_TAG_partial_unit	 0x3c
+#define DW_TAG_imported_unit	 0x3d
+#define DW_TAG_MIPS_loop	 0x4081
+#define DW_TAG_HP_array_descriptor	 0x4090
+#define DW_TAG_format_label	 0x4101
+#define DW_TAG_function_template	 0x4102
+#define DW_TAG_class_template	 0x4103
+#define DW_TAG_GNU_BINCL	 0x4104
+#define DW_TAG_GNU_EINCL	 0x4105
+#define DW_TAG_upc_shared_type	 0x8765
+#define DW_TAG_upc_strict_type	 0x8766
+#define DW_TAG_upc_relaxed_type	 0x8767
+#define DW_TAG_PGI_kanji_type	 0xA000
+#define DW_TAG_PGI_interface_block	 0xA020
+#define DW_TAG_lo_user	0x4080
+#define DW_TAG_hi_user	0xffff
+#define DW_children_no   0
+#define	DW_children_yes  1
+#define DW_FORM_addr	 0x01
+#define DW_FORM_block2	 0x03
+#define DW_FORM_block4	 0x04
+#define DW_FORM_data2	 0x05
+#define DW_FORM_data4	 0x06
+#define DW_FORM_data8	 0x07
+#define DW_FORM_string	 0x08
+#define DW_FORM_block	 0x09
+#define DW_FORM_block1	 0x0a
+#define DW_FORM_data1	 0x0b
+#define DW_FORM_flag	 0x0c
+#define DW_FORM_sdata	 0x0d
+#define DW_FORM_strp	 0x0e
+#define DW_FORM_udata	 0x0f
+#define DW_FORM_ref_addr	 0x10
+#define DW_FORM_ref1	 0x11
+#define DW_FORM_ref2	 0x12
+#define DW_FORM_ref4	 0x13
+#define DW_FORM_ref8	 0x14
+#define DW_FORM_ref_udata	 0x15
+#define DW_FORM_indirect	 0x16
+#define DW_AT_sibling	 0x01
+#define DW_AT_location	 0x02
+#define DW_AT_name	 0x03
+#define DW_AT_ordering	 0x09
+#define DW_AT_subscr_data	 0x0a
+#define DW_AT_byte_size	 0x0b
+#define DW_AT_bit_offset	 0x0c
+#define DW_AT_bit_size	 0x0d
+#define DW_AT_element_list	 0x0f
+#define DW_AT_stmt_list	 0x10
+#define DW_AT_low_pc	 0x11
+#define DW_AT_high_pc	 0x12
+#define DW_AT_language	 0x13
+#define DW_AT_member	 0x14
+#define DW_AT_discr	 0x15
+#define DW_AT_discr_value	 0x16
+#define DW_AT_visibility	 0x17
+#define DW_AT_import	 0x18
+#define DW_AT_string_length	 0x19
+#define DW_AT_common_reference	 0x1a
+#define DW_AT_comp_dir	 0x1b
+#define DW_AT_const_value	 0x1c
+#define DW_AT_containing_type	 0x1d
+#define DW_AT_default_value	 0x1e
+#define DW_AT_inline	 0x20
+#define DW_AT_is_optional	 0x21
+#define DW_AT_lower_bound	 0x22
+#define DW_AT_producer	 0x25
+#define DW_AT_prototyped	 0x27
+#define DW_AT_return_addr	 0x2a
+#define DW_AT_start_scope	 0x2c
+#define DW_AT_stride_size	 0x2e
+#define DW_AT_upper_bound	 0x2f
+#define DW_AT_abstract_origin	 0x31
+#define DW_AT_accessibility	 0x32
+#define DW_AT_address_class	 0x33
+#define DW_AT_artificial	 0x34
+#define DW_AT_base_types	 0x35
+#define DW_AT_calling_convention	 0x36
+#define DW_AT_count	 0x37
+#define DW_AT_data_member_location	 0x38
+#define DW_AT_decl_column	 0x39
+#define DW_AT_decl_file	 0x3a
+#define DW_AT_decl_line	 0x3b
+#define DW_AT_declaration	 0x3c
+#define DW_AT_discr_list	 0x3d
+#define DW_AT_encoding	 0x3e
+#define DW_AT_external	 0x3f
+#define DW_AT_frame_base	 0x40
+#define DW_AT_friend	 0x41
+#define DW_AT_identifier_case	 0x42
+#define DW_AT_macro_info	 0x43
+#define DW_AT_namelist_items	 0x44
+#define DW_AT_priority	 0x45
+#define DW_AT_segment	 0x46
+#define DW_AT_specification	 0x47
+#define DW_AT_static_link	 0x48
+#define DW_AT_type	 0x49
+#define DW_AT_use_location	 0x4a
+#define DW_AT_variable_parameter	 0x4b
+#define DW_AT_virtuality	 0x4c
+#define DW_AT_vtable_elem_location	 0x4d
+#define DW_AT_allocated	 0x4e
+#define DW_AT_associated	 0x4f
+#define DW_AT_data_location	 0x50
+#define DW_AT_stride	 0x51
+#define DW_AT_entry_pc	 0x52
+#define DW_AT_use_UTF8	 0x53
+#define DW_AT_extension	 0x54
+#define DW_AT_ranges	 0x55
+#define DW_AT_trampoline	 0x56
+#define DW_AT_call_column	 0x57
+#define DW_AT_call_file	 0x58
+#define DW_AT_call_line	 0x59
+#define DW_AT_MIPS_fde	 0x2001
+#define DW_AT_MIPS_loop_begin	 0x2002
+#define DW_AT_MIPS_tail_loop_begin	 0x2003
+#define DW_AT_MIPS_epilog_begin	 0x2004
+#define DW_AT_MIPS_loop_unroll_factor	 0x2005
+#define DW_AT_MIPS_software_pipeline_depth	 0x2006
+#define DW_AT_MIPS_linkage_name	 0x2007
+#define DW_AT_MIPS_stride	 0x2008
+#define DW_AT_MIPS_abstract_name	 0x2009
+#define DW_AT_MIPS_clone_origin	 0x200a
+#define DW_AT_MIPS_has_inlines	 0x200b
+#define DW_AT_HP_block_index	 0x2000
+#define DW_AT_HP_unmodifiable	 0x2001
+#define DW_AT_HP_actuals_stmt_list	 0x2010
+#define DW_AT_HP_proc_per_section	 0x2011
+#define DW_AT_HP_raw_data_ptr	 0x2012
+#define DW_AT_HP_pass_by_reference	 0x2013
+#define DW_AT_HP_opt_level	 0x2014
+#define DW_AT_HP_prof_version_id	 0x2015
+#define DW_AT_HP_opt_flags	 0x2016
+#define DW_AT_HP_cold_region_low_pc	 0x2017
+#define DW_AT_HP_cold_region_high_pc	 0x2018
+#define DW_AT_HP_all_variables_modifiable	 0x2019
+#define DW_AT_HP_linkage_name	 0x201a
+#define DW_AT_HP_prof_flags	 0x201b
+#define DW_AT_sf_names	 0x2101
+#define DW_AT_src_info	 0x2102
+#define DW_AT_mac_info	 0x2103
+#define DW_AT_src_coords	 0x2104
+#define DW_AT_body_begin	 0x2105
+#define DW_AT_body_end	 0x2106
+#define DW_AT_GNU_vector	 0x2107
+#define DW_AT_VMS_rtnbeg_pd_address	 0x2201
+#define DW_AT_upc_threads_scaled	 0x3210
+#define DW_AT_PGI_lbase	 0x3a00
+#define DW_AT_PGI_soffset	 0x3a01
+#define DW_AT_PGI_lstride	 0x3a02
+#define DW_AT_lo_user	0x2000	/* Implementation-defined range start.  */
+#define DW_AT_hi_user	0x3ff0	/* Implementation-defined range end.  */
+#define DW_OP_addr	 0x03
+#define DW_OP_deref	 0x06
+#define DW_OP_const1u	 0x08
+#define DW_OP_const1s	 0x09
+#define DW_OP_const2u	 0x0a
+#define DW_OP_const2s	 0x0b
+#define DW_OP_const4u	 0x0c
+#define DW_OP_const4s	 0x0d
+#define DW_OP_const8u	 0x0e
+#define DW_OP_const8s	 0x0f
+#define DW_OP_constu	 0x10
+#define DW_OP_consts	 0x11
+#define DW_OP_dup	 0x12
+#define DW_OP_drop	 0x13
+#define DW_OP_over	 0x14
+#define DW_OP_pick	 0x15
+#define DW_OP_swap	 0x16
+#define DW_OP_rot	 0x17
+#define DW_OP_xderef	 0x18
+#define DW_OP_abs	 0x19
+#define DW_OP_and	 0x1a
+#define DW_OP_div	 0x1b
+#define DW_OP_minus	 0x1c
+#define DW_OP_mod	 0x1d
+#define DW_OP_mul	 0x1e
+#define DW_OP_neg	 0x1f
+#define DW_OP_not	 0x20
+#define DW_OP_or	 0x21
+#define DW_OP_plus	 0x22
+#define DW_OP_plus_uconst	 0x23
+#define DW_OP_shl	 0x24
+#define DW_OP_shr	 0x25
+#define DW_OP_shra	 0x26
+#define DW_OP_xor	 0x27
+#define DW_OP_bra	 0x28
+#define DW_OP_eq	 0x29
+#define DW_OP_ge	 0x2a
+#define DW_OP_gt	 0x2b
+#define DW_OP_le	 0x2c
+#define DW_OP_lt	 0x2d
+#define DW_OP_ne	 0x2e
+#define DW_OP_skip	 0x2f
+#define DW_OP_lit0	 0x30
+#define DW_OP_lit1	 0x31
+#define DW_OP_lit2	 0x32
+#define DW_OP_lit3	 0x33
+#define DW_OP_lit4	 0x34
+#define DW_OP_lit5	 0x35
+#define DW_OP_lit6	 0x36
+#define DW_OP_lit7	 0x37
+#define DW_OP_lit8	 0x38
+#define DW_OP_lit9	 0x39
+#define DW_OP_lit10	 0x3a
+#define DW_OP_lit11	 0x3b
+#define DW_OP_lit12	 0x3c
+#define DW_OP_lit13	 0x3d
+#define DW_OP_lit14	 0x3e
+#define DW_OP_lit15	 0x3f
+#define DW_OP_lit16	 0x40
+#define DW_OP_lit17	 0x41
+#define DW_OP_lit18	 0x42
+#define DW_OP_lit19	 0x43
+#define DW_OP_lit20	 0x44
+#define DW_OP_lit21	 0x45
+#define DW_OP_lit22	 0x46
+#define DW_OP_lit23	 0x47
+#define DW_OP_lit24	 0x48
+#define DW_OP_lit25	 0x49
+#define DW_OP_lit26	 0x4a
+#define DW_OP_lit27	 0x4b
+#define DW_OP_lit28	 0x4c
+#define DW_OP_lit29	 0x4d
+#define DW_OP_lit30	 0x4e
+#define DW_OP_lit31	 0x4f
+#define DW_OP_reg0	 0x50
+#define DW_OP_reg1	 0x51
+#define DW_OP_reg2	 0x52
+#define DW_OP_reg3	 0x53
+#define DW_OP_reg4	 0x54
+#define DW_OP_reg5	 0x55
+#define DW_OP_reg6	 0x56
+#define DW_OP_reg7	 0x57
+#define DW_OP_reg8	 0x58
+#define DW_OP_reg9	 0x59
+#define DW_OP_reg10	 0x5a
+#define DW_OP_reg11	 0x5b
+#define DW_OP_reg12	 0x5c
+#define DW_OP_reg13	 0x5d
+#define DW_OP_reg14	 0x5e
+#define DW_OP_reg15	 0x5f
+#define DW_OP_reg16	 0x60
+#define DW_OP_reg17	 0x61
+#define DW_OP_reg18	 0x62
+#define DW_OP_reg19	 0x63
+#define DW_OP_reg20	 0x64
+#define DW_OP_reg21	 0x65
+#define DW_OP_reg22	 0x66
+#define DW_OP_reg23	 0x67
+#define DW_OP_reg24	 0x68
+#define DW_OP_reg25	 0x69
+#define DW_OP_reg26	 0x6a
+#define DW_OP_reg27	 0x6b
+#define DW_OP_reg28	 0x6c
+#define DW_OP_reg29	 0x6d
+#define DW_OP_reg30	 0x6e
+#define DW_OP_reg31	 0x6f
+#define DW_OP_breg0	 0x70
+#define DW_OP_breg1	 0x71
+#define DW_OP_breg2	 0x72
+#define DW_OP_breg3	 0x73
+#define DW_OP_breg4	 0x74
+#define DW_OP_breg5	 0x75
+#define DW_OP_breg6	 0x76
+#define DW_OP_breg7	 0x77
+#define DW_OP_breg8	 0x78
+#define DW_OP_breg9	 0x79
+#define DW_OP_breg10	 0x7a
+#define DW_OP_breg11	 0x7b
+#define DW_OP_breg12	 0x7c
+#define DW_OP_breg13	 0x7d
+#define DW_OP_breg14	 0x7e
+#define DW_OP_breg15	 0x7f
+#define DW_OP_breg16	 0x80
+#define DW_OP_breg17	 0x81
+#define DW_OP_breg18	 0x82
+#define DW_OP_breg19	 0x83
+#define DW_OP_breg20	 0x84
+#define DW_OP_breg21	 0x85
+#define DW_OP_breg22	 0x86
+#define DW_OP_breg23	 0x87
+#define DW_OP_breg24	 0x88
+#define DW_OP_breg25	 0x89
+#define DW_OP_breg26	 0x8a
+#define DW_OP_breg27	 0x8b
+#define DW_OP_breg28	 0x8c
+#define DW_OP_breg29	 0x8d
+#define DW_OP_breg30	 0x8e
+#define DW_OP_breg31	 0x8f
+#define DW_OP_regx	 0x90
+#define DW_OP_fbreg	 0x91
+#define DW_OP_bregx	 0x92
+#define DW_OP_piece	 0x93
+#define DW_OP_deref_size	 0x94
+#define DW_OP_xderef_size	 0x95
+#define DW_OP_nop	 0x96
+#define DW_OP_push_object_address	 0x97
+#define DW_OP_call2	 0x98
+#define DW_OP_call4	 0x99
+#define DW_OP_call_ref	 0x9a
+#define DW_OP_GNU_push_tls_address	 0xe0
+#define DW_OP_HP_unknown	 0xe0
+#define DW_OP_HP_is_value	 0xe1
+#define DW_OP_HP_fltconst4	 0xe2
+#define DW_OP_HP_fltconst8	 0xe3
+#define DW_OP_HP_mod_range	 0xe4
+#define DW_OP_HP_unmod_range	 0xe5
+#define DW_OP_HP_tls	 0xe6
+#define DW_OP_lo_user	0xe0	/* Implementation-defined range start.  */
+#define DW_OP_hi_user	0xff	/* Implementation-defined range end.  */
+#define DW_ATE_void	 0x0
+#define DW_ATE_address	 0x1
+#define DW_ATE_boolean	 0x2
+#define DW_ATE_complex_float	 0x3
+#define DW_ATE_float	 0x4
+#define DW_ATE_signed	 0x5
+#define DW_ATE_signed_char	 0x6
+#define DW_ATE_unsigned	 0x7
+#define DW_ATE_unsigned_char	 0x8
+#define DW_ATE_imaginary_float	 0x9
+#define DW_ATE_HP_float80	 0x80
+#define DW_ATE_HP_complex_float80	 0x81
+#define DW_ATE_HP_float128	 0x82
+#define DW_ATE_HP_complex_float128	 0x83
+#define DW_ATE_HP_floathpintel	 0x84
+#define DW_ATE_HP_imaginary_float80	 0x85
+#define DW_ATE_HP_imaginary_float128	 0x86
+#define	DW_ATE_lo_user 0x80
+#define	DW_ATE_hi_user 0xff
+#define DW_ORD_row_major	 0
+#define DW_ORD_col_major	 1
+#define DW_ACCESS_public	 1
+#define DW_ACCESS_protected	 2
+#define DW_ACCESS_private	 3
+#define DW_VIS_local	 1
+#define DW_VIS_exported	 2
+#define DW_VIS_qualified	 3
+#define DW_VIRTUALITY_none	 0
+#define DW_VIRTUALITY_virtual	 1
+#define DW_VIRTUALITY_pure_virtual	 2
+#define DW_ID_case_sensitive	 0
+#define DW_ID_up_case	 1
+#define DW_ID_down_case	 2
+#define DW_ID_case_insensitive	 3
+#define DW_CC_normal	 0x1
+#define DW_CC_program	 0x2
+#define DW_CC_nocall	 0x3
+#define DW_CC_lo_user 0x40
+#define DW_CC_hi_user 0xff
+#define DW_INL_not_inlined	 0
+#define DW_INL_inlined	 1
+#define DW_INL_declared_not_inlined	 2
+#define DW_INL_declared_inlined	 3
+#define DW_DSC_label	 0
+#define DW_DSC_range	 1
+#define DW_LNS_extended_op	 0
+#define DW_LNS_copy	 1
+#define DW_LNS_advance_pc	 2
+#define DW_LNS_advance_line	 3
+#define DW_LNS_set_file	 4
+#define DW_LNS_set_column	 5
+#define DW_LNS_negate_stmt	 6
+#define DW_LNS_set_basic_block	 7
+#define DW_LNS_const_add_pc	 8
+#define DW_LNS_fixed_advance_pc	 9
+#define DW_LNS_set_prologue_end	 10
+#define DW_LNS_set_epilogue_begin	 11
+#define DW_LNS_set_isa	 12
+#define DW_LNE_end_sequence	 1
+#define DW_LNE_set_address	 2
+#define DW_LNE_define_file	 3
+#define DW_LNE_HP_negate_is_UV_update	 0x11
+#define DW_LNE_HP_push_context	 0x12
+#define DW_LNE_HP_pop_context	 0x13
+#define DW_LNE_HP_set_file_line_column	 0x14
+#define DW_LNE_HP_set_routine_name	 0x15
+#define DW_LNE_HP_set_sequence	 0x16
+#define DW_LNE_HP_negate_post_semantics	 0x17
+#define DW_LNE_HP_negate_function_exit	 0x18
+#define DW_LNE_HP_negate_front_end_logical	 0x19
+#define DW_LNE_HP_define_proc	 0x20
+#define DW_CFA_advance_loc	 0x40
+#define DW_CFA_offset	 0x80
+#define DW_CFA_restore	 0xc0
+#define DW_CFA_nop	 0x00
+#define DW_CFA_set_loc	 0x01
+#define DW_CFA_advance_loc1	 0x02
+#define DW_CFA_advance_loc2	 0x03
+#define DW_CFA_advance_loc4	 0x04
+#define DW_CFA_offset_extended	 0x05
+#define DW_CFA_restore_extended	 0x06
+#define DW_CFA_undefined	 0x07
+#define DW_CFA_same_value	 0x08
+#define DW_CFA_register	 0x09
+#define DW_CFA_remember_state	 0x0a
+#define DW_CFA_restore_state	 0x0b
+#define DW_CFA_def_cfa	 0x0c
+#define DW_CFA_def_cfa_register	 0x0d
+#define DW_CFA_def_cfa_offset	 0x0e
+#define DW_CFA_def_cfa_expression	 0x0f
+#define DW_CFA_expression	 0x10
+#define DW_CFA_offset_extended_sf	 0x11
+#define DW_CFA_def_cfa_sf	 0x12
+#define DW_CFA_def_cfa_offset_sf	 0x13
+#define DW_CFA_MIPS_advance_loc8	 0x1d
+#define DW_CFA_GNU_window_save	 0x2d
+#define DW_CFA_GNU_args_size	 0x2e
+#define DW_CFA_GNU_negative_offset_extended	 0x2f
+#define DW_CIE_ID	  0xffffffff
+#define DW_CIE_VERSION	  1
+#define DW_CFA_extended   0
+#define DW_CFA_lo_user    0x1c
+#define DW_CFA_hi_user    0x3f
+#define DW_CHILDREN_no		     0x00
+#define DW_CHILDREN_yes		     0x01
+#define DW_ADDR_none		0
+#define DW_LANG_C89	 0x0001
+#define DW_LANG_C	 0x0002
+#define DW_LANG_Ada83	 0x0003
+#define DW_LANG_C_plus_plus	 0x0004
+#define DW_LANG_Cobol74	 0x0005
+#define DW_LANG_Cobol85	 0x0006
+#define DW_LANG_Fortran77	 0x0007
+#define DW_LANG_Fortran90	 0x0008
+#define DW_LANG_Pascal83	 0x0009
+#define DW_LANG_Modula2	 0x000a
+#define DW_LANG_Java	 0x000b
+#define DW_LANG_C99	 0x000c
+#define DW_LANG_Ada95	 0x000d
+#define DW_LANG_Fortran95	 0x000e
+#define DW_LANG_Mips_Assembler	 0x8001
+#define DW_LANG_Upc	 0x8765
+#define DW_LANG_lo_user 0x8000	/* Implementation-defined range start.  */
+#define DW_LANG_hi_user 0xffff	/* Implementation-defined range start.  */
+#define DW_MACINFO_define	 1
+#define DW_MACINFO_undef	 2
+#define DW_MACINFO_start_file	 3
+#define DW_MACINFO_end_file	 4
+#define DW_MACINFO_vendor_ext	 255
+#define DW_EH_PE_absptr		0x00
+#define DW_EH_PE_omit		0xff
+#define DW_EH_PE_uleb128	0x01
+#define DW_EH_PE_udata2		0x02
+#define DW_EH_PE_udata4		0x03
+#define DW_EH_PE_udata8		0x04
+#define DW_EH_PE_sleb128	0x09
+#define DW_EH_PE_sdata2		0x0A
+#define DW_EH_PE_sdata4		0x0B
+#define DW_EH_PE_sdata8		0x0C
+#define DW_EH_PE_signed		0x08
+#define DW_EH_PE_pcrel		0x10
+#define DW_EH_PE_textrel	0x20
+#define DW_EH_PE_datarel	0x30
+#define DW_EH_PE_funcrel	0x40
+#define DW_EH_PE_aligned	0x50
+#define DW_EH_PE_indirect	0x80
+#endif
diff -urN oldtree/include/linux/squashfs_fs.h newtree/include/linux/squashfs_fs.h
--- oldtree/include/linux/squashfs_fs.h	1970-01-01 00:00:00.000000000 +0000
+++ newtree/include/linux/squashfs_fs.h	2006-06-08 19:34:59.153648000 +0000
@@ -0,0 +1,911 @@
+#ifndef SQUASHFS_FS
+#define SQUASHFS_FS
+
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs.h
+ */
+
+#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
+#endif
+
+#ifdef	CONFIG_SQUASHFS_VMALLOC
+#define SQUASHFS_ALLOC(a)		vmalloc(a)
+#define SQUASHFS_FREE(a)		vfree(a)
+#else
+#define SQUASHFS_ALLOC(a)		kmalloc(a, GFP_KERNEL)
+#define SQUASHFS_FREE(a)		kfree(a)
+#endif
+#define SQUASHFS_CACHED_FRAGMENTS	CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE	
+#define SQUASHFS_MAJOR			3
+#define SQUASHFS_MINOR			0
+#define SQUASHFS_MAGIC			0x73717368
+#define SQUASHFS_MAGIC_SWAP		0x68737173
+#define SQUASHFS_START			0
+
+/* size of metadata (inode and directory) blocks */
+#define SQUASHFS_METADATA_SIZE		8192
+#define SQUASHFS_METADATA_LOG		13
+
+/* default size of data blocks */
+#define SQUASHFS_FILE_SIZE		65536
+#define SQUASHFS_FILE_LOG		16
+
+#define SQUASHFS_FILE_MAX_SIZE		65536
+
+/* Max number of uids and gids */
+#define SQUASHFS_UIDS			256
+#define SQUASHFS_GUIDS			255
+
+/* Max length of filename (not 255) */
+#define SQUASHFS_NAME_LEN		256
+
+#define SQUASHFS_INVALID		((long long) 0xffffffffffff)
+#define SQUASHFS_INVALID_FRAG		((unsigned int) 0xffffffff)
+#define SQUASHFS_INVALID_BLK		((long long) -1)
+#define SQUASHFS_USED_BLK		((long long) -2)
+
+/* Filesystem flags */
+#define SQUASHFS_NOI			0
+#define SQUASHFS_NOD			1
+#define SQUASHFS_CHECK			2
+#define SQUASHFS_NOF			3
+#define SQUASHFS_NO_FRAG		4
+#define SQUASHFS_ALWAYS_FRAG		5
+#define SQUASHFS_DUPLICATE		6
+
+#define SQUASHFS_BIT(flag, bit)		((flag >> bit) & 1)
+
+#define SQUASHFS_UNCOMPRESSED_INODES(flags)	SQUASHFS_BIT(flags, \
+						SQUASHFS_NOI)
+
+#define SQUASHFS_UNCOMPRESSED_DATA(flags)	SQUASHFS_BIT(flags, \
+						SQUASHFS_NOD)
+
+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
+						SQUASHFS_NOF)
+
+#define SQUASHFS_NO_FRAGMENTS(flags)		SQUASHFS_BIT(flags, \
+						SQUASHFS_NO_FRAG)
+
+#define SQUASHFS_ALWAYS_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
+						SQUASHFS_ALWAYS_FRAG)
+
+#define SQUASHFS_DUPLICATES(flags)		SQUASHFS_BIT(flags, \
+						SQUASHFS_DUPLICATE)
+
+#define SQUASHFS_CHECK_DATA(flags)		SQUASHFS_BIT(flags, \
+						SQUASHFS_CHECK)
+
+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
+		duplicate_checking)	(noi | (nod << 1) | (check_data << 2) \
+		| (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
+		(duplicate_checking << 6))
+
+/* Max number of types and file types */
+#define SQUASHFS_DIR_TYPE		1
+#define SQUASHFS_FILE_TYPE		2
+#define SQUASHFS_SYMLINK_TYPE		3
+#define SQUASHFS_BLKDEV_TYPE		4
+#define SQUASHFS_CHRDEV_TYPE		5
+#define SQUASHFS_FIFO_TYPE		6
+#define SQUASHFS_SOCKET_TYPE		7
+#define SQUASHFS_LDIR_TYPE		8
+#define SQUASHFS_LREG_TYPE		9
+
+/* 1.0 filesystem type definitions */
+#define SQUASHFS_TYPES			5
+#define SQUASHFS_IPC_TYPE		0
+
+/* Flag whether block is compressed or uncompressed, bit is set if block is
+ * uncompressed */
+#define SQUASHFS_COMPRESSED_BIT		(1 << 15)
+
+#define SQUASHFS_COMPRESSED_SIZE(B)	(((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
+		(B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
+
+#define SQUASHFS_COMPRESSED(B)		(!((B) & SQUASHFS_COMPRESSED_BIT))
+
+#define SQUASHFS_COMPRESSED_BIT_BLOCK		(1 << 24)
+
+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)	(((B) & \
+	~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
+	~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
+
+#define SQUASHFS_COMPRESSED_BLOCK(B)	(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
+
+/*
+ * Inode number ops.  Inodes consist of a compressed block number, and an
+ * uncompressed  offset within that block
+ */
+#define SQUASHFS_INODE_BLK(a)		((unsigned int) ((a) >> 16))
+
+#define SQUASHFS_INODE_OFFSET(a)	((unsigned int) ((a) & 0xffff))
+
+#define SQUASHFS_MKINODE(A, B)		((squashfs_inode_t)(((squashfs_inode_t) (A)\
+					<< 16) + (B)))
+
+/* Compute 32 bit VFS inode number from squashfs inode number */
+#define SQUASHFS_MK_VFS_INODE(a, b)	((unsigned int) (((a) << 8) + \
+					((b) >> 2) + 1))
+/* XXX */
+
+/* Translate between VFS mode and squashfs mode */
+#define SQUASHFS_MODE(a)		((a) & 0xfff)
+
+/* fragment and fragment table defines */
+#define SQUASHFS_FRAGMENT_BYTES(A)	(A * sizeof(struct squashfs_fragment_entry))
+
+#define SQUASHFS_FRAGMENT_INDEX(A)	(SQUASHFS_FRAGMENT_BYTES(A) / \
+					SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)	(SQUASHFS_FRAGMENT_BYTES(A) % \
+						SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEXES(A)	((SQUASHFS_FRAGMENT_BYTES(A) + \
+					SQUASHFS_METADATA_SIZE - 1) / \
+					SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)	(SQUASHFS_FRAGMENT_INDEXES(A) *\
+						sizeof(long long))
+
+/* cached data constants for filesystem */
+#define SQUASHFS_CACHED_BLKS		8
+
+#define SQUASHFS_MAX_FILE_SIZE_LOG	64
+
+#define SQUASHFS_MAX_FILE_SIZE		((long long) 1 << \
+					(SQUASHFS_MAX_FILE_SIZE_LOG - 2))
+
+#define SQUASHFS_MARKER_BYTE		0xff
+
+/* meta index cache */
+#define SQUASHFS_META_INDEXES	(SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
+#define SQUASHFS_META_ENTRIES	31
+#define SQUASHFS_META_NUMBER	8
+#define SQUASHFS_SLOTS		4
+
+struct meta_entry {
+	long long		data_block;
+	unsigned int		index_block;
+	unsigned short		offset;
+	unsigned short		pad;
+};
+
+struct meta_index {
+	unsigned int		inode_number;
+	unsigned int		offset;
+	unsigned short		entries;
+	unsigned short		skip;
+	unsigned short		locked;
+	unsigned short		pad;
+	struct meta_entry	meta_entry[SQUASHFS_META_ENTRIES];
+};
+
+
+/*
+ * definitions for structures on disk
+ */
+
+typedef long long		squashfs_block_t;
+typedef long long		squashfs_inode_t;
+
+struct squashfs_super_block {
+	unsigned int		s_magic;
+	unsigned int		inodes;
+	unsigned int		bytes_used_2;
+	unsigned int		uid_start_2;
+	unsigned int		guid_start_2;
+	unsigned int		inode_table_start_2;
+	unsigned int		directory_table_start_2;
+	unsigned int		s_major:16;
+	unsigned int		s_minor:16;
+	unsigned int		block_size_1:16;
+	unsigned int		block_log:16;
+	unsigned int		flags:8;
+	unsigned int		no_uids:8;
+	unsigned int		no_guids:8;
+	unsigned int		mkfs_time /* time of filesystem creation */;
+	squashfs_inode_t	root_inode;
+	unsigned int		block_size;
+	unsigned int		fragments;
+	unsigned int		fragment_table_start_2;
+	long long		bytes_used;
+	long long		uid_start;
+	long long		guid_start;
+	long long		inode_table_start;
+	long long		directory_table_start;
+	long long		fragment_table_start;
+	long long		unused;
+} __attribute__ ((packed));
+
+struct squashfs_dir_index {
+	unsigned int		index;
+	unsigned int		start_block;
+	unsigned char		size;
+	unsigned char		name[0];
+} __attribute__ ((packed));
+
+#define SQUASHFS_BASE_INODE_HEADER		\
+	unsigned int		inode_type:4;	\
+	unsigned int		mode:12;	\
+	unsigned int		uid:8;		\
+	unsigned int		guid:8;		\
+	unsigned int		mtime;		\
+	unsigned int 		inode_number;
+
+struct squashfs_base_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+} __attribute__ ((packed));
+
+struct squashfs_ipc_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+	unsigned int		nlink;
+} __attribute__ ((packed));
+
+struct squashfs_dev_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+	unsigned int		nlink;
+	unsigned short		rdev;
+} __attribute__ ((packed));
+	
+struct squashfs_symlink_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+	unsigned int		nlink;
+	unsigned short		symlink_size;
+	char			symlink[0];
+} __attribute__ ((packed));
+
+struct squashfs_reg_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+	squashfs_block_t	start_block;
+	unsigned int		fragment;
+	unsigned int		offset;
+	unsigned int		file_size;
+	unsigned short		block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_lreg_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+	unsigned int		nlink;
+	squashfs_block_t	start_block;
+	unsigned int		fragment;
+	unsigned int		offset;
+	long long		file_size;
+	unsigned short		block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+	unsigned int		nlink;
+	unsigned int		file_size:19;
+	unsigned int		offset:13;
+	unsigned int		start_block;
+	unsigned int		parent_inode;
+} __attribute__  ((packed));
+
+struct squashfs_ldir_inode_header {
+	SQUASHFS_BASE_INODE_HEADER;
+	unsigned int		nlink;
+	unsigned int		file_size:27;
+	unsigned int		offset:13;
+	unsigned int		start_block;
+	unsigned int		i_count:16;
+	unsigned int		parent_inode;
+	struct squashfs_dir_index	index[0];
+} __attribute__  ((packed));
+
+union squashfs_inode_header {
+	struct squashfs_base_inode_header	base;
+	struct squashfs_dev_inode_header	dev;
+	struct squashfs_symlink_inode_header	symlink;
+	struct squashfs_reg_inode_header	reg;
+	struct squashfs_lreg_inode_header	lreg;
+	struct squashfs_dir_inode_header	dir;
+	struct squashfs_ldir_inode_header	ldir;
+	struct squashfs_ipc_inode_header	ipc;
+};
+	
+struct squashfs_dir_entry {
+	unsigned int		offset:13;
+	unsigned int		type:3;
+	unsigned int		size:8;
+	int			inode_number:16;
+	char			name[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_header {
+	unsigned int		count:8;
+	unsigned int		start_block;
+	unsigned int		inode_number;
+} __attribute__ ((packed));
+
+struct squashfs_fragment_entry {
+	long long		start_block;
+	unsigned int		size;
+	unsigned int		unused;
+} __attribute__ ((packed));
+
+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
+extern int squashfs_uncompress_init(void);
+extern int squashfs_uncompress_exit(void);
+
+/*
+ * macros to convert each packed bitfield structure from little endian to big
+ * endian and vice versa.  These are needed when creating or using a filesystem
+ * on a machine with different byte ordering to the target architecture.
+ *
+ */
+
+#define SQUASHFS_SWAP_START \
+	int bits;\
+	int b_pos;\
+	unsigned long long val;\
+	unsigned char *s;\
+	unsigned char *d;
+
+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
+	SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
+	SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
+	SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
+	SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
+	SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
+	SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
+	SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
+	SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
+	SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
+	SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
+	SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
+	SQUASHFS_SWAP((s)->flags, d, 288, 8);\
+	SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
+	SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
+	SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
+	SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
+	SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
+	SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
+	SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
+	SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
+	SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
+	SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
+	SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
+	SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
+	SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
+	SQUASHFS_SWAP((s)->unused, d, 888, 64);\
+}
+
+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
+	SQUASHFS_MEMSET(s, d, n);\
+	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
+	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+	SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+			sizeof(struct squashfs_ipc_inode_header))\
+	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+}
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+			sizeof(struct squashfs_dev_inode_header)); \
+	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+	SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+			sizeof(struct squashfs_symlink_inode_header));\
+	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+	SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+			sizeof(struct squashfs_reg_inode_header));\
+	SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
+	SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
+	SQUASHFS_SWAP((s)->offset, d, 192, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
+}
+
+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+			sizeof(struct squashfs_lreg_inode_header));\
+	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
+	SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
+	SQUASHFS_SWAP((s)->offset, d, 224, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+			sizeof(struct squashfs_dir_inode_header));\
+	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
+	SQUASHFS_SWAP((s)->offset, d, 147, 13);\
+	SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
+	SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
+}
+
+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
+			sizeof(struct squashfs_ldir_inode_header));\
+	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
+	SQUASHFS_SWAP((s)->offset, d, 155, 13);\
+	SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
+	SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
+	SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
+}
+
+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
+	SQUASHFS_SWAP((s)->index, d, 0, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
+	SQUASHFS_SWAP((s)->size, d, 64, 8);\
+}
+
+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
+	SQUASHFS_SWAP((s)->count, d, 0, 8);\
+	SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
+	SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
+}
+
+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
+	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
+	SQUASHFS_SWAP((s)->type, d, 13, 3);\
+	SQUASHFS_SWAP((s)->size, d, 16, 8);\
+	SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
+	SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
+	SQUASHFS_SWAP((s)->size, d, 64, 32);\
+}
+
+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
+	int entry;\
+	int bit_position;\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, n * 2);\
+	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+			16)\
+		SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
+}
+
+#define SQUASHFS_SWAP_INTS(s, d, n) {\
+	int entry;\
+	int bit_position;\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, n * 4);\
+	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+			32)\
+		SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
+}
+
+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
+	int entry;\
+	int bit_position;\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, n * 8);\
+	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+			64)\
+		SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
+}
+
+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
+	int entry;\
+	int bit_position;\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, n * bits / 8);\
+	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+			bits)\
+		SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+
+struct squashfs_base_inode_header_1 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+} __attribute__ ((packed));
+
+struct squashfs_ipc_inode_header_1 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned int		type:4;
+	unsigned int		offset:4;
+} __attribute__ ((packed));
+
+struct squashfs_dev_inode_header_1 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned short		rdev;
+} __attribute__ ((packed));
+	
+struct squashfs_symlink_inode_header_1 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned short		symlink_size;
+	char			symlink[0];
+} __attribute__ ((packed));
+
+struct squashfs_reg_inode_header_1 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned int		mtime;
+	unsigned int		start_block;
+	unsigned int		file_size:32;
+	unsigned short		block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_inode_header_1 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned int		file_size:19;
+	unsigned int		offset:13;
+	unsigned int		mtime;
+	unsigned int		start_block:24;
+} __attribute__  ((packed));
+
+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
+	SQUASHFS_MEMSET(s, d, n);\
+	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+	SQUASHFS_SWAP((s)->uid, d, 16, 4);\
+	SQUASHFS_SWAP((s)->guid, d, 20, 4);
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+			sizeof(struct squashfs_ipc_inode_header_1));\
+	SQUASHFS_SWAP((s)->type, d, 24, 4);\
+	SQUASHFS_SWAP((s)->offset, d, 28, 4);\
+}
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+			sizeof(struct squashfs_dev_inode_header_1));\
+	SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+			sizeof(struct squashfs_symlink_inode_header_1));\
+	SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+			sizeof(struct squashfs_reg_inode_header_1));\
+	SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
+			sizeof(struct squashfs_dir_inode_header_1));\
+	SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
+	SQUASHFS_SWAP((s)->offset, d, 43, 13);\
+	SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
+}
+
+#endif
+
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
+
+struct squashfs_dir_index_2 {
+	unsigned int		index:27;
+	unsigned int		start_block:29;
+	unsigned char		size;
+	unsigned char		name[0];
+} __attribute__ ((packed));
+
+struct squashfs_base_inode_header_2 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+} __attribute__ ((packed));
+
+struct squashfs_ipc_inode_header_2 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+} __attribute__ ((packed));
+
+struct squashfs_dev_inode_header_2 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned short		rdev;
+} __attribute__ ((packed));
+	
+struct squashfs_symlink_inode_header_2 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned short		symlink_size;
+	char			symlink[0];
+} __attribute__ ((packed));
+
+struct squashfs_reg_inode_header_2 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned int		mtime;
+	unsigned int		start_block;
+	unsigned int		fragment;
+	unsigned int		offset;
+	unsigned int		file_size:32;
+	unsigned short		block_list[0];
+} __attribute__ ((packed));
+
+struct squashfs_dir_inode_header_2 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned int		file_size:19;
+	unsigned int		offset:13;
+	unsigned int		mtime;
+	unsigned int		start_block:24;
+} __attribute__  ((packed));
+
+struct squashfs_ldir_inode_header_2 {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned int		file_size:27;
+	unsigned int		offset:13;
+	unsigned int		mtime;
+	unsigned int		start_block:24;
+	unsigned int		i_count:16;
+	struct squashfs_dir_index_2	index[0];
+} __attribute__  ((packed));
+
+union squashfs_inode_header_2 {
+	struct squashfs_base_inode_header_2	base;
+	struct squashfs_dev_inode_header_2	dev;
+	struct squashfs_symlink_inode_header_2	symlink;
+	struct squashfs_reg_inode_header_2	reg;
+	struct squashfs_dir_inode_header_2	dir;
+	struct squashfs_ldir_inode_header_2	ldir;
+	struct squashfs_ipc_inode_header_2	ipc;
+};
+	
+struct squashfs_dir_header_2 {
+	unsigned int		count:8;
+	unsigned int		start_block:24;
+} __attribute__ ((packed));
+
+struct squashfs_dir_entry_2 {
+	unsigned int		offset:13;
+	unsigned int		type:3;
+	unsigned int		size:8;
+	char			name[0];
+} __attribute__ ((packed));
+
+struct squashfs_fragment_entry_2 {
+	unsigned int		start_block;
+	unsigned int		size;
+} __attribute__ ((packed));
+
+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
+	SQUASHFS_MEMSET(s, d, n);\
+	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
+	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
+	SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+			sizeof(struct squashfs_dev_inode_header_2)); \
+	SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+			sizeof(struct squashfs_symlink_inode_header_2));\
+	SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+			sizeof(struct squashfs_reg_inode_header_2));\
+	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
+	SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
+	SQUASHFS_SWAP((s)->offset, d, 128, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+			sizeof(struct squashfs_dir_inode_header_2));\
+	SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
+	SQUASHFS_SWAP((s)->offset, d, 51, 13);\
+	SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
+}
+
+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
+			sizeof(struct squashfs_ldir_inode_header_2));\
+	SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
+	SQUASHFS_SWAP((s)->offset, d, 59, 13);\
+	SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
+	SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
+}
+
+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
+	SQUASHFS_SWAP((s)->index, d, 0, 27);\
+	SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
+	SQUASHFS_SWAP((s)->size, d, 56, 8);\
+}
+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
+	SQUASHFS_SWAP((s)->count, d, 0, 8);\
+	SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
+}
+
+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
+	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
+	SQUASHFS_SWAP((s)->type, d, 13, 3);\
+	SQUASHFS_SWAP((s)->size, d, 16, 8);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
+	SQUASHFS_SWAP_START\
+	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
+	SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
+	SQUASHFS_SWAP((s)->size, d, 32, 32);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
+
+/* fragment and fragment table defines */
+#define SQUASHFS_FRAGMENT_BYTES_2(A)	(A * sizeof(struct squashfs_fragment_entry_2))
+
+#define SQUASHFS_FRAGMENT_INDEX_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) / \
+					SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) % \
+						SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEXES_2(A)	((SQUASHFS_FRAGMENT_BYTES_2(A) + \
+					SQUASHFS_METADATA_SIZE - 1) / \
+					SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)	(SQUASHFS_FRAGMENT_INDEXES_2(A) *\
+						sizeof(int))
+
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * macros used to swap each structure entry, taking into account
+ * bitfields and different bitfield placing conventions on differing
+ * architectures
+ */
+
+#include <asm/byteorder.h>
+
+#ifdef __BIG_ENDIAN
+	/* convert from little endian to big endian */
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+		tbits, b_pos)
+#else
+	/* convert from big endian to little endian */ 
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+		tbits, 64 - tbits - b_pos)
+#endif
+
+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
+	b_pos = pos % 8;\
+	val = 0;\
+	s = (unsigned char *)p + (pos / 8);\
+	d = ((unsigned char *) &val) + 7;\
+	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
+		*d-- = *s++;\
+	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
+}
+
+#define SQUASHFS_MEMSET(s, d, n)	memset(s, 0, n);
+
+#endif
+#endif
diff -urN oldtree/include/linux/squashfs_fs_i.h newtree/include/linux/squashfs_fs_i.h
--- oldtree/include/linux/squashfs_fs_i.h	1970-01-01 00:00:00.000000000 +0000
+++ newtree/include/linux/squashfs_fs_i.h	2006-06-08 19:34:59.173649250 +0000
@@ -0,0 +1,45 @@
+#ifndef SQUASHFS_FS_I
+#define SQUASHFS_FS_I
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs_i.h
+ */
+
+struct squashfs_inode_info {
+	long long	start_block;
+	unsigned int	offset;
+	union {
+		struct {
+			long long	fragment_start_block;
+			unsigned int	fragment_size;
+			unsigned int	fragment_offset;
+			long long	block_list_start;
+		} s1;
+		struct {
+			long long	directory_index_start;
+			unsigned int	directory_index_offset;
+			unsigned int	directory_index_count;
+			unsigned int	parent_inode;
+		} s2;
+	} u;
+	struct inode	vfs_inode;
+};
+#endif
diff -urN oldtree/include/linux/squashfs_fs_sb.h newtree/include/linux/squashfs_fs_sb.h
--- oldtree/include/linux/squashfs_fs_sb.h	1970-01-01 00:00:00.000000000 +0000
+++ newtree/include/linux/squashfs_fs_sb.h	2006-06-08 19:34:59.181649750 +0000
@@ -0,0 +1,74 @@
+#ifndef SQUASHFS_FS_SB
+#define SQUASHFS_FS_SB
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006
+ * Phillip Lougher <phillip@lougher.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs_sb.h
+ */
+
+#include <linux/squashfs_fs.h>
+
+struct squashfs_cache {
+	long long	block;
+	int		length;
+	long long	next_index;
+	char		*data;
+};
+
+struct squashfs_fragment_cache {
+	long long	block;
+	int		length;
+	unsigned int	locked;
+	char		*data;
+};
+
+struct squashfs_sb_info {
+	struct squashfs_super_block	sblk;
+	int			devblksize;
+	int			devblksize_log2;
+	int			swap;
+	struct squashfs_cache	*block_cache;
+	struct squashfs_fragment_cache	*fragment;
+	int			next_cache;
+	int			next_fragment;
+	int			next_meta_index;
+	unsigned int		*uid;
+	unsigned int		*guid;
+	long long		*fragment_index;
+	unsigned int		*fragment_index_2;
+	unsigned int		read_size;
+	char			*read_data;
+	char			*read_page;
+	struct semaphore	read_data_mutex;
+	struct semaphore	read_page_mutex;
+	struct semaphore	block_cache_mutex;
+	struct semaphore	fragment_mutex;
+	struct semaphore	meta_index_mutex;
+	wait_queue_head_t	waitq;
+	wait_queue_head_t	fragment_wait_queue;
+	struct meta_index	*meta_index;
+	struct inode		*(*iget)(struct super_block *s,  squashfs_inode_t \
+				inode);
+	long long		(*read_blocklist)(struct inode *inode, int \
+				index, int readahead_blks, char *block_list, \
+				unsigned short **block_p, unsigned int *bsize);
+	int			(*read_fragment_index_table)(struct super_block *s);
+};
+#endif
diff -urN oldtree/init/do_mounts_rd.c newtree/init/do_mounts_rd.c
--- oldtree/init/do_mounts_rd.c	1970-01-01 00:00:00.000000000 +0000
+++ newtree/init/do_mounts_rd.c	2006-06-08 17:16:36.000000000 +0000
@@ -0,0 +1,442 @@
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/minix_fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/romfs_fs.h>
+#include <linux/cramfs_fs.h>
+#include <linux/squashfs_fs.h>
+#include <linux/initrd.h>
+#include <linux/string.h>
+
+#include "do_mounts.h"
+
+#define BUILD_CRAMDISK
+
+int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
+
+static int __init prompt_ramdisk(char *str)
+{
+	rd_prompt = simple_strtol(str,NULL,0) & 1;
+	return 1;
+}
+__setup("prompt_ramdisk=", prompt_ramdisk);
+
+int __initdata rd_image_start;		/* starting block # of image */
+
+static int __init ramdisk_start_setup(char *str)
+{
+	rd_image_start = simple_strtol(str,NULL,0);
+	return 1;
+}
+__setup("ramdisk_start=", ramdisk_start_setup);
+
+static int __init crd_load(int in_fd, int out_fd);
+
+/*
+ * This routine tries to find a RAM disk image to load, and returns the
+ * number of blocks to read for a non-compressed image, 0 if the image
+ * is a compressed image, and -1 if an image with the right magic
+ * numbers could not be found.
+ *
+ * We currently check for the following magic numbers:
+ *      squashfs
+ * 	minix
+ * 	ext2
+ *	romfs
+ *	cramfs
+ * 	gzip
+ */
+static int __init 
+identify_ramdisk_image(int fd, int start_block)
+{
+	const int size = 512;
+	struct minix_super_block *minixsb;
+	struct ext2_super_block *ext2sb;
+	struct romfs_super_block *romfsb;
+	struct cramfs_super *cramfsb;
+	struct squashfs_super_block *squashfsb;
+	int nblocks = -1;
+	unsigned char *buf;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == 0)
+		return -1;
+
+	minixsb = (struct minix_super_block *) buf;
+	ext2sb = (struct ext2_super_block *) buf;
+	romfsb = (struct romfs_super_block *) buf;
+	cramfsb = (struct cramfs_super *) buf;
+	squashfsb = (struct squashfs_super_block *) buf;
+	memset(buf, 0xe5, size);
+
+	/*
+	 * Read block 0 to test for gzipped kernel
+	 */
+	sys_lseek(fd, start_block * BLOCK_SIZE, 0);
+	sys_read(fd, buf, size);
+
+	/*
+	 * If it matches the gzip magic numbers, return -1
+	 */
+	if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) {
+		printk(KERN_NOTICE
+		       "RAMDISK: Compressed image found at block %d\n",
+		       start_block);
+		nblocks = 0;
+		goto done;
+	}
+
+	/* romfs is at block zero too */
+	if (romfsb->word0 == ROMSB_WORD0 &&
+	    romfsb->word1 == ROMSB_WORD1) {
+		printk(KERN_NOTICE
+		       "RAMDISK: romfs filesystem found at block %d\n",
+		       start_block);
+		nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
+		goto done;
+	}
+
+	if (cramfsb->magic == CRAMFS_MAGIC) {
+		printk(KERN_NOTICE
+		       "RAMDISK: cramfs filesystem found at block %d\n",
+		       start_block);
+		nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+		goto done;
+	}
+
+	/* squashfs is at block zero too */
+	if (squashfsb->s_magic == SQUASHFS_MAGIC) {
+		printk(KERN_NOTICE
+		       "RAMDISK: squashfs filesystem found at block %d\n",
+		       start_block);
+		nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
+		goto done;
+	}
+
+	/*
+	 * Read block 1 to test for minix and ext2 superblock
+	 */
+	sys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0);
+	sys_read(fd, buf, size);
+
+	/* Try minix */
+	if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
+	    minixsb->s_magic == MINIX_SUPER_MAGIC2) {
+		printk(KERN_NOTICE
+		       "RAMDISK: Minix filesystem found at block %d\n",
+		       start_block);
+		nblocks = minixsb->s_nzones << minixsb->s_log_zone_size;
+		goto done;
+	}
+
+	/* Try ext2 */
+	if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
+		printk(KERN_NOTICE
+		       "RAMDISK: ext2 filesystem found at block %d\n",
+		       start_block);
+		nblocks = le32_to_cpu(ext2sb->s_blocks_count) <<
+			le32_to_cpu(ext2sb->s_log_block_size);
+		goto done;
+	}
+
+	printk(KERN_NOTICE
+	       "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n",
+	       start_block);
+	
+done:
+	sys_lseek(fd, start_block * BLOCK_SIZE, 0);
+	kfree(buf);
+	return nblocks;
+}
+
+int __init rd_load_image(char *from)
+{
+	int res = 0;
+	int in_fd, out_fd;
+	unsigned long rd_blocks, devblocks;
+	int nblocks, i, disk;
+	char *buf = NULL;
+	unsigned short rotate = 0;
+#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
+	char rotator[4] = { '|' , '/' , '-' , '\\' };
+#endif
+
+	out_fd = sys_open("/dev/ram", O_RDWR, 0);
+	if (out_fd < 0)
+		goto out;
+
+	in_fd = sys_open(from, O_RDONLY, 0);
+	if (in_fd < 0)
+		goto noclose_input;
+
+	nblocks = identify_ramdisk_image(in_fd, rd_image_start);
+	if (nblocks < 0)
+		goto done;
+
+	if (nblocks == 0) {
+#ifdef BUILD_CRAMDISK
+		if (crd_load(in_fd, out_fd) == 0)
+			goto successful_load;
+#else
+		printk(KERN_NOTICE
+		       "RAMDISK: Kernel does not support compressed "
+		       "RAM disk images\n");
+#endif
+		goto done;
+	}
+
+	/*
+	 * NOTE NOTE: nblocks is not actually blocks but
+	 * the number of kibibytes of data to load into a ramdisk.
+	 * So any ramdisk block size that is a multiple of 1KiB should
+	 * work when the appropriate ramdisk_blocksize is specified
+	 * on the command line.
+	 *
+	 * The default ramdisk_blocksize is 1KiB and it is generally
+	 * silly to use anything else, so make sure to use 1KiB
+	 * blocksize while generating ext2fs ramdisk-images.
+	 */
+	if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0)
+		rd_blocks = 0;
+	else
+		rd_blocks >>= 1;
+
+	if (nblocks > rd_blocks) {
+		printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n",
+		       nblocks, rd_blocks);
+		goto done;
+	}
+		
+	/*
+	 * OK, time to copy in the data
+	 */
+	if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0)
+		devblocks = 0;
+	else
+		devblocks >>= 1;
+
+	if (strcmp(from, "/initrd.image") == 0)
+		devblocks = nblocks;
+
+	if (devblocks == 0) {
+		printk(KERN_ERR "RAMDISK: could not determine device size\n");
+		goto done;
+	}
+
+	buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
+	if (buf == 0) {
+		printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
+		goto done;
+	}
+
+	printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
+		nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
+	for (i = 0, disk = 1; i < nblocks; i++) {
+		if (i && (i % devblocks == 0)) {
+			printk("done disk #%d.\n", disk++);
+			rotate = 0;
+			if (sys_close(in_fd)) {
+				printk("Error closing the disk.\n");
+				goto noclose_input;
+			}
+			change_floppy("disk #%d", disk);
+			in_fd = sys_open(from, O_RDONLY, 0);
+			if (in_fd < 0)  {
+				printk("Error opening disk.\n");
+				goto noclose_input;
+			}
+			printk("Loading disk #%d... ", disk);
+		}
+		sys_read(in_fd, buf, BLOCK_SIZE);
+		sys_write(out_fd, buf, BLOCK_SIZE);
+#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
+		if (!(i % 16)) {
+			printk("%c\b", rotator[rotate & 0x3]);
+			rotate++;
+		}
+#endif
+	}
+	printk("done.\n");
+
+successful_load:
+	res = 1;
+done:
+	sys_close(in_fd);
+noclose_input:
+	sys_close(out_fd);
+out:
+	kfree(buf);
+	sys_unlink("/dev/ram");
+	return res;
+}
+
+int __init rd_load_disk(int n)
+{
+	if (rd_prompt)
+		change_floppy("root floppy disk to be loaded into RAM disk");
+	create_dev("/dev/root", ROOT_DEV, root_device_name);
+	create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL);
+	return rd_load_image("/dev/root");
+}
+
+#ifdef BUILD_CRAMDISK
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+
+#ifndef memzero
+#define memzero(s, n)     memset ((s), 0, (n))
+#endif
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define INBUFSIZ 4096
+#define WSIZE 0x8000    /* window size--must be a power of two, and */
+			/*  at least 32K for zip's deflate method */
+
+static uch *inbuf;
+static uch *window;
+
+static unsigned insize;  /* valid bytes in inbuf */
+static unsigned inptr;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt;  /* bytes in output buffer */
+static int exit_code;
+static int unzip_error;
+static long bytes_out;
+static int crd_infd, crd_outfd;
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+		
+/* Diagnostic functions (stubbed out) */
+#define Assert(cond,msg)
+#define Trace(x)
+#define Tracev(x)
+#define Tracevv(x)
+#define Tracec(c,x)
+#define Tracecv(c,x)
+
+#define STATIC static
+#define INIT __init
+
+static int  __init fill_inbuf(void);
+static void __init flush_window(void);
+static void __init *malloc(size_t size);
+static void __init free(void *where);
+static void __init error(char *m);
+static void __init gzip_mark(void **);
+static void __init gzip_release(void **);
+
+#include "../lib/inflate.c"
+
+static void __init *malloc(size_t size)
+{
+	return kmalloc(size, GFP_KERNEL);
+}
+
+static void __init free(void *where)
+{
+	kfree(where);
+}
+
+static void __init gzip_mark(void **ptr)
+{
+}
+
+static void __init gzip_release(void **ptr)
+{
+}
+
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ * Returning -1 does not guarantee that gunzip() will ever return.
+ */
+static int __init fill_inbuf(void)
+{
+	if (exit_code) return -1;
+	
+	insize = sys_read(crd_infd, inbuf, INBUFSIZ);
+	if (insize == 0) {
+		error("RAMDISK: ran out of compressed data");
+		return -1;
+	}
+
+	inptr = 1;
+
+	return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void __init flush_window(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n, written;
+    uch *in, ch;
+    
+    written = sys_write(crd_outfd, window, outcnt);
+    if (written != outcnt && unzip_error == 0) {
+	printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n",
+	       written, outcnt, bytes_out);
+	unzip_error = 1;
+    }
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+	    ch = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void __init error(char *x)
+{
+	printk(KERN_ERR "%s\n", x);
+	exit_code = 1;
+	unzip_error = 1;
+}
+
+static int __init crd_load(int in_fd, int out_fd)
+{
+	int result;
+
+	insize = 0;		/* valid bytes in inbuf */
+	inptr = 0;		/* index of next byte to be processed in inbuf */
+	outcnt = 0;		/* bytes in output buffer */
+	exit_code = 0;
+	bytes_out = 0;
+	crc = (ulg)0xffffffffL; /* shift register contents */
+
+	crd_infd = in_fd;
+	crd_outfd = out_fd;
+	inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
+	if (inbuf == 0) {
+		printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n");
+		return -1;
+	}
+	window = kmalloc(WSIZE, GFP_KERNEL);
+	if (window == 0) {
+		printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n");
+		kfree(inbuf);
+		return -1;
+	}
+	makecrc();
+	result = gunzip();
+	if (unzip_error)
+		result = 1;
+	kfree(inbuf);
+	kfree(window);
+	return result;
+}
+
+#endif  /* BUILD_CRAMDISK */
