[PATCH V3 05/17] Squashfs: symlink operations

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/squashfs/symlink.c |  118 +
 1 files changed, 118 insertions(+), 0 deletions(-)

diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
new file mode 100644
index 000..83d8788
--- /dev/null
+++ b/fs/squashfs/symlink.c
@@ -0,0 +1,118 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * symlink.c
+ */
+
+/*
+ * This file implements code to handle symbolic links.
+ *
+ * The data contents of symbolic links are stored inside the symbolic
+ * link inode within the inode table.  This allows the normally small symbolic
+ * link to be compressed as part of the inode table, achieving much greater
+ * compression than if the symbolic link was compressed individually.
+ */
+
+#include linux/fs.h
+#include linux/vfs.h
+#include linux/kernel.h
+#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
+#include squashfs_fs_i.h
+#include squashfs.h
+
+static int squashfs_symlink_readpage(struct file *file, struct page *page)
+{
+   struct inode *inode = page-mapping-host;
+   struct super_block *sb = inode-i_sb;
+   struct squashfs_sb_info *msblk = sb-s_fs_info;
+   int index = page-index  PAGE_CACHE_SHIFT;
+   u64 block = squashfs_i(inode)-start;
+   int offset = squashfs_i(inode)-offset;
+   int length = min_t(int, i_size_read(inode) - index, PAGE_CACHE_SIZE);
+   int bytes, copied;
+   void *pageaddr;
+   struct squashfs_cache_entry *entry;
+
+   TRACE(Entered squashfs_symlink_readpage, page index %ld, start block 
+   %llx, offset %x\n, page-index, block, offset);
+
+   /*
+* Skip index bytes into symlink metadata.
+*/
+   if (index) {
+   bytes = squashfs_read_metadata(sb, NULL, block, offset,
+   index);
+   if (bytes  0) {
+   ERROR(Unable to read symlink [%llx:%x]\n,
+   squashfs_i(inode)-start,
+   squashfs_i(inode)-offset);
+   goto error_out;
+   }
+   }
+
+   /*
+* Read length bytes from symlink metadata.  Squashfs_read_metadata
+* is not used here because it can sleep and we want to use
+* kmap_atomic to map the page.  Instead call the underlying
+* squashfs_cache_get routine.  As length bytes may overlap metadata
+* blocks, we may need to call squashfs_cache_get multiple times.
+*/
+   for (bytes = 0; bytes  length; offset = 0, bytes += copied) {
+   entry = squashfs_cache_get(sb, msblk-block_cache, block, 0);
+   if (entry-error) {
+   ERROR(Unable to read symlink [%llx:%x]\n,
+   squashfs_i(inode)-start,
+   squashfs_i(inode)-offset);
+   squashfs_cache_put(entry);
+   goto error_out;
+   }
+
+   pageaddr = kmap_atomic(page, KM_USER0);
+   copied = squashfs_copy_data(pageaddr + bytes, entry, offset,
+   length - bytes);
+   if (copied == length - bytes)
+   memset(pageaddr + length, 0, PAGE_CACHE_SIZE - length);
+   else
+   block = entry-next_index;
+   kunmap_atomic(pageaddr, KM_USER0);
+   squashfs_cache_put(entry);
+   }
+
+   flush_dcache_page(page);
+   SetPageUptodate(page);
+   unlock_page(page);
+   return 0;
+
+error_out:
+   SetPageError(page);
+   unlock_page(page);
+   return 0;
+}
+
+
+const struct address_space_operations squashfs_symlink_aops = {
+   .readpage = squashfs_symlink_readpage
+};
-- 
1.5.6.3

--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  

[PATCH V3 01/17] Squashfs: inode operations

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/squashfs/inode.c |  346 +++
 1 files changed, 346 insertions(+), 0 deletions(-)

diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
new file mode 100644
index 000..7a63398
--- /dev/null
+++ b/fs/squashfs/inode.c
@@ -0,0 +1,346 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * inode.c
+ */
+
+/*
+ * This file implements code to create and read inodes from disk.
+ *
+ * Inodes in Squashfs are identified by a 48-bit inode which encodes the
+ * location of the compressed metadata block containing the inode, and the byte
+ * offset into that block where the inode is placed (block, offset).
+ *
+ * To maximise compression there are different inodes for each file type
+ * (regular file, directory, device, etc.), the inode contents and length
+ * varying with the type.
+ *
+ * To further maximise compression, two types of regular file inode and
+ * directory inode are defined: inodes optimised for frequently occurring
+ * regular files and directories, and extended types where extra
+ * information has to be stored.
+ */
+
+#include linux/fs.h
+#include linux/vfs.h
+#include linux/zlib.h
+
+#include squashfs_fs.h
+#include squashfs_fs_sb.h
+#include squashfs_fs_i.h
+#include squashfs.h
+
+/*
+ * Initialise VFS inode with the base inode information common to all
+ * Squashfs inode types.  Sqsh_ino contains the unswapped base inode
+ * off disk.
+ */
+static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
+   struct squashfs_base_inode *sqsh_ino)
+{
+   int err;
+
+   err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino-uid), inode-i_uid);
+   if (err)
+   return err;
+
+   err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino-guid), inode-i_gid);
+   if (err)
+   return err;
+
+   inode-i_ino = le32_to_cpu(sqsh_ino-inode_number);
+   inode-i_mtime.tv_sec = le32_to_cpu(sqsh_ino-mtime);
+   inode-i_atime.tv_sec = inode-i_mtime.tv_sec;
+   inode-i_ctime.tv_sec = inode-i_mtime.tv_sec;
+   inode-i_mode = le16_to_cpu(sqsh_ino-mode);
+   inode-i_size = 0;
+
+   return err;
+}
+
+
+struct inode *squashfs_iget(struct super_block *sb, long long ino,
+   unsigned int ino_number)
+{
+   struct inode *inode = iget_locked(sb, ino_number);
+   int err;
+
+   TRACE(Entered squashfs_iget\n);
+
+   if (!inode)
+   return ERR_PTR(-ENOMEM);
+   if (!(inode-i_state  I_NEW))
+   return inode;
+
+   err = squashfs_read_inode(inode, ino);
+   if (err) {
+   iget_failed(inode);
+   return ERR_PTR(err);
+   }
+
+   unlock_new_inode(inode);
+   return inode;
+}
+
+
+/*
+ * Initialise VFS inode by reading inode from inode table (compressed
+ * metadata).  The format and amount of data read depends on type.
+ */
+int squashfs_read_inode(struct inode *inode, long long ino)
+{
+   struct super_block *sb = inode-i_sb;
+   struct squashfs_sb_info *msblk = sb-s_fs_info;
+   u64 block = SQUASHFS_INODE_BLK(ino) + msblk-inode_table;
+   int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
+   union squashfs_inode squashfs_ino;
+   struct squashfs_base_inode *sqshb_ino = squashfs_ino.base;
+
+   TRACE(Entered squashfs_read_inode\n);
+
+   /*
+* Read inode base common to all inode types.
+*/
+   err = squashfs_read_metadata(sb, sqshb_ino, block,
+   offset, sizeof(*sqshb_ino));
+   if (err  0)
+   goto failed_read;
+
+   err = squashfs_new_inode(sb, inode, sqshb_ino);
+   if (err)
+   goto failed_read;
+
+   block = SQUASHFS_INODE_BLK(ino) + msblk-inode_table;
+   offset = SQUASHFS_INODE_OFFSET(ino);
+
+   type = le16_to_cpu(sqshb_ino-inode_type);
+   switch (type) {
+   case SQUASHFS_REG_TYPE: {
+   unsigned int frag_offset, frag_size, frag;
+   u64 frag_blk;
+   struct squashfs_reg_inode *sqsh_ino = 

[PATCH V3 17/17] MAINTAINERS: squashfs entry

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 MAINTAINERS |7 +++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index befacf0..6ed506f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4049,6 +4049,13 @@ L:   cbe-oss-...@ozlabs.org
 W: http://www.ibm.com/developerworks/power/cell/
 S: Supported
 
+SQUASHFS FILE SYSTEM
+P: Phillip Lougher
+M: phil...@lougher.demon.co.uk
+L: squashfs-de...@lists.sourceforge.net (subscribers-only)
+W: http://squashfs.org.uk
+S: Maintained
+
 SRM (Alpha) environment access
 P: Jan-Benedict Glaw
 M: jbg...@lug-owl.de
-- 
1.5.6.3

--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 11/17] Squashfs: block operations

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/squashfs/block.c |  274 +++
 1 files changed, 274 insertions(+), 0 deletions(-)

diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
new file mode 100644
index 000..c837dfc
--- /dev/null
+++ b/fs/squashfs/block.c
@@ -0,0 +1,274 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * block.c
+ */
+
+/*
+ * This file implements the low-level routines to read and decompress
+ * datablocks and metadata blocks.
+ */
+
+#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
+
+/*
+ * Read the metadata block length, this is stored in the first two
+ * bytes of the metadata block.
+ */
+static struct buffer_head *get_block_length(struct super_block *sb,
+   u64 *cur_index, int *offset, int *length)
+{
+   struct squashfs_sb_info *msblk = sb-s_fs_info;
+   struct buffer_head *bh;
+
+   bh = sb_bread(sb, *cur_index);
+   if (bh == NULL)
+   return NULL;
+
+   if (msblk-devblksize - *offset == 1) {
+   *length = (unsigned char) bh-b_data[*offset];
+   put_bh(bh);
+   bh = sb_bread(sb, ++(*cur_index));
+   if (bh == NULL)
+   return NULL;
+   *length |= (unsigned char) bh-b_data[0]  8;
+   *offset = 1;
+   } else {
+   *length = (unsigned char) bh-b_data[*offset] |
+   (unsigned char) bh-b_data[*offset + 1]  8;
+   *offset += 2;
+   }
+
+   return bh;
+}
+
+
+/*
+ * Read and decompress a metadata block or datablock.  Length is non-zero
+ * if a datablock is being read (the size is stored elsewhere in the
+ * filesystem), otherwise the length is obtained from the first two bytes of
+ * the metadata block.  A bit in the length field indicates if the block
+ * is stored uncompressed in the filesystem (usually because compression
+ * generated a larger block - this does occasionally happen with zlib).
+ */
+int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
+   int length, u64 *next_index, int srclength)
+{
+   struct squashfs_sb_info *msblk = sb-s_fs_info;
+   struct buffer_head **bh;
+   int offset = index  ((1  msblk-devblksize_log2) - 1);
+   u64 cur_index = index  msblk-devblksize_log2;
+   int bytes, compressed, b = 0, k = 0, page = 0, avail;
+
+
+   bh = kcalloc((msblk-block_size  msblk-devblksize_log2) + 1,
+   sizeof(*bh), GFP_KERNEL);
+   if (bh == NULL)
+   return -ENOMEM;
+
+   if (length) {
+   /*
+* Datablock.
+*/
+   bytes = -offset;
+   compressed = SQUASHFS_COMPRESSED_BLOCK(length);
+   length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
+   if (next_index)
+   *next_index = index + length;
+
+   TRACE(Block @ 0x%llx, %scompressed size %d, src size %d\n,
+   index, compressed ?  : un, length, srclength);
+
+   if (length  0 || length  srclength ||
+   (index + length)  msblk-bytes_used)
+   goto read_failure;
+
+   for (b = 0; bytes  length; b++, cur_index++) {
+   bh[b] = sb_getblk(sb, cur_index);
+   if (bh[b] == NULL)
+   goto block_release;
+   bytes += msblk-devblksize;
+   }
+   ll_rw_block(READ, b, bh);
+   } else {
+   /*
+* Metadata block.
+*/
+   if ((index + 2)  msblk-bytes_used)
+   goto read_failure;
+
+   bh[0] = get_block_length(sb, cur_index, offset, length);
+   if (bh[0] == NULL)
+   

[PATCH V3 14/17] Squashfs: Kconfig entry

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/Kconfig |   52 
 1 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index ff0e819..2553e0b 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -894,6 +894,58 @@ config CRAMFS
 
  If unsure, say N.
 
+config SQUASHFS
+   tristate SquashFS 4.0 - Squashed file system support
+   depends on BLOCK
+   select ZLIB_INFLATE
+   help
+ Saying Y here includes support for SquashFS 4.0 (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 4.0 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 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
-- 
1.5.6.3

--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 02/17] Squashfs: directory lookup operations

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/squashfs/namei.c |  242 +++
 1 files changed, 242 insertions(+), 0 deletions(-)

diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
new file mode 100644
index 000..9e39865
--- /dev/null
+++ b/fs/squashfs/namei.c
@@ -0,0 +1,242 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * namei.c
+ */
+
+/*
+ * This file implements code to do filename lookup in directories.
+ *
+ * Like inodes, directories are packed into compressed metadata blocks, stored
+ * in a directory table.  Directories are accessed using the start address of
+ * the metablock containing the directory and the offset into the
+ * decompressed block (block, offset).
+ *
+ * Directories are organised in a slightly complex way, and are not simply
+ * a list of file names.  The organisation takes advantage of the
+ * fact that (in most cases) the inodes of the files will be in the same
+ * compressed metadata block, and therefore, can share the start block.
+ * Directories are therefore organised in a two level list, a directory
+ * header containing the shared start block value, and a sequence of directory
+ * entries, each of which share the shared start block.  A new directory header
+ * is written once/if the inode start block changes.  The directory
+ * header/directory entry list is repeated as many times as necessary.
+ *
+ * Directories are sorted, and can contain a directory index to speed up
+ * file lookup.  Directory indexes store one entry per metablock, each entry
+ * storing the index/filename mapping to the first directory header
+ * in each metadata block.  Directories are sorted in alphabetical order,
+ * and at lookup the index is scanned linearly looking for the first filename
+ * alphabetically larger than the filename being looked up.  At this point the
+ * location of the metadata block the filename is in has been found.
+ * The general idea of the index is ensure only one metadata block needs to be
+ * decompressed to do a lookup irrespective of the length of the directory.
+ * This scheme has the advantage that it doesn't require extra memory overhead
+ * and doesn't require much extra storage on disk.
+ */
+
+#include linux/fs.h
+#include linux/vfs.h
+#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
+#include squashfs_fs_i.h
+#include squashfs.h
+
+/*
+ * Lookup name in the directory index, returning the location of the metadata
+ * block containing it, and the directory index this represents.
+ *
+ * If we get an error reading the index then return the part of the index
+ * (if any) we have managed to read - the index isn't essential, just
+ * quicker.
+ */
+static int get_dir_index_using_name(struct super_block *sb,
+   u64 *next_block, int *next_offset, u64 index_start,
+   int index_offset, int i_count, const char *name,
+   int len)
+{
+   struct squashfs_sb_info *msblk = sb-s_fs_info;
+   int i, size, length = 0, err;
+   struct squashfs_dir_index *index;
+   char *str;
+
+   TRACE(Entered get_dir_index_using_name, i_count %d\n, i_count);
+
+   index = kmalloc(sizeof(*index) + SQUASHFS_NAME_LEN * 2 + 2, GFP_KERNEL);
+   if (index == NULL) {
+   ERROR(Failed to allocate squashfs_dir_index\n);
+   goto out;
+   }
+
+   str = index-name[SQUASHFS_NAME_LEN + 1];
+   strncpy(str, name, len);
+   str[len] = '\0';
+
+   for (i = 0; i  i_count; i++) {
+   err = squashfs_read_metadata(sb, index, index_start,
+   index_offset, sizeof(*index));
+   if (err  0)
+   break;
+
+
+   size = le32_to_cpu(index-size) + 1;
+
+   err = squashfs_read_metadata(sb, index-name, index_start,
+   index_offset, size);
+   if (err  0)
+   break;
+
+   index-name[size] = '\0';
+
+   

[PATCH V3 09/17] Squashfs: uid/gid lookup operations

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/squashfs/id.c |   94 ++
 1 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c
new file mode 100644
index 000..3795b83
--- /dev/null
+++ b/fs/squashfs/id.c
@@ -0,0 +1,94 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * id.c
+ */
+
+/*
+ * This file implements code to handle uids and gids.
+ *
+ * For space efficiency regular files store uid and gid indexes, which are
+ * converted to 32-bit uids/gids using an id look up table.  This table is
+ * stored compressed into metadata blocks.  A second index table is used to
+ * locate these.  This second index table for speed of access (and because it
+ * is small) is read at mount time and cached in memory.
+ */
+
+#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
+#include squashfs_fs_i.h
+#include squashfs.h
+
+/*
+ * Map uid/gid index into real 32-bit uid/gid using the id look up table
+ */
+int squashfs_get_id(struct super_block *sb, unsigned int index,
+   unsigned int *id)
+{
+   struct squashfs_sb_info *msblk = sb-s_fs_info;
+   int block = SQUASHFS_ID_BLOCK(index);
+   int offset = SQUASHFS_ID_BLOCK_OFFSET(index);
+   u64 start_block = le64_to_cpu(msblk-id_table[block]);
+   __le32 disk_id;
+   int err;
+
+   err = squashfs_read_metadata(sb, disk_id, start_block, offset,
+   sizeof(disk_id));
+   if (err  0)
+   return err;
+
+   *id = le32_to_cpu(disk_id);
+   return 0;
+}
+
+
+/*
+ * Read uncompressed id lookup table indexes from disk into memory
+ */
+__le64 *squashfs_read_id_index_table(struct super_block *sb,
+   u64 id_table_start, unsigned short no_ids)
+{
+   unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids);
+   __le64 *id_table;
+   int err;
+
+   TRACE(In read_id_index_table, length %d\n, length);
+
+   /* Allocate id lookup table indexes */
+   id_table = kmalloc(length, GFP_KERNEL);
+   if (id_table == NULL) {
+   ERROR(Failed to allocate id index table\n);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   err = squashfs_read_table(sb, id_table, id_table_start, length);
+   if (err  0) {
+   ERROR(unable to read id index table\n);
+   kfree(id_table);
+   return ERR_PTR(err);
+   }
+
+   return id_table;
+}
-- 
1.5.6.3

--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 10/17] Squashfs: cache operations

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/squashfs/cache.c |  412 +++
 1 files changed, 412 insertions(+), 0 deletions(-)

diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
new file mode 100644
index 000..f29eda1
--- /dev/null
+++ b/fs/squashfs/cache.c
@@ -0,0 +1,412 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * cache.c
+ */
+
+/*
+ * Blocks in Squashfs are compressed.  To avoid repeatedly decompressing
+ * recently accessed data Squashfs uses two small metadata and fragment caches.
+ *
+ * This file implements a generic cache implementation used for both caches,
+ * plus functions layered ontop of the generic cache implementation to
+ * access the metadata and fragment caches.
+ *
+ * To avoid out of memory and fragmentation isssues with vmalloc the cache
+ * uses sequences of kmalloced PAGE_CACHE_SIZE buffers.
+ *
+ * It should be noted that the cache is not used for file datablocks, these
+ * are decompressed and cached in the page-cache in the normal way.  The
+ * cache is only used to temporarily cache fragment and metadata blocks
+ * which have been read as as a result of a metadata (i.e. inode or
+ * directory) or fragment access.  Because metadata and fragments are packed
+ * together into blocks (to gain greater compression) the read of a particular
+ * piece of metadata or fragment will retrieve other metadata/fragments which
+ * have been packed with it, these because of locality-of-reference may be read
+ * in the near future. Temporarily caching them ensures they are available for
+ * near future access without requiring an additional read and decompress.
+ */
+
+#include linux/fs.h
+#include linux/vfs.h
+#include linux/slab.h
+#include linux/vmalloc.h
+#include linux/sched.h
+#include linux/spinlock.h
+#include linux/wait.h
+#include linux/zlib.h
+#include linux/pagemap.h
+
+#include squashfs_fs.h
+#include squashfs_fs_sb.h
+#include squashfs_fs_i.h
+#include squashfs.h
+
+/*
+ * Look-up block in cache, and increment usage count.  If not in cache, read
+ * and decompress it from disk.
+ */
+struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb,
+   struct squashfs_cache *cache, u64 block, int length)
+{
+   int i, n;
+   struct squashfs_cache_entry *entry;
+
+   spin_lock(cache-lock);
+
+   while (1) {
+   for (i = 0; i  cache-entries; i++)
+   if (cache-entry[i].block == block)
+   break;
+
+   if (i == cache-entries) {
+   /*
+* Block not in cache, if all cache entries are used
+* go to sleep waiting for one to become available.
+*/
+   if (cache-unused == 0) {
+   cache-num_waiters++;
+   spin_unlock(cache-lock);
+   wait_event(cache-wait_queue, cache-unused);
+   spin_lock(cache-lock);
+   cache-num_waiters--;
+   continue;
+   }
+
+   /*
+* At least one unused cache entry.  A simple
+* round-robin strategy is used to choose the entry to
+* be evicted from the cache.
+*/
+   i = cache-next_blk;
+   for (n = 0; n  cache-entries; n++) {
+   if (cache-entry[i].refcount == 0)
+   break;
+   i = (i + 1) % cache-entries;
+   }
+
+   cache-next_blk = (i + 1) % cache-entries;
+   entry = cache-entry[i];
+
+   /*
+* Initialise choosen cache entry, and fill it in from
+* disk.
+*/
+   cache-unused--;
+   entry-block = block;
+  

Re: [PATCH 1/3]: Replace kernel/timeconst.pl with kernel/timeconst.sh

2009-01-05 Thread Bernd Petrovitsch
On Son, 2009-01-04 at 22:50 -0600, Rob Landley wrote:
 On Sunday 04 January 2009 18:15:30 Bernd Petrovitsch wrote:
[...]
  ACK. A bash can IMHO be expected. Even going for `dash` is IMHO somewhat
  too extreme.
 
 I have yet to encounter a system that uses dash _without_ bash.  (All ubuntu 

Hmm, should be doable with a chroot environment quite cheap and simple.

 variants, even jeos, install bash by default.  They moved the /bin/sh symlink 

Yes, I know (small) embedded systems that have a bash (and not only
one of busybox shells). It eases writing somewhat fast shell scripts
without the need for lots of fork()s+exec()s too .

Bernd
-- 
Firmix Software GmbH   http://www.firmix.at/
mobil: +43 664 4416156 fax: +43 1 7890849-55
  Embedded Linux Development and Services

--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 12/17] Squashfs: header files

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/squashfs/squashfs.h   |   90 ++
 fs/squashfs/squashfs_fs.h|  381 ++
 fs/squashfs/squashfs_fs_i.h  |   45 +
 fs/squashfs/squashfs_fs_sb.h |   76 +
 4 files changed, 592 insertions(+), 0 deletions(-)

diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
new file mode 100644
index 000..6b2515d
--- /dev/null
+++ b/fs/squashfs/squashfs.h
@@ -0,0 +1,90 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * squashfs.h
+ */
+
+#define TRACE(s, args...)  pr_debug(SQUASHFS: s, ## args)
+
+#define ERROR(s, args...)  pr_err(SQUASHFS error: s, ## args)
+
+#define WARNING(s, args...)pr_warning(SQUASHFS: s, ## args)
+
+static inline struct squashfs_inode_info *squashfs_i(struct inode *inode)
+{
+   return list_entry(inode, struct squashfs_inode_info, vfs_inode);
+}
+
+/* block.c */
+extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *,
+   int);
+
+/* cache.c */
+extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
+extern void squashfs_cache_delete(struct squashfs_cache *);
+extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *,
+   struct squashfs_cache *, u64, int);
+extern void squashfs_cache_put(struct squashfs_cache_entry *);
+extern int squashfs_copy_data(void *, struct squashfs_cache_entry *, int, int);
+extern int squashfs_read_metadata(struct super_block *, void *, u64 *,
+   int *, int);
+extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *,
+   u64, int);
+extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block 
*,
+   u64, int);
+extern int squashfs_read_table(struct super_block *, void *, u64, int);
+
+/* export.c */
+extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
+   unsigned int);
+
+/* fragment.c */
+extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *);
+extern __le64 *squashfs_read_fragment_index_table(struct super_block *,
+   u64, unsigned int);
+
+/* id.c */
+extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
+extern __le64 *squashfs_read_id_index_table(struct super_block *, u64,
+   unsigned short);
+
+/* inode.c */
+extern struct inode *squashfs_iget(struct super_block *, long long,
+   unsigned int);
+extern int squashfs_read_inode(struct inode *, long long);
+
+/*
+ * Inodes and files operations
+ */
+
+/* dir.c */
+extern const struct file_operations squashfs_dir_ops;
+
+/* export.c */
+extern const struct export_operations squashfs_export_ops;
+
+/* file.c */
+extern const struct address_space_operations squashfs_aops;
+
+/* namei.c */
+extern const struct inode_operations squashfs_dir_inode_ops;
+
+/* symlink.c */
+extern const struct address_space_operations squashfs_symlink_aops;
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
new file mode 100644
index 000..6840da1
--- /dev/null
+++ b/fs/squashfs/squashfs_fs.h
@@ -0,0 +1,381 @@
+#ifndef SQUASHFS_FS
+#define SQUASHFS_FS
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ * Phillip Lougher phil...@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, 51 Franklin 

Re: [PATCH 1/3]: Replace kernel/timeconst.pl with kernel/timeconst.sh

2009-01-05 Thread Bernd Petrovitsch
On Mon, 2009-01-05 at 02:23 +, Jamie Lokier wrote:
 Bernd Petrovitsch wrote:
   (I have 850 Linux boxes on my network with a bourne shell which
   doesn't do $((...)).  I won't be building kernels on them though :-)
  
  Believe it or not, but there are folks out there who build the firmware
  on ARM 200 MHz NFS-mounted systems natively  (and not simply
  cross-compile it on a 2GHz PC .).
 
 Really?
 
 My 850 Linux boxes are 166MHz ARMs and occasionally NFS-mounted.
 Their /bin/sh does not do $((...)), and Bash is not there at all.

I assume that the NFS-mounted root filesystem is a real distribution.
And on the local flash is a usual busybox based firmware.

 If I were installing GCC natively on them, I'd install GNU Make and a
 proper shell while I were at it.  But I don't know if Bash works

ACK.

 properly without fork()* - or even if GCC does :-)
 
 Perl might be hard, as shared libraries aren't supported by the
 toolchain which targets my ARMs* and Perl likes its loadable modules.

The simplest way to go is probably to use CentOS or Debian or another
ready binary distribution on ARM (or MIPS or PPC or whatever core the
embedded system has) possibly on a custom build kernel (if necessary).

[...]
 (* - No MMU on some ARMs, but I'm working on ARM FDPIC-ELF to add
  proper shared libs.  Feel free to fund this :-)

The above mentioned ARMs have a MMU. Without MMU, it would be truly
insane IMHO.

Bernd
-- 
Firmix Software GmbH   http://www.firmix.at/
mobil: +43 664 4416156 fax: +43 1 7890849-55
  Embedded Linux Development and Services

--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V3 13/17] Squashfs: Makefiles

2009-01-05 Thread Phillip Lougher

Signed-off-by: Phillip Lougher phil...@lougher.demon.co.uk
---
 fs/Makefile  |1 +
 fs/squashfs/Makefile |8 
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/fs/Makefile b/fs/Makefile
index e6f423d..3f8843c 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -73,6 +73,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 --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
new file mode 100644
index 000..8258cf9
--- /dev/null
+++ b/fs/squashfs/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux squashfs routines.
+#
+
+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 += squashfs2_0.o
-- 
1.5.6.3

--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH V3 01/17] Squashfs: inode operations

2009-01-05 Thread Evgeniy Polyakov
Hi.

On Mon, Jan 05, 2009 at 11:08:23AM +, Phillip Lougher 
(phil...@lougher.demon.co.uk) wrote:
 +int squashfs_read_inode(struct inode *inode, long long ino)
 +{
 + struct super_block *sb = inode-i_sb;
 + struct squashfs_sb_info *msblk = sb-s_fs_info;
 + u64 block = SQUASHFS_INODE_BLK(ino) + msblk-inode_table;
 + int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
 + union squashfs_inode squashfs_ino;
 + struct squashfs_base_inode *sqshb_ino = squashfs_ino.base;
 +

What's the size of that union? If big enough it will lead to some
problems.

 + TRACE(Entered squashfs_read_inode\n);
 +
 + /*
 +  * Read inode base common to all inode types.
 +  */
 + err = squashfs_read_metadata(sb, sqshb_ino, block,
 + offset, sizeof(*sqshb_ino));
 + if (err  0)
 + goto failed_read;
 +
 + err = squashfs_new_inode(sb, inode, sqshb_ino);
 + if (err)
 + goto failed_read;
 +
 + block = SQUASHFS_INODE_BLK(ino) + msblk-inode_table;
 + offset = SQUASHFS_INODE_OFFSET(ino);
 +
 + type = le16_to_cpu(sqshb_ino-inode_type);
 + switch (type) {
 + case SQUASHFS_REG_TYPE: {
 + unsigned int frag_offset, frag_size, frag;
 + u64 frag_blk;

Above variables can be moved out of the switch, since they are used in
some other cases too.

-- 
Evgeniy Polyakov
--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/3]: Replace kernel/timeconst.pl with kernel/timeconst.sh

2009-01-05 Thread Rob Landley
On Monday 05 January 2009 09:01:56 Jamie Lokier wrote:
 Bernd Petrovitsch wrote:
  I assume that the NFS-mounted root filesystem is a real distribution.

 Not unless you call uClinux (MMU-less) a real distribution, no.

I want things to be orthogonal.  The following should be completely separate 
steps:

1) Creating a cross compiler
2) building a native development environment
3) booting a native development environment (on real hardware or under and 
emulator)
4) natively building your target system.

You should be able to mix and match.  Crosstool for #1, go download fedora 
for arm instead of #2, qemu or real hardware is your choice for #3, and then 
you should be able to natively build gentoo under an ubuntu host or vice 
versa.  (How is not currently properly documented, but I'm working on that.)

My objection to build systems like buildroot or uClinux is that they bundle 
all this together into a big hairball.  They create their own cross compiler, 
build their own root file system, use their own packaging system, and you have 
to take it all or nothing.

My build system is ruthlessly orthogonal.  I try not to make it depend on 
other bits of _itself_ more than necessary.

   (* - No MMU on some ARMs, but I'm working on ARM FDPIC-ELF to add
proper shared libs.  Feel free to fund this :-)
 
  The above mentioned ARMs have a MMU. Without MMU, it would be truly
  insane IMHO.

 We have similar cross-build issues without MMUs... I.e. that a lot of
 useful packages don't cross-build properly (including many which use
 Autoconf), and it might be easier to make a native build environment
 than to debug and patch all the broken-for-cross-build packages.
 Especially as sometimes they build, but fail at run-time in some
 conditions.

If you can get a version of the same architecture with an mmu you can actually 
build natively on that.  It's not ideal (it's a bit like trying to build i486 
code on an i686; the fact it runs on the host is no guarantee it'll run on the 
target), but it's better than cross compiling.  And most things have a broad 
enough compatible base architecture that you can mostly get away with it.

 But you're right it's probably insane to try.  I haven't dared as I
 suspect GCC and/or Binutils would break too :-)

Oh it does, but you can fix it. :)

 I'm sticking instead with oh well cross-build a few packages by hand
 and just don't even _try_ to use most of the handy software out there.

Cross compiling doesn't scale, and it bit-rots insanely quickly.

 You mentioned ARM Debian.  According to
 http://wiki.debian.org/ArmEabiPort one recommended method of
 bootstrapping it is building natively on an emulated ARM, because
 cross-building is fragile.

That's what my firmware linux project does too.  (I believe I was one of the 
first doing this back in 2006, but there are three or four others out there 
doing it now.)

Native compiling under emulation is an idea whose time has come.  Emulators on 
cheap x86-64 laptops today are about as powerful as high end tricked out build 
servers circa 2001, and Moore's Law continues to advance.  More memory, more 
CPU (maybe via SMP but distcc can take advantage of that today and qemu will 
develop threading someday).  You can throw engineering time at the problem 
(making cross compiling work) or you can throw hardware at the problem (build 
natively and buy fast native or emulator-hosting hardware).  The balance used 
to be in favor of the former; not so much anymore.

That said, my drive for reproducibility and orthogonality says that your 
native development environment must be something you can reproduce entirely 
from source on an arbitrary host.  You can't make cross compiling go away 
entirely, the best you can do is limit it to bootstrapping the native 
environment.  But I want to keep the parts I have to cross compile as small 
and simple as possible, and then run a native build script to get a richer 
environment.  For the past 5+ years my definition has been an environment 
that can rebuild itself under itself is powerful enough, that's all I need to 
cross compile, and from the first time I tried this (late 2002) up until 
2.6.25 that was 7 packages.  That's why I responded to the addition of perl as 
a regression, because for my use case it was.

 -- Jamie

Rob
--
To unsubscribe from this list: send the line unsubscribe linux-embedded in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html