SOURCES: kernel-livecd-squashfs.patch (NEW) - init
shadzik
shadzik at pld-linux.org
Tue Mar 10 07:00:03 CET 2009
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 <phillip at lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ * inode.c
++ */
++
++#include <linux/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>>
More information about the pld-cvs-commit
mailing list