summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch
diff options
context:
space:
mode:
authorRoman Yeryomin <roman@advem.lv>2013-05-17 20:40:24 +0300
committerRoman Yeryomin <roman@advem.lv>2013-05-17 20:40:24 +0300
commite6d87036412b952cb083eff2dc716aee97a771f2 (patch)
tree273dd3daaa85553832d3cc6d48276229dc7fbe09 /target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch
parenta18fec42221baa52fff4c5ffd45ec8f32e3add36 (diff)
Move to rsdk 3.2.4. Compiles cleanly.
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch')
-rw-r--r--target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch1048
1 files changed, 1048 insertions, 0 deletions
diff --git a/target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch b/target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch
new file mode 100644
index 000000000..9e1397ccd
--- /dev/null
+++ b/target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch
@@ -0,0 +1,1048 @@
+--- linux-2.6.30.9/fs/dcache.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/dcache.c 2013-05-02 01:47:57.547226749 +0300
+@@ -1865,6 +1865,7 @@ out_nolock:
+ shouldnt_be_hashed:
+ spin_unlock(&dcache_lock);
+ BUG();
++ return 0;
+ }
+
+ static int prepend(char **buffer, int *buflen, const char *str, int namelen)
+@@ -2256,7 +2257,7 @@ static void __init dcache_init_early(voi
+ HASH_EARLY,
+ &d_hash_shift,
+ &d_hash_mask,
+- 0);
++ 256*1024);
+
+ for (loop = 0; loop < (1 << d_hash_shift); loop++)
+ INIT_HLIST_HEAD(&dentry_hashtable[loop]);
+@@ -2288,7 +2289,7 @@ static void __init dcache_init(void)
+ 0,
+ &d_hash_shift,
+ &d_hash_mask,
+- 0);
++ 256*1024);
+
+ for (loop = 0; loop < (1 << d_hash_shift); loop++)
+ INIT_HLIST_HEAD(&dentry_hashtable[loop]);
+--- linux-2.6.30.9/fs/hostfs/Makefile 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/hostfs/Makefile 2013-05-02 01:47:57.650226741 +0300
+@@ -8,4 +8,4 @@ hostfs-objs := hostfs_kern.o hostfs_user
+ obj-y :=
+ obj-$(CONFIG_HOSTFS) += hostfs.o
+
+-include arch/um/scripts/Makefile.rules
++#include arch/um/scripts/Makefile.rules
+--- linux-2.6.30.9/fs/inode.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/inode.c 2013-05-02 01:47:57.656226740 +0300
+@@ -1520,7 +1521,7 @@ void __init inode_init_early(void)
+ HASH_EARLY,
+ &i_hash_shift,
+ &i_hash_mask,
+- 0);
++ 256*1024);
+
+ for (loop = 0; loop < (1 << i_hash_shift); loop++)
+ INIT_HLIST_HEAD(&inode_hashtable[loop]);
+@@ -1551,7 +1552,7 @@ void __init inode_init(void)
+ 0,
+ &i_hash_shift,
+ &i_hash_mask,
+- 0);
++ 256*1024);
+
+ for (loop = 0; loop < (1 << i_hash_shift); loop++)
+ INIT_HLIST_HEAD(&inode_hashtable[loop]);
+--- linux-2.6.30.9/fs/jffs2/file.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/jffs2/file.c 2013-05-02 01:47:57.669226739 +0300
+@@ -18,6 +18,7 @@
+ #include <linux/crc32.h>
+ #include <linux/jffs2.h>
+ #include "nodelist.h"
++#include <asm/cacheflush.h>
+
+ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+@@ -96,6 +97,7 @@ static int jffs2_do_readpage_nolock (str
+ }
+
+ flush_dcache_page(pg);
++ __flush_cache_all();
+ kunmap(pg);
+
+ D2(printk(KERN_DEBUG "readpage finished\n"));
+--- linux-2.6.30.9/fs/jffs2/super.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/jffs2/super.c 2013-05-02 01:47:57.674226739 +0300
+@@ -209,6 +209,7 @@ static struct file_system_type jffs2_fs_
+ .name = "jffs2",
+ .get_sb = jffs2_get_sb,
+ .kill_sb = jffs2_kill_sb,
++ .fs_flags = FS_REQUIRES_DEV, // pkshih: add to make mount_block_root() try this fs
+ };
+
+ static int __init init_jffs2_fs(void)
+--- linux-2.6.30.9/fs/partitions/msdos.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/partitions/msdos.c 2013-05-02 01:47:58.094226705 +0300
+@@ -31,6 +31,508 @@
+ */
+ #include <asm/unaligned.h>
+
++#ifdef CONFIG_4KB_HARDDISK_SUPPORT
++#define SYS_IND(p) get_unaligned(&p->sys_ind)
++
++static inline sector_t nr_sects(struct partition *p)
++{
++ return (sector_t)get_unaligned_le32(&p->nr_sects);
++}
++
++static inline sector_t start_sect(struct partition *p)
++{
++ return (sector_t)get_unaligned_le32(&p->start_sect);
++}
++
++static inline int is_extended_partition(struct partition *p)
++{
++ return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
++ SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
++ SYS_IND(p) == LINUX_EXTENDED_PARTITION);
++}
++
++#define MSDOS_LABEL_MAGIC1 0x55
++#define MSDOS_LABEL_MAGIC2 0xAA
++
++static inline int
++msdos_magic_present(unsigned char *p)
++{
++ return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
++}
++
++/* Value is EBCDIC 'IBMA' */
++#define AIX_LABEL_MAGIC1 0xC9
++#define AIX_LABEL_MAGIC2 0xC2
++#define AIX_LABEL_MAGIC3 0xD4
++#define AIX_LABEL_MAGIC4 0xC1
++static int aix_magic_present(unsigned char *p, struct block_device *bdev)
++{
++ struct partition *pt = (struct partition *) (p + 0x1be);
++ Sector sect;
++ unsigned char *d;
++ int slot, ret = 0;
++
++ if (!(p[0] == AIX_LABEL_MAGIC1 &&
++ p[1] == AIX_LABEL_MAGIC2 &&
++ p[2] == AIX_LABEL_MAGIC3 &&
++ p[3] == AIX_LABEL_MAGIC4))
++ return 0;
++ /* Assume the partition table is valid if Linux partitions exists */
++ for (slot = 1; slot <= 4; slot++, pt++) {
++ if (pt->sys_ind == LINUX_SWAP_PARTITION ||
++ pt->sys_ind == LINUX_RAID_PARTITION ||
++ pt->sys_ind == LINUX_DATA_PARTITION ||
++ pt->sys_ind == LINUX_LVM_PARTITION ||
++ is_extended_partition(pt))
++ return 0;
++ }
++ d = read_dev_sector(bdev, 7, &sect);
++ if (d) {
++ if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
++ ret = 1;
++ put_dev_sector(sect);
++ };
++ return ret;
++}
++
++/*
++ * Create devices for each logical partition in an extended partition.
++ * The logical partitions form a linked list, with each entry being
++ * a partition table with two entries. The first entry
++ * is the real data partition (with a start relative to the partition
++ * table start). The second is a pointer to the next logical partition
++ * (with a start relative to the entire extended partition).
++ * We do not create a Linux partition for the partition tables, but
++ * only for the actual data partitions.
++ */
++
++static void
++parse_extended(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t first_sector, sector_t first_size)
++{
++ struct partition *p;
++ Sector sect;
++ unsigned char *data;
++ sector_t this_sector, this_size;
++ sector_t sector_size = bdev_hardsect_size(bdev) / 512;
++ int loopct = 0; /* number of links followed
++ without finding a data partition */
++ int i;
++
++ this_sector = first_sector;
++ this_size = first_size;
++
++ while (1) {
++ if (++loopct > 100)
++ return;
++ if (state->next == state->limit)
++ return;
++ data = read_dev_sector(bdev, this_sector, &sect);
++ if (!data)
++ return;
++
++ if (!msdos_magic_present(data + 510))
++ goto done;
++
++ p = (struct partition *) (data + 0x1be);
++
++ /*
++ * Usually, the first entry is the real data partition,
++ * the 2nd entry is the next extended partition, or empty,
++ * and the 3rd and 4th entries are unused.
++ * However, DRDOS sometimes has the extended partition as
++ * the first entry (when the data partition is empty),
++ * and OS/2 seems to use all four entries.
++ */
++
++ /*
++ * First process the data partition(s)
++ */
++ for (i=0; i<4; i++, p++) {
++ sector_t offs, size, next;
++ if (!nr_sects(p) || is_extended_partition(p))
++ continue;
++
++ /* Check the 3rd and 4th entries -
++ these sometimes contain random garbage */
++ offs = start_sect(p)*sector_size;
++ size = nr_sects(p)*sector_size;
++ next = this_sector + offs;
++ if (i >= 2) {
++ if (offs + size > this_size)
++ continue;
++ if (next < first_sector)
++ continue;
++ if (next + size > first_sector + first_size)
++ continue;
++ }
++
++ put_partition(state, state->next, next, size);
++ if (SYS_IND(p) == LINUX_RAID_PARTITION)
++ state->parts[state->next].flags = ADDPART_FLAG_RAID;
++ loopct = 0;
++ if (++state->next == state->limit)
++ goto done;
++ }
++ /*
++ * Next, process the (first) extended partition, if present.
++ * (So far, there seems to be no reason to make
++ * parse_extended() recursive and allow a tree
++ * of extended partitions.)
++ * It should be a link to the next logical partition.
++ */
++ p -= 4;
++ for (i=0; i<4; i++, p++)
++ if (nr_sects(p) && is_extended_partition(p))
++ break;
++ if (i == 4)
++ goto done; /* nothing left to do */
++
++ this_sector = first_sector + start_sect(p) * sector_size;
++ this_size = nr_sects(p) * sector_size;
++ put_dev_sector(sect);
++ }
++done:
++ put_dev_sector(sect);
++}
++
++/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
++ indicates linux swap. Be careful before believing this is Solaris. */
++
++static void
++parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t offset, sector_t size, int origin)
++{
++#ifdef CONFIG_SOLARIS_X86_PARTITION
++ Sector sect;
++ struct solaris_x86_vtoc *v;
++ int i;
++ short max_nparts;
++
++ v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
++ if (!v)
++ return;
++ if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
++ put_dev_sector(sect);
++ return;
++ }
++ printk(" %s%d: <solaris:", state->name, origin);
++ if (le32_to_cpu(v->v_version) != 1) {
++ printk(" cannot handle version %d vtoc>\n",
++ le32_to_cpu(v->v_version));
++ put_dev_sector(sect);
++ return;
++ }
++ /* Ensure we can handle previous case of VTOC with 8 entries gracefully */
++ max_nparts = le16_to_cpu (v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
++ for (i=0; i<max_nparts && state->next<state->limit; i++) {
++ struct solaris_x86_slice *s = &v->v_slice[i];
++ if (s->s_size == 0)
++ continue;
++ printk(" [s%d]", i);
++ /* solaris partitions are relative to current MS-DOS
++ * one; must add the offset of the current partition */
++ put_partition(state, state->next++,
++ le32_to_cpu(s->s_start)+offset,
++ le32_to_cpu(s->s_size));
++ }
++ put_dev_sector(sect);
++ printk(" >\n");
++#endif
++}
++
++#if defined(CONFIG_BSD_DISKLABEL)
++/*
++ * Create devices for BSD partitions listed in a disklabel, under a
++ * dos-like partition. See parse_extended() for more information.
++ */
++static void
++parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t offset, sector_t size, int origin, char *flavour,
++ int max_partitions)
++{
++ Sector sect;
++ struct bsd_disklabel *l;
++ struct bsd_partition *p;
++
++ l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
++ if (!l)
++ return;
++ if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
++ put_dev_sector(sect);
++ return;
++ }
++ printk(" %s%d: <%s:", state->name, origin, flavour);
++
++ if (le16_to_cpu(l->d_npartitions) < max_partitions)
++ max_partitions = le16_to_cpu(l->d_npartitions);
++ for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
++ sector_t bsd_start, bsd_size;
++
++ if (state->next == state->limit)
++ break;
++ if (p->p_fstype == BSD_FS_UNUSED)
++ continue;
++ bsd_start = le32_to_cpu(p->p_offset);
++ bsd_size = le32_to_cpu(p->p_size);
++ if (offset == bsd_start && size == bsd_size)
++ /* full parent partition, we have it already */
++ continue;
++ if (offset > bsd_start || offset+size < bsd_start+bsd_size) {
++ printk("bad subpartition - ignored\n");
++ continue;
++ }
++ put_partition(state, state->next++, bsd_start, bsd_size);
++ }
++ put_dev_sector(sect);
++ if (le16_to_cpu(l->d_npartitions) > max_partitions)
++ printk(" (ignored %d more)",
++ le16_to_cpu(l->d_npartitions) - max_partitions);
++ printk(" >\n");
++}
++#endif
++
++static void
++parse_freebsd(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t offset, sector_t size, int origin)
++{
++#ifdef CONFIG_BSD_DISKLABEL
++ parse_bsd(state, bdev, offset, size, origin,
++ "bsd", BSD_MAXPARTITIONS);
++#endif
++}
++
++static void
++parse_netbsd(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t offset, sector_t size, int origin)
++{
++#ifdef CONFIG_BSD_DISKLABEL
++ parse_bsd(state, bdev, offset, size, origin,
++ "netbsd", BSD_MAXPARTITIONS);
++#endif
++}
++
++static void
++parse_openbsd(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t offset, sector_t size, int origin)
++{
++#ifdef CONFIG_BSD_DISKLABEL
++ parse_bsd(state, bdev, offset, size, origin,
++ "openbsd", OPENBSD_MAXPARTITIONS);
++#endif
++}
++
++/*
++ * Create devices for Unixware partitions listed in a disklabel, under a
++ * dos-like partition. See parse_extended() for more information.
++ */
++static void
++parse_unixware(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t offset, sector_t size, int origin)
++{
++#ifdef CONFIG_UNIXWARE_DISKLABEL
++ Sector sect;
++ struct unixware_disklabel *l;
++ struct unixware_slice *p;
++
++ l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
++ if (!l)
++ return;
++ if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
++ le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
++ put_dev_sector(sect);
++ return;
++ }
++ printk(" %s%d: <unixware:", state->name, origin);
++ p = &l->vtoc.v_slice[1];
++ /* I omit the 0th slice as it is the same as whole disk. */
++ while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
++ if (state->next == state->limit)
++ break;
++
++ if (p->s_label != UNIXWARE_FS_UNUSED)
++ put_partition(state, state->next++,
++ le32_to_cpu(p->start_sect),
++ le32_to_cpu(p->nr_sects));
++ p++;
++ }
++ put_dev_sector(sect);
++ printk(" >\n");
++#endif
++}
++
++/*
++ * Minix 2.0.0/2.0.2 subpartition support.
++ * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
++ * Rajeev V. Pillai <rajeevvp@yahoo.com>
++ */
++static void
++parse_minix(struct parsed_partitions *state, struct block_device *bdev,
++ sector_t offset, sector_t size, int origin)
++{
++#ifdef CONFIG_MINIX_SUBPARTITION
++ Sector sect;
++ unsigned char *data;
++ struct partition *p;
++ int i;
++
++ data = read_dev_sector(bdev, offset, &sect);
++ if (!data)
++ return;
++
++ p = (struct partition *)(data + 0x1be);
++
++ /* The first sector of a Minix partition can have either
++ * a secondary MBR describing its subpartitions, or
++ * the normal boot sector. */
++ if (msdos_magic_present (data + 510) &&
++ SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
++
++ printk(" %s%d: <minix:", state->name, origin);
++ for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
++ if (state->next == state->limit)
++ break;
++ /* add each partition in use */
++ if (SYS_IND(p) == MINIX_PARTITION)
++ put_partition(state, state->next++,
++ start_sect(p), nr_sects(p));
++ }
++ printk(" >\n");
++ }
++ put_dev_sector(sect);
++#endif /* CONFIG_MINIX_SUBPARTITION */
++}
++
++static struct {
++ unsigned char id;
++ void (*parse)(struct parsed_partitions *, struct block_device *,
++ sector_t, sector_t, int);
++} subtypes[] = {
++ {FREEBSD_PARTITION, parse_freebsd},
++ {NETBSD_PARTITION, parse_netbsd},
++ {OPENBSD_PARTITION, parse_openbsd},
++ {MINIX_PARTITION, parse_minix},
++ {UNIXWARE_PARTITION, parse_unixware},
++ {SOLARIS_X86_PARTITION, parse_solaris_x86},
++ {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86},
++ {0, NULL},
++};
++
++int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
++{
++ sector_t sector_size = bdev_hardsect_size(bdev) / 512;
++ Sector sect;
++ unsigned char *data;
++ struct partition *p;
++ struct fat_boot_sector *fb;
++ int slot;
++
++ data = read_dev_sector(bdev, 0, &sect);
++ if (!data)
++ return -1;
++ if (!msdos_magic_present(data + 510)) {
++ put_dev_sector(sect);
++ return 0;
++ }
++
++ if (aix_magic_present(data, bdev)) {
++ put_dev_sector(sect);
++ printk( " [AIX]");
++ return 0;
++ }
++
++ /*
++ * Now that the 55aa signature is present, this is probably
++ * either the boot sector of a FAT filesystem or a DOS-type
++ * partition table. Reject this in case the boot indicator
++ * is not 0 or 0x80.
++ */
++ p = (struct partition *) (data + 0x1be);
++ for (slot = 1; slot <= 4; slot++, p++) {
++ if (p->boot_ind != 0 && p->boot_ind != 0x80) {
++ /*
++ * Even without a valid boot inidicator value
++ * its still possible this is valid FAT filesystem
++ * without a partition table.
++ */
++ fb = (struct fat_boot_sector *) data;
++ if (slot == 1 && fb->reserved && fb->fats
++ && fat_valid_media(fb->media)) {
++ printk("\n");
++ put_dev_sector(sect);
++ return 1;
++ } else {
++ put_dev_sector(sect);
++ return 0;
++ }
++ }
++ }
++
++#ifdef CONFIG_EFI_PARTITION
++ p = (struct partition *) (data + 0x1be);
++ for (slot = 1 ; slot <= 4 ; slot++, p++) {
++ /* If this is an EFI GPT disk, msdos should ignore it. */
++ if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
++ put_dev_sector(sect);
++ return 0;
++ }
++ }
++#endif
++ p = (struct partition *) (data + 0x1be);
++
++ /*
++ * Look for partitions in two passes:
++ * First find the primary and DOS-type extended partitions.
++ * On the second pass look inside *BSD, Unixware and Solaris partitions.
++ */
++
++ state->next = 5;
++ for (slot = 1 ; slot <= 4 ; slot++, p++) {
++ sector_t start = start_sect(p)*sector_size;
++ sector_t size = nr_sects(p)*sector_size;
++ if (!size)
++ continue;
++ if (is_extended_partition(p)) {
++ /* prevent someone doing mkfs or mkswap on an
++ extended partition, but leave room for LILO */
++ put_partition(state, slot, start, size == 1 ? 1 : 2);
++ printk(" <");
++ parse_extended(state, bdev, start, size);
++ printk(" >");
++ continue;
++ }
++ put_partition(state, slot, start, size);
++ if (SYS_IND(p) == LINUX_RAID_PARTITION)
++ state->parts[slot].flags = 1;
++ if (SYS_IND(p) == DM6_PARTITION)
++ printk("[DM]");
++ if (SYS_IND(p) == EZD_PARTITION)
++ printk("[EZD]");
++ }
++
++ printk("\n");
++
++ /* second pass - output for each on a separate line */
++ p = (struct partition *) (0x1be + data);
++ for (slot = 1 ; slot <= 4 ; slot++, p++) {
++ unsigned char id = SYS_IND(p);
++ int n;
++
++ if (!nr_sects(p))
++ continue;
++
++ for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
++ ;
++
++ if (!subtypes[n].parse)
++ continue;
++ subtypes[n].parse(state, bdev, start_sect(p)*sector_size,
++ nr_sects(p)*sector_size, slot);
++ }
++ put_dev_sector(sect);
++ return 1;
++}
++#else
+ #define SYS_IND(p) (get_unaligned(&p->sys_ind))
+ #define NR_SECTS(p) ({ __le32 __a = get_unaligned(&p->nr_sects); \
+ le32_to_cpu(__a); \
+@@ -527,3 +1029,4 @@ int msdos_partition(struct parsed_partit
+ put_dev_sector(sect);
+ return 1;
+ }
++#endif
+--- linux-2.6.30.9/fs/squashfs/block.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/block.c 2013-05-02 01:47:58.139226701 +0300
+@@ -29,16 +29,14 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/mutex.h>
+ #include <linux/string.h>
+ #include <linux/buffer_head.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
+-
++#include "decompressor.h"
+ /*
+ * Read the metadata block length, this is stored in the first two
+ * bytes of the metadata block.
+@@ -153,72 +151,10 @@ int squashfs_read_data(struct super_bloc
+ }
+
+ if (compressed) {
+- int zlib_err = 0, zlib_init = 0;
+-
+- /*
+- * Uncompress block.
+- */
+-
+- mutex_lock(&msblk->read_data_mutex);
+-
+- msblk->stream.avail_out = 0;
+- msblk->stream.avail_in = 0;
+-
+- bytes = length;
+- do {
+- if (msblk->stream.avail_in == 0 && k < b) {
+- avail = min(bytes, msblk->devblksize - offset);
+- bytes -= avail;
+- wait_on_buffer(bh[k]);
+- if (!buffer_uptodate(bh[k]))
+- goto release_mutex;
+-
+- if (avail == 0) {
+- offset = 0;
+- put_bh(bh[k++]);
+- continue;
+- }
+-
+- msblk->stream.next_in = bh[k]->b_data + offset;
+- msblk->stream.avail_in = avail;
+- offset = 0;
+- }
+-
+- if (msblk->stream.avail_out == 0 && page < pages) {
+- msblk->stream.next_out = buffer[page++];
+- msblk->stream.avail_out = PAGE_CACHE_SIZE;
+- }
+-
+- if (!zlib_init) {
+- zlib_err = zlib_inflateInit(&msblk->stream);
+- if (zlib_err != Z_OK) {
+- ERROR("zlib_inflateInit returned"
+- " unexpected result 0x%x,"
+- " srclength %d\n", zlib_err,
+- srclength);
+- goto release_mutex;
+- }
+- zlib_init = 1;
+- }
+-
+- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
+-
+- if (msblk->stream.avail_in == 0 && k < b)
+- put_bh(bh[k++]);
+- } while (zlib_err == Z_OK);
+-
+- if (zlib_err != Z_STREAM_END) {
+- ERROR("zlib_inflate error, data probably corrupt\n");
+- goto release_mutex;
+- }
+-
+- zlib_err = zlib_inflateEnd(&msblk->stream);
+- if (zlib_err != Z_OK) {
+- ERROR("zlib_inflate error, data probably corrupt\n");
+- goto release_mutex;
+- }
+- length = msblk->stream.total_out;
+- mutex_unlock(&msblk->read_data_mutex);
++ length = squashfs_decompress(msblk, buffer, bh, b, offset,
++ length, srclength, pages);
++ if (length < 0)
++ goto read_failure;
+ } else {
+ /*
+ * Block is uncompressed.
+@@ -255,9 +191,6 @@ int squashfs_read_data(struct super_bloc
+ kfree(bh);
+ return length;
+
+-release_mutex:
+- mutex_unlock(&msblk->read_data_mutex);
+-
+ block_release:
+ for (; k < b; k++)
+ put_bh(bh[k]);
+--- linux-2.6.30.9/fs/squashfs/cache.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/cache.c 2013-05-02 01:47:58.139226701 +0300
+@@ -51,7 +51,6 @@
+ #include <linux/sched.h>
+ #include <linux/spinlock.h>
+ #include <linux/wait.h>
+-#include <linux/zlib.h>
+ #include <linux/pagemap.h>
+
+ #include "squashfs_fs.h"
+--- linux-2.6.30.9/fs/squashfs/dir.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/dir.c 2013-05-02 01:47:58.140226701 +0300
+@@ -30,7 +30,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- linux-2.6.30.9/fs/squashfs/export.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/export.c 2013-05-02 01:47:58.140226701 +0300
+@@ -39,7 +39,6 @@
+ #include <linux/vfs.h>
+ #include <linux/dcache.h>
+ #include <linux/exportfs.h>
+-#include <linux/zlib.h>
+ #include <linux/slab.h>
+
+ #include "squashfs_fs.h"
+--- linux-2.6.30.9/fs/squashfs/file.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/file.c 2013-05-02 01:47:58.140226701 +0300
+@@ -47,7 +47,6 @@
+ #include <linux/string.h>
+ #include <linux/pagemap.h>
+ #include <linux/mutex.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- linux-2.6.30.9/fs/squashfs/fragment.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/fragment.c 2013-05-02 01:47:58.141226701 +0300
+@@ -36,7 +36,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- linux-2.6.30.9/fs/squashfs/id.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/id.c 2013-05-02 01:47:58.141226701 +0300
+@@ -34,7 +34,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- linux-2.6.30.9/fs/squashfs/inode.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/inode.c 2013-05-02 01:47:58.141226701 +0300
+@@ -40,7 +40,6 @@
+
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- linux-2.6.30.9/fs/squashfs/Kconfig 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/Kconfig 2013-05-02 01:47:58.139226701 +0300
+@@ -26,6 +26,12 @@ config SQUASHFS
+
+ If unsure, say N.
+
++config SQUASHFS_LZMA
++ bool "Include support for LZMA compressed file systems"
++ depends on SQUASHFS
++ select DECOMPRESS_LZMA
++ select DECOMPRESS_LZMA_NEEDED
++
+ config SQUASHFS_EMBEDDED
+
+ bool "Additional option for memory-constrained systems"
+--- linux-2.6.30.9/fs/squashfs/Makefile 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/Makefile 2013-05-02 01:47:58.139226701 +0300
+@@ -4,4 +4,5 @@
+
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
+-squashfs-y += namei.o super.o symlink.o
++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
++squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o
+--- linux-2.6.30.9/fs/squashfs/namei.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/namei.c 2013-05-02 01:47:58.142226701 +0300
+@@ -57,7 +57,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/dcache.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- linux-2.6.30.9/fs/squashfs/squashfs_fs.h 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/squashfs_fs.h 2013-05-02 01:47:58.142226701 +0300
+@@ -212,6 +212,8 @@ struct meta_index {
+ * definitions for structures on disk
+ */
+ #define ZLIB_COMPRESSION 1
++#define LZMA_COMPRESSION 2
++#define LZO_COMPRESSION 3
+
+ struct squashfs_super_block {
+ __le32 s_magic;
+--- linux-2.6.30.9/fs/squashfs/squashfs_fs_sb.h 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/squashfs_fs_sb.h 2013-05-02 01:47:58.142226701 +0300
+@@ -52,6 +52,7 @@ struct squashfs_cache_entry {
+ };
+
+ struct squashfs_sb_info {
++ const struct squashfs_decompressor *decompressor;
+ int devblksize;
+ int devblksize_log2;
+ struct squashfs_cache *block_cache;
+@@ -64,7 +65,7 @@ struct squashfs_sb_info {
+ struct mutex read_data_mutex;
+ struct mutex meta_index_mutex;
+ struct meta_index *meta_index;
+- z_stream stream;
++ void *stream;
+ __le64 *inode_lookup_table;
+ u64 inode_table;
+ u64 directory_table;
+--- linux-2.6.30.9/fs/squashfs/squashfs.h 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/squashfs.h 2013-05-02 01:47:58.142226701 +0300
+@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squa
+ u64, int);
+ extern int squashfs_read_table(struct super_block *, void *, u64, int);
+
++/* decompressor.c */
++extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
++
+ /* export.c */
+ extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
+ unsigned int);
+@@ -71,7 +74,7 @@ extern struct inode *squashfs_iget(struc
+ extern int squashfs_read_inode(struct inode *, long long);
+
+ /*
+- * Inodes and files operations
++ * Inodes, files and decompressor operations
+ */
+
+ /* dir.c */
+@@ -88,3 +91,9 @@ extern const struct inode_operations squ
+
+ /* symlink.c */
+ extern const struct address_space_operations squashfs_symlink_aops;
++
++/* zlib_wrapper.c */
++extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
++
++/* lzma wrapper.c */
++extern const struct squashfs_decompressor squashfs_lzma_comp_ops;
+--- linux-2.6.30.9/fs/squashfs/super.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/super.c 2013-05-02 01:47:58.143226701 +0300
+@@ -30,38 +30,46 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
++#include <linux/smp_lock.h>
+ #include <linux/mutex.h>
+ #include <linux/pagemap.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/zlib.h>
+ #include <linux/magic.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
++#include "decompressor.h"
+
+ static struct file_system_type squashfs_fs_type;
+-static struct super_operations squashfs_super_ops;
++static const struct super_operations squashfs_super_ops;
+
+-static int supported_squashfs_filesystem(short major, short minor, short comp)
++static const struct squashfs_decompressor *supported_squashfs_filesystem(short
++ major, short minor, short id)
+ {
++ const struct squashfs_decompressor *decompressor;
++
+ if (major < SQUASHFS_MAJOR) {
+ ERROR("Major/Minor mismatch, older Squashfs %d.%d "
+ "filesystems are unsupported\n", major, minor);
+- return -EINVAL;
++ return NULL;
+ } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
+ ERROR("Major/Minor mismatch, trying to mount newer "
+ "%d.%d filesystem\n", major, minor);
+ ERROR("Please update your kernel\n");
+- return -EINVAL;
++ return NULL;
+ }
+
+- if (comp != ZLIB_COMPRESSION)
+- return -EINVAL;
++ decompressor = squashfs_lookup_decompressor(id);
++ if (!decompressor->supported) {
++ ERROR("Filesystem uses \"%s\" compression. This is not "
++ "supported\n", decompressor->name);
++ return NULL;
++ }
+
+- return 0;
++ return decompressor;
+ }
+
+
+@@ -86,13 +94,6 @@ static int squashfs_fill_super(struct su
+ }
+ msblk = sb->s_fs_info;
+
+- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
+- GFP_KERNEL);
+- if (msblk->stream.workspace == NULL) {
+- ERROR("Failed to allocate zlib workspace\n");
+- goto failure;
+- }
+-
+ sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
+ if (sblk == NULL) {
+ ERROR("Failed to allocate squashfs_super_block\n");
+@@ -119,25 +120,25 @@ static int squashfs_fill_super(struct su
+ goto failed_mount;
+ }
+
++ err = -EINVAL;
++
+ /* Check it is a SQUASHFS superblock */
+ sb->s_magic = le32_to_cpu(sblk->s_magic);
+ if (sb->s_magic != SQUASHFS_MAGIC) {
+ if (!silent)
+ ERROR("Can't find a SQUASHFS superblock on %s\n",
+ bdevname(sb->s_bdev, b));
+- err = -EINVAL;
+ goto failed_mount;
+ }
+
+- /* Check the MAJOR & MINOR versions and compression type */
+- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
++ /* Check the MAJOR & MINOR versions and lookup compression type */
++ msblk->decompressor = supported_squashfs_filesystem(
++ le16_to_cpu(sblk->s_major),
+ le16_to_cpu(sblk->s_minor),
+ le16_to_cpu(sblk->compression));
+- if (err < 0)
++ if (msblk->decompressor == NULL)
+ goto failed_mount;
+
+- err = -EINVAL;
+-
+ /*
+ * Check if there's xattrs in the filesystem. These are not
+ * supported in this version, so warn that they will be ignored.
+@@ -204,6 +205,10 @@ static int squashfs_fill_super(struct su
+
+ err = -ENOMEM;
+
++ msblk->stream = squashfs_decompressor_init(msblk);
++ if (msblk->stream == NULL)
++ goto failed_mount;
++
+ msblk->block_cache = squashfs_cache_init("metadata",
+ SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
+ if (msblk->block_cache == NULL)
+@@ -291,17 +296,16 @@ failed_mount:
+ squashfs_cache_delete(msblk->block_cache);
+ squashfs_cache_delete(msblk->fragment_cache);
+ squashfs_cache_delete(msblk->read_page);
++ squashfs_decompressor_free(msblk, msblk->stream);
+ kfree(msblk->inode_lookup_table);
+ kfree(msblk->fragment_index);
+ kfree(msblk->id_table);
+- kfree(msblk->stream.workspace);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ kfree(sblk);
+ return err;
+
+ failure:
+- kfree(msblk->stream.workspace);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ return -ENOMEM;
+@@ -338,18 +342,22 @@ static int squashfs_remount(struct super
+
+ static void squashfs_put_super(struct super_block *sb)
+ {
++ lock_kernel();
++
+ if (sb->s_fs_info) {
+ struct squashfs_sb_info *sbi = sb->s_fs_info;
+ squashfs_cache_delete(sbi->block_cache);
+ squashfs_cache_delete(sbi->fragment_cache);
+ squashfs_cache_delete(sbi->read_page);
++ squashfs_decompressor_free(sbi, sbi->stream);
+ kfree(sbi->id_table);
+ kfree(sbi->fragment_index);
+ kfree(sbi->meta_index);
+- kfree(sbi->stream.workspace);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ }
++
++ unlock_kernel();
+ }
+
+
+@@ -439,7 +447,7 @@ static struct file_system_type squashfs_
+ .fs_flags = FS_REQUIRES_DEV
+ };
+
+-static struct super_operations squashfs_super_ops = {
++static const struct super_operations squashfs_super_ops = {
+ .alloc_inode = squashfs_alloc_inode,
+ .destroy_inode = squashfs_destroy_inode,
+ .statfs = squashfs_statfs,
+--- linux-2.6.30.9/fs/squashfs/symlink.c 2009-10-05 18:38:08.000000000 +0300
++++ linux-2.6.30.9-rsdk/fs/squashfs/symlink.c 2013-05-02 01:47:58.143226701 +0300
+@@ -36,7 +36,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/pagemap.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"