--- 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 #include #include "nodelist.h" +#include 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 +#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: 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; inextlimit; 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: 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 + * Rajeev V. Pillai + */ +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: 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 #include #include -#include #include #include -#include #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 #include #include -#include #include #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 #include #include -#include #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 #include #include -#include #include #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 #include #include -#include #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 #include #include -#include #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 #include #include -#include #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 #include -#include #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 #include #include -#include #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 #include #include +#include #include #include #include #include -#include #include #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 #include #include -#include #include "squashfs_fs.h" #include "squashfs_fs_sb.h"