Author: shadzik Date: Tue Mar 10 06:00:03 2009 GMT Module: SOURCES Tag: HEAD ---- Log message: - init
---- Files affected: SOURCES: kernel-livecd-squashfs.patch (NONE -> 1.1) (NEW) ---- Diffs: ================================================================ Index: SOURCES/kernel-livecd-squashfs.patch diff -u /dev/null SOURCES/kernel-livecd-squashfs.patch:1.1 --- /dev/null Tue Mar 10 07:00:04 2009 +++ SOURCES/kernel-livecd-squashfs.patch Tue Mar 10 06:59:58 2009 @@ -0,0 +1,4218 @@ +diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/Kconfig linux-2.6.27-rc4-squashfs3.4/fs/Kconfig +--- linux-2.6.27-rc4/fs/Kconfig 2008-08-11 15:20:41.000000000 +0100 ++++ linux-2.6.27-rc4-squashfs3.4/fs/Kconfig 2008-08-19 18:31:56.000000000 +0100 +@@ -1348,6 +1348,56 @@ config CRAMFS + + If unsure, say N. + ++config SQUASHFS ++ tristate "SquashFS 3.4 - Squashed file system support" ++ select ZLIB_INFLATE ++ help ++ Saying Y here includes support for SquashFS 3.4 (a Compressed ++ Read-Only File System). Squashfs is a highly compressed read-only ++ filesystem for Linux. It uses zlib compression to compress both ++ files, inodes and directories. Inodes in the system are very small ++ and all blocks are packed to minimise data overhead. Block sizes ++ greater than 4K are supported up to a maximum of 1 Mbytes (default ++ block size 128K). SquashFS 3.3 supports 64 bit filesystems and files ++ (larger than 4GB), full uid/gid information, hard links and timestamps. ++ ++ Squashfs is intended for general read-only filesystem use, for ++ archival use (i.e. in cases where a .tar.gz file may be used), and in ++ embedded systems where low overhead is needed. Further information ++ and filesystem tools are available from http://squashfs.sourceforge.net. ++ ++ If you want to compile this as a module ( = code which can be ++ inserted in and removed from the running kernel whenever you want), ++ say M here and read <file:Documentation/modules.txt>. The module ++ will be called squashfs. Note that the root file system (the one ++ containing the directory /) cannot be compiled as a module. ++ ++ If unsure, say N. ++ ++config SQUASHFS_EMBEDDED ++ ++ bool "Additional option for memory-constrained systems" ++ depends on SQUASHFS ++ default n ++ help ++ Saying Y here allows you to specify cache size. ++ ++ If unsure, say N. ++ ++config SQUASHFS_FRAGMENT_CACHE_SIZE ++ int "Number of fragments cached" if SQUASHFS_EMBEDDED ++ depends on SQUASHFS ++ default "3" ++ help ++ By default SquashFS caches the last 3 fragments read from ++ the filesystem. Increasing this amount may mean SquashFS ++ has to re-read fragments less often from disk, at the expense ++ of extra system memory. Decreasing this amount will mean ++ SquashFS uses less memory at the expense of extra reads from disk. ++ ++ Note there must be at least one cached fragment. Anything ++ much more than three will probably not make much difference. ++ + config VXFS_FS + tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" + depends on BLOCK +diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/Makefile linux-2.6.27-rc4-squashfs3.4/fs/Makefile +--- linux-2.6.27-rc4/fs/Makefile 2008-08-11 15:20:41.000000000 +0100 ++++ linux-2.6.27-rc4-squashfs3.4/fs/Makefile 2008-08-19 18:31:56.000000000 +0100 +@@ -74,6 +74,7 @@ obj-$(CONFIG_JBD) += jbd/ + obj-$(CONFIG_JBD2) += jbd2/ + obj-$(CONFIG_EXT2_FS) += ext2/ + obj-$(CONFIG_CRAMFS) += cramfs/ ++obj-$(CONFIG_SQUASHFS) += squashfs/ + obj-y += ramfs/ + obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ + obj-$(CONFIG_CODA_FS) += coda/ +diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/squashfs/inode.c linux-2.6.27-rc4-squashfs3.4/fs/squashfs/inode.c +--- linux-2.6.27-rc4/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.27-rc4-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:25:23.000000000 +0100 +@@ -0,0 +1,2173 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher <[email protected]> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * inode.c ++ */ ++ ++#include <linux/squashfs_fs.h> ++#include <linux/module.h> ++#include <linux/zlib.h> ++#include <linux/fs.h> ++#include <linux/squashfs_fs_sb.h> ++#include <linux/squashfs_fs_i.h> ++#include <linux/buffer_head.h> ++#include <linux/vfs.h> ++#include <linux/vmalloc.h> ++#include <linux/spinlock.h> ++#include <linux/smp_lock.h> ++#include <linux/exportfs.h> ++ ++#include "squashfs.h" ++ ++static struct dentry *squashfs_fh_to_dentry(struct super_block *s, ++ struct fid *fid, int fh_len, int fh_type); ++static struct dentry *squashfs_fh_to_parent(struct super_block *s, ++ struct fid *fid, int fh_len, int fh_type); ++static struct dentry *squashfs_get_parent(struct dentry *child); ++static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); ++static int squashfs_statfs(struct dentry *, struct kstatfs *); ++static int squashfs_symlink_readpage(struct file *file, struct page *page); ++static long long read_blocklist(struct inode *inode, int index, ++ int readahead_blks, char *block_list, ++ unsigned short **block_p, unsigned int *bsize); ++static int squashfs_readpage(struct file *file, struct page *page); ++static int squashfs_readdir(struct file *, void *, filldir_t); ++static struct dentry *squashfs_lookup(struct inode *, struct dentry *, ++ struct nameidata *); ++static int squashfs_remount(struct super_block *s, int *flags, char *data); ++static void squashfs_put_super(struct super_block *); ++static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, ++ struct vfsmount *); ++static struct inode *squashfs_alloc_inode(struct super_block *sb); ++static void squashfs_destroy_inode(struct inode *inode); ++static int init_inodecache(void); ++static void destroy_inodecache(void); ++ ++static struct file_system_type squashfs_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "squashfs", ++ .get_sb = squashfs_get_sb, ++ .kill_sb = kill_block_super, ++ .fs_flags = FS_REQUIRES_DEV ++}; ++ ++static const unsigned char squashfs_filetype_table[] = { ++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK ++}; ++ ++static struct super_operations squashfs_super_ops = { ++ .alloc_inode = squashfs_alloc_inode, ++ .destroy_inode = squashfs_destroy_inode, ++ .statfs = squashfs_statfs, ++ .put_super = squashfs_put_super, ++ .remount_fs = squashfs_remount ++}; ++ ++static struct export_operations squashfs_export_ops = { ++ .fh_to_dentry = squashfs_fh_to_dentry, ++ .fh_to_parent = squashfs_fh_to_parent, ++ .get_parent = squashfs_get_parent ++}; ++ ++SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { ++ .readpage = squashfs_symlink_readpage ++}; ++ ++SQSH_EXTERN const struct address_space_operations squashfs_aops = { ++ .readpage = squashfs_readpage ++}; ++ ++static const struct file_operations squashfs_dir_ops = { ++ .read = generic_read_dir, ++ .readdir = squashfs_readdir ++}; ++ ++SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { ++ .lookup = squashfs_lookup ++}; ++ ++ ++static struct buffer_head *get_block_length(struct super_block *s, ++ int *cur_index, int *offset, int *c_byte) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ unsigned short temp; ++ struct buffer_head *bh; ++ ++ if (!(bh = sb_bread(s, *cur_index))) ++ goto out; ++ ++ if (msblk->devblksize - *offset == 1) { ++ if (msblk->swap) ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ else ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ brelse(bh); ++ if (!(bh = sb_bread(s, ++(*cur_index)))) ++ goto out; ++ if (msblk->swap) ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ bh->b_data); ++ else ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ bh->b_data); ++ *c_byte = temp; ++ *offset = 1; ++ } else { ++ if (msblk->swap) { ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ (bh->b_data + *offset + 1)); ++ } else { ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ (bh->b_data + *offset + 1)); ++ } ++ *c_byte = temp; ++ *offset += 2; ++ } ++ ++ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { ++ if (*offset == msblk->devblksize) { ++ brelse(bh); ++ if (!(bh = sb_bread(s, ++(*cur_index)))) ++ goto out; ++ *offset = 0; ++ } ++ if (*((unsigned char *) (bh->b_data + *offset)) != ++ SQUASHFS_MARKER_BYTE) { ++ ERROR("Metadata block marker corrupt @ %x\n", ++ *cur_index); ++ brelse(bh); ++ goto out; ++ } ++ (*offset)++; ++ } ++ return bh; ++ ++out: ++ return NULL; ++} ++ ++ ++SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, ++ long long index, unsigned int length, ++ long long *next_index, int srclength) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ struct buffer_head **bh; ++ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); ++ unsigned int cur_index = index >> msblk->devblksize_log2; ++ int bytes, avail_bytes, b = 0, k = 0; ++ unsigned int compressed; ++ unsigned int c_byte = length; ++ ++ bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * ++ sizeof(struct buffer_head *), GFP_KERNEL); ++ if (bh == NULL) ++ goto read_failure; ++ ++ if (c_byte) { ++ bytes = -offset; ++ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); ++ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); ++ ++ TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, ++ compressed ? "" : "un", (unsigned int) c_byte, srclength); ++ ++ if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) ++ goto read_failure; ++ ++ for (b = 0; bytes < (int) c_byte; b++, cur_index++) { ++ bh[b] = sb_getblk(s, cur_index); ++ if (bh[b] == NULL) ++ goto block_release; ++ bytes += msblk->devblksize; ++ } ++ ll_rw_block(READ, b, bh); ++ } else { ++ if (index < 0 || (index + 2) > sblk->bytes_used) ++ goto read_failure; ++ ++ bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); ++ if (bh[0] == NULL) ++ goto read_failure; ++ b = 1; ++ ++ bytes = msblk->devblksize - offset; ++ compressed = SQUASHFS_COMPRESSED(c_byte); ++ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); ++ ++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed ++ ? "" : "un", (unsigned int) c_byte); ++ ++ if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) ++ goto block_release; ++ ++ for (; bytes < c_byte; b++) { ++ bh[b] = sb_getblk(s, ++cur_index); ++ if (bh[b] == NULL) ++ goto block_release; ++ bytes += msblk->devblksize; ++ } ++ ll_rw_block(READ, b - 1, bh + 1); ++ } ++ ++ if (compressed) { ++ int zlib_err = 0; ++ ++ /* ++ * uncompress block ++ */ ++ ++ mutex_lock(&msblk->read_data_mutex); ++ ++ msblk->stream.next_out = buffer; ++ msblk->stream.avail_out = srclength; ++ ++ for (bytes = 0; k < b; k++) { ++ avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); ++ ++ wait_on_buffer(bh[k]); ++ if (!buffer_uptodate(bh[k])) ++ goto release_mutex; ++ ++ msblk->stream.next_in = bh[k]->b_data + offset; ++ msblk->stream.avail_in = avail_bytes; ++ ++ if (k == 0) { ++ 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; ++ } ++ ++ if (avail_bytes == 0) { ++ offset = 0; ++ brelse(bh[k]); ++ continue; ++ } ++ } ++ ++ zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); ++ if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { ++ ERROR("zlib_inflate returned unexpected result 0x%x," ++ " srclength %d, avail_in %d, avail_out %d\n", zlib_err, ++ srclength, msblk->stream.avail_in, msblk->stream.avail_out); ++ goto release_mutex; ++ } ++ ++ bytes += avail_bytes; ++ offset = 0; ++ brelse(bh[k]); ++ } ++ ++ if (zlib_err != Z_STREAM_END) ++ goto release_mutex; ++ ++ zlib_err = zlib_inflateEnd(&msblk->stream); ++ if (zlib_err != Z_OK) { ++ ERROR("zlib_inflateEnd returned unexpected result 0x%x," ++ " srclength %d\n", zlib_err, srclength); ++ goto release_mutex; ++ } ++ bytes = msblk->stream.total_out; ++ mutex_unlock(&msblk->read_data_mutex); ++ } else { ++ int i; ++ ++ for(i = 0; i < b; i++) { ++ wait_on_buffer(bh[i]); ++ if (!buffer_uptodate(bh[i])) ++ goto block_release; ++ } ++ ++ for (bytes = 0; k < b; k++) { ++ avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); ++ ++ memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); ++ bytes += avail_bytes; ++ offset = 0; ++ brelse(bh[k]); ++ } ++ } ++ ++ if (next_index) ++ *next_index = index + c_byte + (length ? 0 : ++ (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); ++ ++ kfree(bh); ++ return bytes; ++ ++release_mutex: ++ mutex_unlock(&msblk->read_data_mutex); ++ ++block_release: ++ for (; k < b; k++) ++ brelse(bh[k]); ++ ++read_failure: ++ ERROR("sb_bread failed reading block 0x%x\n", cur_index); ++ kfree(bh); ++ return 0; ++} ++ ++ ++static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, ++ struct squashfs_cache *cache, long long block, int length) ++{ ++ int i, n; ++ struct squashfs_cache_entry *entry; ++ ++ spin_lock(&cache->lock); ++ ++ while (1) { ++ for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); ++ ++ if (i == cache->entries) { ++ if (cache->unused_blks == 0) { ++ cache->waiting ++; ++ spin_unlock(&cache->lock); ++ wait_event(cache->wait_queue, cache->unused_blks); ++ spin_lock(&cache->lock); ++ cache->waiting --; ++ continue; ++ } ++ ++ i = cache->next_blk; ++ for (n = 0; n < cache->entries; n++) { ++ if (cache->entry[i].locked == 0) ++ break; ++ i = (i + 1) % cache->entries; ++ } ++ ++ cache->next_blk = (i + 1) % cache->entries; ++ entry = &cache->entry[i]; ++ ++ cache->unused_blks --; ++ entry->block = block; ++ entry->locked = 1; ++ entry->pending = 1; ++ entry->waiting = 0; ++ entry->error = 0; ++ spin_unlock(&cache->lock); ++ ++ entry->length = squashfs_read_data(s, entry->data, ++ block, length, &entry->next_index, cache->block_size); ++ ++ spin_lock(&cache->lock); ++ ++ if (entry->length == 0) ++ entry->error = 1; ++ ++ entry->pending = 0; ++ spin_unlock(&cache->lock); ++ if (entry->waiting) ++ wake_up_all(&entry->wait_queue); ++ goto out; ++ } ++ ++ entry = &cache->entry[i]; ++ if (entry->locked == 0) ++ cache->unused_blks --; ++ entry->locked++; ++ ++ if (entry->pending) { ++ entry->waiting ++; ++ spin_unlock(&cache->lock); ++ wait_event(entry->wait_queue, !entry->pending); ++ goto out; ++ } ++ ++ spin_unlock(&cache->lock); ++ goto out; ++ } ++ ++out: ++ TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, ++ cache->name, entry->block, entry->locked, entry->error); ++ if (entry->error) ++ ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); ++ return entry; ++} ++ ++ ++static void squashfs_cache_put(struct squashfs_cache *cache, ++ struct squashfs_cache_entry *entry) ++{ ++ spin_lock(&cache->lock); ++ entry->locked --; ++ if (entry->locked == 0) { ++ cache->unused_blks ++; ++ spin_unlock(&cache->lock); ++ if (cache->waiting) ++ wake_up(&cache->wait_queue); ++ } else ++ spin_unlock(&cache->lock); ++} ++ ++ ++static void squashfs_cache_delete(struct squashfs_cache *cache) ++{ ++ int i; ++ ++ if (cache == NULL) ++ return; ++ ++ for (i = 0; i < cache->entries; i++) ++ if (cache->entry[i].data) { ++ if (cache->use_vmalloc) ++ vfree(cache->entry[i].data); ++ else ++ kfree(cache->entry[i].data); ++ } ++ ++ kfree(cache); ++} ++ ++ ++static struct squashfs_cache *squashfs_cache_init(char *name, int entries, ++ int block_size, int use_vmalloc) ++{ ++ int i; ++ struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + ++ entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); ++ if (cache == NULL) { ++ ERROR("Failed to allocate %s cache\n", name); ++ goto failed; ++ } ++ ++ cache->next_blk = 0; ++ cache->unused_blks = entries; ++ cache->entries = entries; ++ cache->block_size = block_size; ++ cache->use_vmalloc = use_vmalloc; ++ cache->name = name; ++ cache->waiting = 0; ++ spin_lock_init(&cache->lock); ++ init_waitqueue_head(&cache->wait_queue); ++ ++ for (i = 0; i < entries; i++) { ++ init_waitqueue_head(&cache->entry[i].wait_queue); ++ cache->entry[i].block = SQUASHFS_INVALID_BLK; ++ cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : ++ kmalloc(block_size, GFP_KERNEL); ++ if (cache->entry[i].data == NULL) { ++ ERROR("Failed to allocate %s cache entry\n", name); ++ goto cleanup; ++ } ++ } ++ ++ return cache; ++ ++cleanup: ++ squashfs_cache_delete(cache); ++failed: ++ return NULL; ++} ++ ++ ++SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, ++ long long block, unsigned int offset, ++ int length, long long *next_block, ++ unsigned int *next_offset) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ int bytes, return_length = length; ++ struct squashfs_cache_entry *entry; ++ ++ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); ++ ++ while (1) { ++ entry = squashfs_cache_get(s, msblk->block_cache, block, 0); ++ bytes = entry->length - offset; ++ ++ if (entry->error || bytes < 1) { ++ return_length = 0; ++ goto finish; ++ } else if (bytes >= length) { ++ if (buffer) ++ memcpy(buffer, entry->data + offset, length); ++ if (entry->length - offset == length) { ++ *next_block = entry->next_index; ++ *next_offset = 0; <<Diff was trimmed, longer than 597 lines>> _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
