diff options
author | Roman Yeryomin <roman@advem.lv> | 2013-05-17 20:40:24 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2013-05-17 20:40:24 +0300 |
commit | e6d87036412b952cb083eff2dc716aee97a771f2 (patch) | |
tree | 273dd3daaa85553832d3cc6d48276229dc7fbe09 /target/linux/realtek/patches-2.6.30/0003-rsdk-fs-nonewfiles.patch | |
parent | a18fec42221baa52fff4c5ffd45ec8f32e3add36 (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.patch | 1048 |
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, §); ++ 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, §); ++ 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, §); ++ 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, §); ++ 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, §); ++ 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, §); ++ 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, §); ++ 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" |