Commit 31aeb6c815549948571eec988ad9728c27d7a68d

Authored by Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus

* git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus:
  MAINTAINERS: squashfs entry
  Squashfs: documentation
  Squashfs: initrd support
  Squashfs: Kconfig entry
  Squashfs: Makefiles
  Squashfs: header files
  Squashfs: block operations
  Squashfs: cache operations
  Squashfs: uid/gid lookup operations
  Squashfs: fragment block operations
  Squashfs: export operations
  Squashfs: super block operations
  Squashfs: symlink operations
  Squashfs: regular file operations
  Squashfs: directory readdir operations
  Squashfs: directory lookup operations
  Squashfs: inode operations

Showing 21 changed files Side-by-side Diff

Documentation/filesystems/squashfs.txt
  1 +SQUASHFS 4.0 FILESYSTEM
  2 +=======================
  3 +
  4 +Squashfs is a compressed read-only filesystem for Linux.
  5 +It uses zlib compression to compress files, inodes and directories.
  6 +Inodes in the system are very small and all blocks are packed to minimise
  7 +data overhead. Block sizes greater than 4K are supported up to a maximum
  8 +of 1Mbytes (default block size 128K).
  9 +
  10 +Squashfs is intended for general read-only filesystem use, for archival
  11 +use (i.e. in cases where a .tar.gz file may be used), and in constrained
  12 +block device/memory systems (e.g. embedded systems) where low overhead is
  13 +needed.
  14 +
  15 +Mailing list: squashfs-devel@lists.sourceforge.net
  16 +Web site: www.squashfs.org
  17 +
  18 +1. FILESYSTEM FEATURES
  19 +----------------------
  20 +
  21 +Squashfs filesystem features versus Cramfs:
  22 +
  23 + Squashfs Cramfs
  24 +
  25 +Max filesystem size: 2^64 16 MiB
  26 +Max file size: ~ 2 TiB 16 MiB
  27 +Max files: unlimited unlimited
  28 +Max directories: unlimited unlimited
  29 +Max entries per directory: unlimited unlimited
  30 +Max block size: 1 MiB 4 KiB
  31 +Metadata compression: yes no
  32 +Directory indexes: yes no
  33 +Sparse file support: yes no
  34 +Tail-end packing (fragments): yes no
  35 +Exportable (NFS etc.): yes no
  36 +Hard link support: yes no
  37 +"." and ".." in readdir: yes no
  38 +Real inode numbers: yes no
  39 +32-bit uids/gids: yes no
  40 +File creation time: yes no
  41 +Xattr and ACL support: no no
  42 +
  43 +Squashfs compresses data, inodes and directories. In addition, inode and
  44 +directory data are highly compacted, and packed on byte boundaries. Each
  45 +compressed inode is on average 8 bytes in length (the exact length varies on
  46 +file type, i.e. regular file, directory, symbolic link, and block/char device
  47 +inodes have different sizes).
  48 +
  49 +2. USING SQUASHFS
  50 +-----------------
  51 +
  52 +As squashfs is a read-only filesystem, the mksquashfs program must be used to
  53 +create populated squashfs filesystems. This and other squashfs utilities
  54 +can be obtained from http://www.squashfs.org. Usage instructions can be
  55 +obtained from this site also.
  56 +
  57 +
  58 +3. SQUASHFS FILESYSTEM DESIGN
  59 +-----------------------------
  60 +
  61 +A squashfs filesystem consists of seven parts, packed together on a byte
  62 +alignment:
  63 +
  64 + ---------------
  65 + | superblock |
  66 + |---------------|
  67 + | datablocks |
  68 + | & fragments |
  69 + |---------------|
  70 + | inode table |
  71 + |---------------|
  72 + | directory |
  73 + | table |
  74 + |---------------|
  75 + | fragment |
  76 + | table |
  77 + |---------------|
  78 + | export |
  79 + | table |
  80 + |---------------|
  81 + | uid/gid |
  82 + | lookup table |
  83 + ---------------
  84 +
  85 +Compressed data blocks are written to the filesystem as files are read from
  86 +the source directory, and checked for duplicates. Once all file data has been
  87 +written the completed inode, directory, fragment, export and uid/gid lookup
  88 +tables are written.
  89 +
  90 +3.1 Inodes
  91 +----------
  92 +
  93 +Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each
  94 +compressed block is prefixed by a two byte length, the top bit is set if the
  95 +block is uncompressed. A block will be uncompressed if the -noI option is set,
  96 +or if the compressed block was larger than the uncompressed block.
  97 +
  98 +Inodes are packed into the metadata blocks, and are not aligned to block
  99 +boundaries, therefore inodes overlap compressed blocks. Inodes are identified
  100 +by a 48-bit number which encodes the location of the compressed metadata block
  101 +containing the inode, and the byte offset into that block where the inode is
  102 +placed (<block, offset>).
  103 +
  104 +To maximise compression there are different inodes for each file type
  105 +(regular file, directory, device, etc.), the inode contents and length
  106 +varying with the type.
  107 +
  108 +To further maximise compression, two types of regular file inode and
  109 +directory inode are defined: inodes optimised for frequently occurring
  110 +regular files and directories, and extended types where extra
  111 +information has to be stored.
  112 +
  113 +3.2 Directories
  114 +---------------
  115 +
  116 +Like inodes, directories are packed into compressed metadata blocks, stored
  117 +in a directory table. Directories are accessed using the start address of
  118 +the metablock containing the directory and the offset into the
  119 +decompressed block (<block, offset>).
  120 +
  121 +Directories are organised in a slightly complex way, and are not simply
  122 +a list of file names. The organisation takes advantage of the
  123 +fact that (in most cases) the inodes of the files will be in the same
  124 +compressed metadata block, and therefore, can share the start block.
  125 +Directories are therefore organised in a two level list, a directory
  126 +header containing the shared start block value, and a sequence of directory
  127 +entries, each of which share the shared start block. A new directory header
  128 +is written once/if the inode start block changes. The directory
  129 +header/directory entry list is repeated as many times as necessary.
  130 +
  131 +Directories are sorted, and can contain a directory index to speed up
  132 +file lookup. Directory indexes store one entry per metablock, each entry
  133 +storing the index/filename mapping to the first directory header
  134 +in each metadata block. Directories are sorted in alphabetical order,
  135 +and at lookup the index is scanned linearly looking for the first filename
  136 +alphabetically larger than the filename being looked up. At this point the
  137 +location of the metadata block the filename is in has been found.
  138 +The general idea of the index is ensure only one metadata block needs to be
  139 +decompressed to do a lookup irrespective of the length of the directory.
  140 +This scheme has the advantage that it doesn't require extra memory overhead
  141 +and doesn't require much extra storage on disk.
  142 +
  143 +3.3 File data
  144 +-------------
  145 +
  146 +Regular files consist of a sequence of contiguous compressed blocks, and/or a
  147 +compressed fragment block (tail-end packed block). The compressed size
  148 +of each datablock is stored in a block list contained within the
  149 +file inode.
  150 +
  151 +To speed up access to datablocks when reading 'large' files (256 Mbytes or
  152 +larger), the code implements an index cache that caches the mapping from
  153 +block index to datablock location on disk.
  154 +
  155 +The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
  156 +retaining a simple and space-efficient block list on disk. The cache
  157 +is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
  158 +Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
  159 +The index cache is designed to be memory efficient, and by default uses
  160 +16 KiB.
  161 +
  162 +3.4 Fragment lookup table
  163 +-------------------------
  164 +
  165 +Regular files can contain a fragment index which is mapped to a fragment
  166 +location on disk and compressed size using a fragment lookup table. This
  167 +fragment lookup table is itself stored compressed into metadata blocks.
  168 +A second index table is used to locate these. This second index table for
  169 +speed of access (and because it is small) is read at mount time and cached
  170 +in memory.
  171 +
  172 +3.5 Uid/gid lookup table
  173 +------------------------
  174 +
  175 +For space efficiency regular files store uid and gid indexes, which are
  176 +converted to 32-bit uids/gids using an id look up table. This table is
  177 +stored compressed into metadata blocks. A second index table is used to
  178 +locate these. This second index table for speed of access (and because it
  179 +is small) is read at mount time and cached in memory.
  180 +
  181 +3.6 Export table
  182 +----------------
  183 +
  184 +To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems
  185 +can optionally (disabled with the -no-exports Mksquashfs option) contain
  186 +an inode number to inode disk location lookup table. This is required to
  187 +enable Squashfs to map inode numbers passed in filehandles to the inode
  188 +location on disk, which is necessary when the export code reinstantiates
  189 +expired/flushed inodes.
  190 +
  191 +This table is stored compressed into metadata blocks. A second index table is
  192 +used to locate these. This second index table for speed of access (and because
  193 +it is small) is read at mount time and cached in memory.
  194 +
  195 +
  196 +4. TODOS AND OUTSTANDING ISSUES
  197 +-------------------------------
  198 +
  199 +4.1 Todo list
  200 +-------------
  201 +
  202 +Implement Xattr and ACL support. The Squashfs 4.0 filesystem layout has hooks
  203 +for these but the code has not been written. Once the code has been written
  204 +the existing layout should not require modification.
  205 +
  206 +4.2 Squashfs internal cache
  207 +---------------------------
  208 +
  209 +Blocks in Squashfs are compressed. To avoid repeatedly decompressing
  210 +recently accessed data Squashfs uses two small metadata and fragment caches.
  211 +
  212 +The cache is not used for file datablocks, these are decompressed and cached in
  213 +the page-cache in the normal way. The cache is used to temporarily cache
  214 +fragment and metadata blocks which have been read as a result of a metadata
  215 +(i.e. inode or directory) or fragment access. Because metadata and fragments
  216 +are packed together into blocks (to gain greater compression) the read of a
  217 +particular piece of metadata or fragment will retrieve other metadata/fragments
  218 +which have been packed with it, these because of locality-of-reference may be
  219 +read in the near future. Temporarily caching them ensures they are available
  220 +for near future access without requiring an additional read and decompress.
  221 +
  222 +In the future this internal cache may be replaced with an implementation which
  223 +uses the kernel page cache. Because the page cache operates on page sized
  224 +units this may introduce additional complexity in terms of locking and
  225 +associated race conditions.
... ... @@ -4081,6 +4081,13 @@
4081 4081 W: http://www.ibm.com/developerworks/power/cell/
4082 4082 S: Supported
4083 4083  
  4084 +SQUASHFS FILE SYSTEM
  4085 +P: Phillip Lougher
  4086 +M: phillip@lougher.demon.co.uk
  4087 +L: squashfs-devel@lists.sourceforge.net (subscribers-only)
  4088 +W: http://squashfs.org.uk
  4089 +S: Maintained
  4090 +
4084 4091 SRM (Alpha) environment access
4085 4092 P: Jan-Benedict Glaw
4086 4093 M: jbglaw@lug-owl.de
... ... @@ -932,6 +932,58 @@
932 932  
933 933 If unsure, say N.
934 934  
  935 +config SQUASHFS
  936 + tristate "SquashFS 4.0 - Squashed file system support"
  937 + depends on BLOCK
  938 + select ZLIB_INFLATE
  939 + help
  940 + Saying Y here includes support for SquashFS 4.0 (a Compressed
  941 + Read-Only File System). Squashfs is a highly compressed read-only
  942 + filesystem for Linux. It uses zlib compression to compress both
  943 + files, inodes and directories. Inodes in the system are very small
  944 + and all blocks are packed to minimise data overhead. Block sizes
  945 + greater than 4K are supported up to a maximum of 1 Mbytes (default
  946 + block size 128K). SquashFS 4.0 supports 64 bit filesystems and files
  947 + (larger than 4GB), full uid/gid information, hard links and
  948 + timestamps.
  949 +
  950 + Squashfs is intended for general read-only filesystem use, for
  951 + archival use (i.e. in cases where a .tar.gz file may be used), and in
  952 + embedded systems where low overhead is needed. Further information
  953 + and tools are available from http://squashfs.sourceforge.net.
  954 +
  955 + If you want to compile this as a module ( = code which can be
  956 + inserted in and removed from the running kernel whenever you want),
  957 + say M here and read <file:Documentation/modules.txt>. The module
  958 + will be called squashfs. Note that the root file system (the one
  959 + containing the directory /) cannot be compiled as a module.
  960 +
  961 + If unsure, say N.
  962 +
  963 +config SQUASHFS_EMBEDDED
  964 +
  965 + bool "Additional option for memory-constrained systems"
  966 + depends on SQUASHFS
  967 + default n
  968 + help
  969 + Saying Y here allows you to specify cache size.
  970 +
  971 + If unsure, say N.
  972 +
  973 +config SQUASHFS_FRAGMENT_CACHE_SIZE
  974 + int "Number of fragments cached" if SQUASHFS_EMBEDDED
  975 + depends on SQUASHFS
  976 + default "3"
  977 + help
  978 + By default SquashFS caches the last 3 fragments read from
  979 + the filesystem. Increasing this amount may mean SquashFS
  980 + has to re-read fragments less often from disk, at the expense
  981 + of extra system memory. Decreasing this amount will mean
  982 + SquashFS uses less memory at the expense of extra reads from disk.
  983 +
  984 + Note there must be at least one cached fragment. Anything
  985 + much more than three will probably not make much difference.
  986 +
935 987 config VXFS_FS
936 988 tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
937 989 depends on BLOCK
... ... @@ -74,6 +74,7 @@
74 74 obj-$(CONFIG_JBD2) += jbd2/
75 75 obj-$(CONFIG_EXT2_FS) += ext2/
76 76 obj-$(CONFIG_CRAMFS) += cramfs/
  77 +obj-$(CONFIG_SQUASHFS) += squashfs/
77 78 obj-y += ramfs/
78 79 obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
79 80 obj-$(CONFIG_CODA_FS) += coda/
fs/squashfs/Makefile
  1 +#
  2 +# Makefile for the linux squashfs routines.
  3 +#
  4 +
  5 +obj-$(CONFIG_SQUASHFS) += squashfs.o
  6 +squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
  7 +squashfs-y += namei.o super.o symlink.o
  8 +#squashfs-y += squashfs2_0.o
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * block.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements the low-level routines to read and decompress
  26 + * datablocks and metadata blocks.
  27 + */
  28 +
  29 +#include <linux/fs.h>
  30 +#include <linux/vfs.h>
  31 +#include <linux/slab.h>
  32 +#include <linux/mutex.h>
  33 +#include <linux/string.h>
  34 +#include <linux/buffer_head.h>
  35 +#include <linux/zlib.h>
  36 +
  37 +#include "squashfs_fs.h"
  38 +#include "squashfs_fs_sb.h"
  39 +#include "squashfs_fs_i.h"
  40 +#include "squashfs.h"
  41 +
  42 +/*
  43 + * Read the metadata block length, this is stored in the first two
  44 + * bytes of the metadata block.
  45 + */
  46 +static struct buffer_head *get_block_length(struct super_block *sb,
  47 + u64 *cur_index, int *offset, int *length)
  48 +{
  49 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  50 + struct buffer_head *bh;
  51 +
  52 + bh = sb_bread(sb, *cur_index);
  53 + if (bh == NULL)
  54 + return NULL;
  55 +
  56 + if (msblk->devblksize - *offset == 1) {
  57 + *length = (unsigned char) bh->b_data[*offset];
  58 + put_bh(bh);
  59 + bh = sb_bread(sb, ++(*cur_index));
  60 + if (bh == NULL)
  61 + return NULL;
  62 + *length |= (unsigned char) bh->b_data[0] << 8;
  63 + *offset = 1;
  64 + } else {
  65 + *length = (unsigned char) bh->b_data[*offset] |
  66 + (unsigned char) bh->b_data[*offset + 1] << 8;
  67 + *offset += 2;
  68 + }
  69 +
  70 + return bh;
  71 +}
  72 +
  73 +
  74 +/*
  75 + * Read and decompress a metadata block or datablock. Length is non-zero
  76 + * if a datablock is being read (the size is stored elsewhere in the
  77 + * filesystem), otherwise the length is obtained from the first two bytes of
  78 + * the metadata block. A bit in the length field indicates if the block
  79 + * is stored uncompressed in the filesystem (usually because compression
  80 + * generated a larger block - this does occasionally happen with zlib).
  81 + */
  82 +int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
  83 + int length, u64 *next_index, int srclength)
  84 +{
  85 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  86 + struct buffer_head **bh;
  87 + int offset = index & ((1 << msblk->devblksize_log2) - 1);
  88 + u64 cur_index = index >> msblk->devblksize_log2;
  89 + int bytes, compressed, b = 0, k = 0, page = 0, avail;
  90 +
  91 +
  92 + bh = kcalloc((msblk->block_size >> msblk->devblksize_log2) + 1,
  93 + sizeof(*bh), GFP_KERNEL);
  94 + if (bh == NULL)
  95 + return -ENOMEM;
  96 +
  97 + if (length) {
  98 + /*
  99 + * Datablock.
  100 + */
  101 + bytes = -offset;
  102 + compressed = SQUASHFS_COMPRESSED_BLOCK(length);
  103 + length = SQUASHFS_COMPRESSED_SIZE_BLOCK(length);
  104 + if (next_index)
  105 + *next_index = index + length;
  106 +
  107 + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n",
  108 + index, compressed ? "" : "un", length, srclength);
  109 +
  110 + if (length < 0 || length > srclength ||
  111 + (index + length) > msblk->bytes_used)
  112 + goto read_failure;
  113 +
  114 + for (b = 0; bytes < length; b++, cur_index++) {
  115 + bh[b] = sb_getblk(sb, cur_index);
  116 + if (bh[b] == NULL)
  117 + goto block_release;
  118 + bytes += msblk->devblksize;
  119 + }
  120 + ll_rw_block(READ, b, bh);
  121 + } else {
  122 + /*
  123 + * Metadata block.
  124 + */
  125 + if ((index + 2) > msblk->bytes_used)
  126 + goto read_failure;
  127 +
  128 + bh[0] = get_block_length(sb, &cur_index, &offset, &length);
  129 + if (bh[0] == NULL)
  130 + goto read_failure;
  131 + b = 1;
  132 +
  133 + bytes = msblk->devblksize - offset;
  134 + compressed = SQUASHFS_COMPRESSED(length);
  135 + length = SQUASHFS_COMPRESSED_SIZE(length);
  136 + if (next_index)
  137 + *next_index = index + length + 2;
  138 +
  139 + TRACE("Block @ 0x%llx, %scompressed size %d\n", index,
  140 + compressed ? "" : "un", length);
  141 +
  142 + if (length < 0 || length > srclength ||
  143 + (index + length) > msblk->bytes_used)
  144 + goto block_release;
  145 +
  146 + for (; bytes < length; b++) {
  147 + bh[b] = sb_getblk(sb, ++cur_index);
  148 + if (bh[b] == NULL)
  149 + goto block_release;
  150 + bytes += msblk->devblksize;
  151 + }
  152 + ll_rw_block(READ, b - 1, bh + 1);
  153 + }
  154 +
  155 + if (compressed) {
  156 + int zlib_err = 0, zlib_init = 0;
  157 +
  158 + /*
  159 + * Uncompress block.
  160 + */
  161 +
  162 + mutex_lock(&msblk->read_data_mutex);
  163 +
  164 + msblk->stream.avail_out = 0;
  165 + msblk->stream.avail_in = 0;
  166 +
  167 + bytes = length;
  168 + do {
  169 + if (msblk->stream.avail_in == 0 && k < b) {
  170 + avail = min(bytes, msblk->devblksize - offset);
  171 + bytes -= avail;
  172 + wait_on_buffer(bh[k]);
  173 + if (!buffer_uptodate(bh[k]))
  174 + goto release_mutex;
  175 +
  176 + if (avail == 0) {
  177 + offset = 0;
  178 + put_bh(bh[k++]);
  179 + continue;
  180 + }
  181 +
  182 + msblk->stream.next_in = bh[k]->b_data + offset;
  183 + msblk->stream.avail_in = avail;
  184 + offset = 0;
  185 + }
  186 +
  187 + if (msblk->stream.avail_out == 0) {
  188 + msblk->stream.next_out = buffer[page++];
  189 + msblk->stream.avail_out = PAGE_CACHE_SIZE;
  190 + }
  191 +
  192 + if (!zlib_init) {
  193 + zlib_err = zlib_inflateInit(&msblk->stream);
  194 + if (zlib_err != Z_OK) {
  195 + ERROR("zlib_inflateInit returned"
  196 + " unexpected result 0x%x,"
  197 + " srclength %d\n", zlib_err,
  198 + srclength);
  199 + goto release_mutex;
  200 + }
  201 + zlib_init = 1;
  202 + }
  203 +
  204 + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
  205 +
  206 + if (msblk->stream.avail_in == 0 && k < b)
  207 + put_bh(bh[k++]);
  208 + } while (zlib_err == Z_OK);
  209 +
  210 + if (zlib_err != Z_STREAM_END) {
  211 + ERROR("zlib_inflate returned unexpected result"
  212 + " 0x%x, srclength %d, avail_in %d,"
  213 + " avail_out %d\n", zlib_err, srclength,
  214 + msblk->stream.avail_in,
  215 + msblk->stream.avail_out);
  216 + goto release_mutex;
  217 + }
  218 +
  219 + zlib_err = zlib_inflateEnd(&msblk->stream);
  220 + if (zlib_err != Z_OK) {
  221 + ERROR("zlib_inflateEnd returned unexpected result 0x%x,"
  222 + " srclength %d\n", zlib_err, srclength);
  223 + goto release_mutex;
  224 + }
  225 + length = msblk->stream.total_out;
  226 + mutex_unlock(&msblk->read_data_mutex);
  227 + } else {
  228 + /*
  229 + * Block is uncompressed.
  230 + */
  231 + int i, in, pg_offset = 0;
  232 +
  233 + for (i = 0; i < b; i++) {
  234 + wait_on_buffer(bh[i]);
  235 + if (!buffer_uptodate(bh[i]))
  236 + goto block_release;
  237 + }
  238 +
  239 + for (bytes = length; k < b; k++) {
  240 + in = min(bytes, msblk->devblksize - offset);
  241 + bytes -= in;
  242 + while (in) {
  243 + if (pg_offset == PAGE_CACHE_SIZE) {
  244 + page++;
  245 + pg_offset = 0;
  246 + }
  247 + avail = min_t(int, in, PAGE_CACHE_SIZE -
  248 + pg_offset);
  249 + memcpy(buffer[page] + pg_offset,
  250 + bh[k]->b_data + offset, avail);
  251 + in -= avail;
  252 + pg_offset += avail;
  253 + offset += avail;
  254 + }
  255 + offset = 0;
  256 + put_bh(bh[k]);
  257 + }
  258 + }
  259 +
  260 + kfree(bh);
  261 + return length;
  262 +
  263 +release_mutex:
  264 + mutex_unlock(&msblk->read_data_mutex);
  265 +
  266 +block_release:
  267 + for (; k < b; k++)
  268 + put_bh(bh[k]);
  269 +
  270 +read_failure:
  271 + ERROR("sb_bread failed reading block 0x%llx\n", cur_index);
  272 + kfree(bh);
  273 + return -EIO;
  274 +}
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * cache.c
  22 + */
  23 +
  24 +/*
  25 + * Blocks in Squashfs are compressed. To avoid repeatedly decompressing
  26 + * recently accessed data Squashfs uses two small metadata and fragment caches.
  27 + *
  28 + * This file implements a generic cache implementation used for both caches,
  29 + * plus functions layered ontop of the generic cache implementation to
  30 + * access the metadata and fragment caches.
  31 + *
  32 + * To avoid out of memory and fragmentation isssues with vmalloc the cache
  33 + * uses sequences of kmalloced PAGE_CACHE_SIZE buffers.
  34 + *
  35 + * It should be noted that the cache is not used for file datablocks, these
  36 + * are decompressed and cached in the page-cache in the normal way. The
  37 + * cache is only used to temporarily cache fragment and metadata blocks
  38 + * which have been read as as a result of a metadata (i.e. inode or
  39 + * directory) or fragment access. Because metadata and fragments are packed
  40 + * together into blocks (to gain greater compression) the read of a particular
  41 + * piece of metadata or fragment will retrieve other metadata/fragments which
  42 + * have been packed with it, these because of locality-of-reference may be read
  43 + * in the near future. Temporarily caching them ensures they are available for
  44 + * near future access without requiring an additional read and decompress.
  45 + */
  46 +
  47 +#include <linux/fs.h>
  48 +#include <linux/vfs.h>
  49 +#include <linux/slab.h>
  50 +#include <linux/vmalloc.h>
  51 +#include <linux/sched.h>
  52 +#include <linux/spinlock.h>
  53 +#include <linux/wait.h>
  54 +#include <linux/zlib.h>
  55 +#include <linux/pagemap.h>
  56 +
  57 +#include "squashfs_fs.h"
  58 +#include "squashfs_fs_sb.h"
  59 +#include "squashfs_fs_i.h"
  60 +#include "squashfs.h"
  61 +
  62 +/*
  63 + * Look-up block in cache, and increment usage count. If not in cache, read
  64 + * and decompress it from disk.
  65 + */
  66 +struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb,
  67 + struct squashfs_cache *cache, u64 block, int length)
  68 +{
  69 + int i, n;
  70 + struct squashfs_cache_entry *entry;
  71 +
  72 + spin_lock(&cache->lock);
  73 +
  74 + while (1) {
  75 + for (i = 0; i < cache->entries; i++)
  76 + if (cache->entry[i].block == block)
  77 + break;
  78 +
  79 + if (i == cache->entries) {
  80 + /*
  81 + * Block not in cache, if all cache entries are used
  82 + * go to sleep waiting for one to become available.
  83 + */
  84 + if (cache->unused == 0) {
  85 + cache->num_waiters++;
  86 + spin_unlock(&cache->lock);
  87 + wait_event(cache->wait_queue, cache->unused);
  88 + spin_lock(&cache->lock);
  89 + cache->num_waiters--;
  90 + continue;
  91 + }
  92 +
  93 + /*
  94 + * At least one unused cache entry. A simple
  95 + * round-robin strategy is used to choose the entry to
  96 + * be evicted from the cache.
  97 + */
  98 + i = cache->next_blk;
  99 + for (n = 0; n < cache->entries; n++) {
  100 + if (cache->entry[i].refcount == 0)
  101 + break;
  102 + i = (i + 1) % cache->entries;
  103 + }
  104 +
  105 + cache->next_blk = (i + 1) % cache->entries;
  106 + entry = &cache->entry[i];
  107 +
  108 + /*
  109 + * Initialise choosen cache entry, and fill it in from
  110 + * disk.
  111 + */
  112 + cache->unused--;
  113 + entry->block = block;
  114 + entry->refcount = 1;
  115 + entry->pending = 1;
  116 + entry->num_waiters = 0;
  117 + entry->error = 0;
  118 + spin_unlock(&cache->lock);
  119 +
  120 + entry->length = squashfs_read_data(sb, entry->data,
  121 + block, length, &entry->next_index,
  122 + cache->block_size);
  123 +
  124 + spin_lock(&cache->lock);
  125 +
  126 + if (entry->length < 0)
  127 + entry->error = entry->length;
  128 +
  129 + entry->pending = 0;
  130 +
  131 + /*
  132 + * While filling this entry one or more other processes
  133 + * have looked it up in the cache, and have slept
  134 + * waiting for it to become available.
  135 + */
  136 + if (entry->num_waiters) {
  137 + spin_unlock(&cache->lock);
  138 + wake_up_all(&entry->wait_queue);
  139 + } else
  140 + spin_unlock(&cache->lock);
  141 +
  142 + goto out;
  143 + }
  144 +
  145 + /*
  146 + * Block already in cache. Increment refcount so it doesn't
  147 + * get reused until we're finished with it, if it was
  148 + * previously unused there's one less cache entry available
  149 + * for reuse.
  150 + */
  151 + entry = &cache->entry[i];
  152 + if (entry->refcount == 0)
  153 + cache->unused--;
  154 + entry->refcount++;
  155 +
  156 + /*
  157 + * If the entry is currently being filled in by another process
  158 + * go to sleep waiting for it to become available.
  159 + */
  160 + if (entry->pending) {
  161 + entry->num_waiters++;
  162 + spin_unlock(&cache->lock);
  163 + wait_event(entry->wait_queue, !entry->pending);
  164 + } else
  165 + spin_unlock(&cache->lock);
  166 +
  167 + goto out;
  168 + }
  169 +
  170 +out:
  171 + TRACE("Got %s %d, start block %lld, refcount %d, error %d\n",
  172 + cache->name, i, entry->block, entry->refcount, entry->error);
  173 +
  174 + if (entry->error)
  175 + ERROR("Unable to read %s cache entry [%llx]\n", cache->name,
  176 + block);
  177 + return entry;
  178 +}
  179 +
  180 +
  181 +/*
  182 + * Release cache entry, once usage count is zero it can be reused.
  183 + */
  184 +void squashfs_cache_put(struct squashfs_cache_entry *entry)
  185 +{
  186 + struct squashfs_cache *cache = entry->cache;
  187 +
  188 + spin_lock(&cache->lock);
  189 + entry->refcount--;
  190 + if (entry->refcount == 0) {
  191 + cache->unused++;
  192 + /*
  193 + * If there's any processes waiting for a block to become
  194 + * available, wake one up.
  195 + */
  196 + if (cache->num_waiters) {
  197 + spin_unlock(&cache->lock);
  198 + wake_up(&cache->wait_queue);
  199 + return;
  200 + }
  201 + }
  202 + spin_unlock(&cache->lock);
  203 +}
  204 +
  205 +/*
  206 + * Delete cache reclaiming all kmalloced buffers.
  207 + */
  208 +void squashfs_cache_delete(struct squashfs_cache *cache)
  209 +{
  210 + int i, j;
  211 +
  212 + if (cache == NULL)
  213 + return;
  214 +
  215 + for (i = 0; i < cache->entries; i++) {
  216 + if (cache->entry[i].data) {
  217 + for (j = 0; j < cache->pages; j++)
  218 + kfree(cache->entry[i].data[j]);
  219 + kfree(cache->entry[i].data);
  220 + }
  221 + }
  222 +
  223 + kfree(cache->entry);
  224 + kfree(cache);
  225 +}
  226 +
  227 +
  228 +/*
  229 + * Initialise cache allocating the specified number of entries, each of
  230 + * size block_size. To avoid vmalloc fragmentation issues each entry
  231 + * is allocated as a sequence of kmalloced PAGE_CACHE_SIZE buffers.
  232 + */
  233 +struct squashfs_cache *squashfs_cache_init(char *name, int entries,
  234 + int block_size)
  235 +{
  236 + int i, j;
  237 + struct squashfs_cache *cache = kzalloc(sizeof(*cache), GFP_KERNEL);
  238 +
  239 + if (cache == NULL) {
  240 + ERROR("Failed to allocate %s cache\n", name);
  241 + return NULL;
  242 + }
  243 +
  244 + cache->entry = kcalloc(entries, sizeof(*(cache->entry)), GFP_KERNEL);
  245 + if (cache->entry == NULL) {
  246 + ERROR("Failed to allocate %s cache\n", name);
  247 + goto cleanup;
  248 + }
  249 +
  250 + cache->next_blk = 0;
  251 + cache->unused = entries;
  252 + cache->entries = entries;
  253 + cache->block_size = block_size;
  254 + cache->pages = block_size >> PAGE_CACHE_SHIFT;
  255 + cache->name = name;
  256 + cache->num_waiters = 0;
  257 + spin_lock_init(&cache->lock);
  258 + init_waitqueue_head(&cache->wait_queue);
  259 +
  260 + for (i = 0; i < entries; i++) {
  261 + struct squashfs_cache_entry *entry = &cache->entry[i];
  262 +
  263 + init_waitqueue_head(&cache->entry[i].wait_queue);
  264 + entry->cache = cache;
  265 + entry->block = SQUASHFS_INVALID_BLK;
  266 + entry->data = kcalloc(cache->pages, sizeof(void *), GFP_KERNEL);
  267 + if (entry->data == NULL) {
  268 + ERROR("Failed to allocate %s cache entry\n", name);
  269 + goto cleanup;
  270 + }
  271 +
  272 + for (j = 0; j < cache->pages; j++) {
  273 + entry->data[j] = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
  274 + if (entry->data[j] == NULL) {
  275 + ERROR("Failed to allocate %s buffer\n", name);
  276 + goto cleanup;
  277 + }
  278 + }
  279 + }
  280 +
  281 + return cache;
  282 +
  283 +cleanup:
  284 + squashfs_cache_delete(cache);
  285 + return NULL;
  286 +}
  287 +
  288 +
  289 +/*
  290 + * Copy upto length bytes from cache entry to buffer starting at offset bytes
  291 + * into the cache entry. If there's not length bytes then copy the number of
  292 + * bytes available. In all cases return the number of bytes copied.
  293 + */
  294 +int squashfs_copy_data(void *buffer, struct squashfs_cache_entry *entry,
  295 + int offset, int length)
  296 +{
  297 + int remaining = length;
  298 +
  299 + if (length == 0)
  300 + return 0;
  301 + else if (buffer == NULL)
  302 + return min(length, entry->length - offset);
  303 +
  304 + while (offset < entry->length) {
  305 + void *buff = entry->data[offset / PAGE_CACHE_SIZE]
  306 + + (offset % PAGE_CACHE_SIZE);
  307 + int bytes = min_t(int, entry->length - offset,
  308 + PAGE_CACHE_SIZE - (offset % PAGE_CACHE_SIZE));
  309 +
  310 + if (bytes >= remaining) {
  311 + memcpy(buffer, buff, remaining);
  312 + remaining = 0;
  313 + break;
  314 + }
  315 +
  316 + memcpy(buffer, buff, bytes);
  317 + buffer += bytes;
  318 + remaining -= bytes;
  319 + offset += bytes;
  320 + }
  321 +
  322 + return length - remaining;
  323 +}
  324 +
  325 +
  326 +/*
  327 + * Read length bytes from metadata position <block, offset> (block is the
  328 + * start of the compressed block on disk, and offset is the offset into
  329 + * the block once decompressed). Data is packed into consecutive blocks,
  330 + * and length bytes may require reading more than one block.
  331 + */
  332 +int squashfs_read_metadata(struct super_block *sb, void *buffer,
  333 + u64 *block, int *offset, int length)
  334 +{
  335 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  336 + int bytes, copied = length;
  337 + struct squashfs_cache_entry *entry;
  338 +
  339 + TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset);
  340 +
  341 + while (length) {
  342 + entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0);
  343 + if (entry->error)
  344 + return entry->error;
  345 + else if (*offset >= entry->length)
  346 + return -EIO;
  347 +
  348 + bytes = squashfs_copy_data(buffer, entry, *offset, length);
  349 + if (buffer)
  350 + buffer += bytes;
  351 + length -= bytes;
  352 + *offset += bytes;
  353 +
  354 + if (*offset == entry->length) {
  355 + *block = entry->next_index;
  356 + *offset = 0;
  357 + }
  358 +
  359 + squashfs_cache_put(entry);
  360 + }
  361 +
  362 + return copied;
  363 +}
  364 +
  365 +
  366 +/*
  367 + * Look-up in the fragmment cache the fragment located at <start_block> in the
  368 + * filesystem. If necessary read and decompress it from disk.
  369 + */
  370 +struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *sb,
  371 + u64 start_block, int length)
  372 +{
  373 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  374 +
  375 + return squashfs_cache_get(sb, msblk->fragment_cache, start_block,
  376 + length);
  377 +}
  378 +
  379 +
  380 +/*
  381 + * Read and decompress the datablock located at <start_block> in the
  382 + * filesystem. The cache is used here to avoid duplicating locking and
  383 + * read/decompress code.
  384 + */
  385 +struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb,
  386 + u64 start_block, int length)
  387 +{
  388 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  389 +
  390 + return squashfs_cache_get(sb, msblk->read_page, start_block, length);
  391 +}
  392 +
  393 +
  394 +/*
  395 + * Read a filesystem table (uncompressed sequence of bytes) from disk
  396 + */
  397 +int squashfs_read_table(struct super_block *sb, void *buffer, u64 block,
  398 + int length)
  399 +{
  400 + int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
  401 + int i, res;
  402 + void **data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
  403 + if (data == NULL)
  404 + return -ENOMEM;
  405 +
  406 + for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
  407 + data[i] = buffer;
  408 + res = squashfs_read_data(sb, data, block, length |
  409 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length);
  410 + kfree(data);
  411 + return res;
  412 +}
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * dir.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to read directories from disk.
  26 + *
  27 + * See namei.c for a description of directory organisation on disk.
  28 + */
  29 +
  30 +#include <linux/fs.h>
  31 +#include <linux/vfs.h>
  32 +#include <linux/slab.h>
  33 +#include <linux/zlib.h>
  34 +
  35 +#include "squashfs_fs.h"
  36 +#include "squashfs_fs_sb.h"
  37 +#include "squashfs_fs_i.h"
  38 +#include "squashfs.h"
  39 +
  40 +static const unsigned char squashfs_filetype_table[] = {
  41 + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
  42 +};
  43 +
  44 +/*
  45 + * Lookup offset (f_pos) in the directory index, returning the
  46 + * metadata block containing it.
  47 + *
  48 + * If we get an error reading the index then return the part of the index
  49 + * (if any) we have managed to read - the index isn't essential, just
  50 + * quicker.
  51 + */
  52 +static int get_dir_index_using_offset(struct super_block *sb,
  53 + u64 *next_block, int *next_offset, u64 index_start, int index_offset,
  54 + int i_count, u64 f_pos)
  55 +{
  56 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  57 + int err, i, index, length = 0;
  58 + struct squashfs_dir_index dir_index;
  59 +
  60 + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %lld\n",
  61 + i_count, f_pos);
  62 +
  63 + /*
  64 + * Translate from external f_pos to the internal f_pos. This
  65 + * is offset by 3 because we invent "." and ".." entries which are
  66 + * not actually stored in the directory.
  67 + */
  68 + if (f_pos < 3)
  69 + return f_pos;
  70 + f_pos -= 3;
  71 +
  72 + for (i = 0; i < i_count; i++) {
  73 + err = squashfs_read_metadata(sb, &dir_index, &index_start,
  74 + &index_offset, sizeof(dir_index));
  75 + if (err < 0)
  76 + break;
  77 +
  78 + index = le32_to_cpu(dir_index.index);
  79 + if (index > f_pos)
  80 + /*
  81 + * Found the index we're looking for.
  82 + */
  83 + break;
  84 +
  85 + err = squashfs_read_metadata(sb, NULL, &index_start,
  86 + &index_offset, le32_to_cpu(dir_index.size) + 1);
  87 + if (err < 0)
  88 + break;
  89 +
  90 + length = index;
  91 + *next_block = le32_to_cpu(dir_index.start_block) +
  92 + msblk->directory_table;
  93 + }
  94 +
  95 + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  96 +
  97 + /*
  98 + * Translate back from internal f_pos to external f_pos.
  99 + */
  100 + return length + 3;
  101 +}
  102 +
  103 +
  104 +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
  105 +{
  106 + struct inode *inode = file->f_dentry->d_inode;
  107 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  108 + u64 block = squashfs_i(inode)->start + msblk->directory_table;
  109 + int offset = squashfs_i(inode)->offset, length = 0, dir_count, size,
  110 + type, err;
  111 + unsigned int inode_number;
  112 + struct squashfs_dir_header dirh;
  113 + struct squashfs_dir_entry *dire;
  114 +
  115 + TRACE("Entered squashfs_readdir [%llx:%x]\n", block, offset);
  116 +
  117 + dire = kmalloc(sizeof(*dire) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL);
  118 + if (dire == NULL) {
  119 + ERROR("Failed to allocate squashfs_dir_entry\n");
  120 + goto finish;
  121 + }
  122 +
  123 + /*
  124 + * Return "." and ".." entries as the first two filenames in the
  125 + * directory. To maximise compression these two entries are not
  126 + * stored in the directory, and so we invent them here.
  127 + *
  128 + * It also means that the external f_pos is offset by 3 from the
  129 + * on-disk directory f_pos.
  130 + */
  131 + while (file->f_pos < 3) {
  132 + char *name;
  133 + int i_ino;
  134 +
  135 + if (file->f_pos == 0) {
  136 + name = ".";
  137 + size = 1;
  138 + i_ino = inode->i_ino;
  139 + } else {
  140 + name = "..";
  141 + size = 2;
  142 + i_ino = squashfs_i(inode)->parent;
  143 + }
  144 +
  145 + TRACE("Calling filldir(%p, %s, %d, %lld, %d, %d)\n",
  146 + dirent, name, size, file->f_pos, i_ino,
  147 + squashfs_filetype_table[1]);
  148 +
  149 + if (filldir(dirent, name, size, file->f_pos, i_ino,
  150 + squashfs_filetype_table[1]) < 0) {
  151 + TRACE("Filldir returned less than 0\n");
  152 + goto finish;
  153 + }
  154 +
  155 + file->f_pos += size;
  156 + }
  157 +
  158 + length = get_dir_index_using_offset(inode->i_sb, &block, &offset,
  159 + squashfs_i(inode)->dir_idx_start,
  160 + squashfs_i(inode)->dir_idx_offset,
  161 + squashfs_i(inode)->dir_idx_cnt,
  162 + file->f_pos);
  163 +
  164 + while (length < i_size_read(inode)) {
  165 + /*
  166 + * Read directory header
  167 + */
  168 + err = squashfs_read_metadata(inode->i_sb, &dirh, &block,
  169 + &offset, sizeof(dirh));
  170 + if (err < 0)
  171 + goto failed_read;
  172 +
  173 + length += sizeof(dirh);
  174 +
  175 + dir_count = le32_to_cpu(dirh.count) + 1;
  176 + while (dir_count--) {
  177 + /*
  178 + * Read directory entry.
  179 + */
  180 + err = squashfs_read_metadata(inode->i_sb, dire, &block,
  181 + &offset, sizeof(*dire));
  182 + if (err < 0)
  183 + goto failed_read;
  184 +
  185 + size = le16_to_cpu(dire->size) + 1;
  186 +
  187 + err = squashfs_read_metadata(inode->i_sb, dire->name,
  188 + &block, &offset, size);
  189 + if (err < 0)
  190 + goto failed_read;
  191 +
  192 + length += sizeof(*dire) + size;
  193 +
  194 + if (file->f_pos >= length)
  195 + continue;
  196 +
  197 + dire->name[size] = '\0';
  198 + inode_number = le32_to_cpu(dirh.inode_number) +
  199 + ((short) le16_to_cpu(dire->inode_number));
  200 + type = le16_to_cpu(dire->type);
  201 +
  202 + TRACE("Calling filldir(%p, %s, %d, %lld, %x:%x, %d, %d)"
  203 + "\n", dirent, dire->name, size,
  204 + file->f_pos,
  205 + le32_to_cpu(dirh.start_block),
  206 + le16_to_cpu(dire->offset),
  207 + inode_number,
  208 + squashfs_filetype_table[type]);
  209 +
  210 + if (filldir(dirent, dire->name, size, file->f_pos,
  211 + inode_number,
  212 + squashfs_filetype_table[type]) < 0) {
  213 + TRACE("Filldir returned less than 0\n");
  214 + goto finish;
  215 + }
  216 +
  217 + file->f_pos = length;
  218 + }
  219 + }
  220 +
  221 +finish:
  222 + kfree(dire);
  223 + return 0;
  224 +
  225 +failed_read:
  226 + ERROR("Unable to read directory block [%llx:%x]\n", block, offset);
  227 + kfree(dire);
  228 + return 0;
  229 +}
  230 +
  231 +
  232 +const struct file_operations squashfs_dir_ops = {
  233 + .read = generic_read_dir,
  234 + .readdir = squashfs_readdir
  235 +};
fs/squashfs/export.c
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * export.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to make Squashfs filesystems exportable (NFS etc.)
  26 + *
  27 + * The export code uses an inode lookup table to map inode numbers passed in
  28 + * filehandles to an inode location on disk. This table is stored compressed
  29 + * into metadata blocks. A second index table is used to locate these. This
  30 + * second index table for speed of access (and because it is small) is read at
  31 + * mount time and cached in memory.
  32 + *
  33 + * The inode lookup table is used only by the export code, inode disk
  34 + * locations are directly encoded in directories, enabling direct access
  35 + * without an intermediate lookup for all operations except the export ops.
  36 + */
  37 +
  38 +#include <linux/fs.h>
  39 +#include <linux/vfs.h>
  40 +#include <linux/dcache.h>
  41 +#include <linux/exportfs.h>
  42 +#include <linux/zlib.h>
  43 +
  44 +#include "squashfs_fs.h"
  45 +#include "squashfs_fs_sb.h"
  46 +#include "squashfs_fs_i.h"
  47 +#include "squashfs.h"
  48 +
  49 +/*
  50 + * Look-up inode number (ino) in table, returning the inode location.
  51 + */
  52 +static long long squashfs_inode_lookup(struct super_block *sb, int ino_num)
  53 +{
  54 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  55 + int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1);
  56 + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1);
  57 + u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]);
  58 + __le64 ino;
  59 + int err;
  60 +
  61 + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num);
  62 +
  63 + err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino));
  64 + if (err < 0)
  65 + return err;
  66 +
  67 + TRACE("squashfs_inode_lookup, inode = 0x%llx\n",
  68 + (u64) le64_to_cpu(ino));
  69 +
  70 + return le64_to_cpu(ino);
  71 +}
  72 +
  73 +
  74 +static struct dentry *squashfs_export_iget(struct super_block *sb,
  75 + unsigned int ino_num)
  76 +{
  77 + long long ino;
  78 + struct dentry *dentry = ERR_PTR(-ENOENT);
  79 +
  80 + TRACE("Entered squashfs_export_iget\n");
  81 +
  82 + ino = squashfs_inode_lookup(sb, ino_num);
  83 + if (ino >= 0)
  84 + dentry = d_obtain_alias(squashfs_iget(sb, ino, ino_num));
  85 +
  86 + return dentry;
  87 +}
  88 +
  89 +
  90 +static struct dentry *squashfs_fh_to_dentry(struct super_block *sb,
  91 + struct fid *fid, int fh_len, int fh_type)
  92 +{
  93 + if ((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT)
  94 + || fh_len < 2)
  95 + return NULL;
  96 +
  97 + return squashfs_export_iget(sb, fid->i32.ino);
  98 +}
  99 +
  100 +
  101 +static struct dentry *squashfs_fh_to_parent(struct super_block *sb,
  102 + struct fid *fid, int fh_len, int fh_type)
  103 +{
  104 + if (fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4)
  105 + return NULL;
  106 +
  107 + return squashfs_export_iget(sb, fid->i32.parent_ino);
  108 +}
  109 +
  110 +
  111 +static struct dentry *squashfs_get_parent(struct dentry *child)
  112 +{
  113 + struct inode *inode = child->d_inode;
  114 + unsigned int parent_ino = squashfs_i(inode)->parent;
  115 +
  116 + return squashfs_export_iget(inode->i_sb, parent_ino);
  117 +}
  118 +
  119 +
  120 +/*
  121 + * Read uncompressed inode lookup table indexes off disk into memory
  122 + */
  123 +__le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
  124 + u64 lookup_table_start, unsigned int inodes)
  125 +{
  126 + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes);
  127 + __le64 *inode_lookup_table;
  128 + int err;
  129 +
  130 + TRACE("In read_inode_lookup_table, length %d\n", length);
  131 +
  132 + /* Allocate inode lookup table indexes */
  133 + inode_lookup_table = kmalloc(length, GFP_KERNEL);
  134 + if (inode_lookup_table == NULL) {
  135 + ERROR("Failed to allocate inode lookup table\n");
  136 + return ERR_PTR(-ENOMEM);
  137 + }
  138 +
  139 + err = squashfs_read_table(sb, inode_lookup_table, lookup_table_start,
  140 + length);
  141 + if (err < 0) {
  142 + ERROR("unable to read inode lookup table\n");
  143 + kfree(inode_lookup_table);
  144 + return ERR_PTR(err);
  145 + }
  146 +
  147 + return inode_lookup_table;
  148 +}
  149 +
  150 +
  151 +const struct export_operations squashfs_export_ops = {
  152 + .fh_to_dentry = squashfs_fh_to_dentry,
  153 + .fh_to_parent = squashfs_fh_to_parent,
  154 + .get_parent = squashfs_get_parent
  155 +};
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * file.c
  22 + */
  23 +
  24 +/*
  25 + * This file contains code for handling regular files. A regular file
  26 + * consists of a sequence of contiguous compressed blocks, and/or a
  27 + * compressed fragment block (tail-end packed block). The compressed size
  28 + * of each datablock is stored in a block list contained within the
  29 + * file inode (itself stored in one or more compressed metadata blocks).
  30 + *
  31 + * To speed up access to datablocks when reading 'large' files (256 Mbytes or
  32 + * larger), the code implements an index cache that caches the mapping from
  33 + * block index to datablock location on disk.
  34 + *
  35 + * The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
  36 + * retaining a simple and space-efficient block list on disk. The cache
  37 + * is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
  38 + * Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
  39 + * The index cache is designed to be memory efficient, and by default uses
  40 + * 16 KiB.
  41 + */
  42 +
  43 +#include <linux/fs.h>
  44 +#include <linux/vfs.h>
  45 +#include <linux/kernel.h>
  46 +#include <linux/slab.h>
  47 +#include <linux/string.h>
  48 +#include <linux/pagemap.h>
  49 +#include <linux/mutex.h>
  50 +#include <linux/zlib.h>
  51 +
  52 +#include "squashfs_fs.h"
  53 +#include "squashfs_fs_sb.h"
  54 +#include "squashfs_fs_i.h"
  55 +#include "squashfs.h"
  56 +
  57 +/*
  58 + * Locate cache slot in range [offset, index] for specified inode. If
  59 + * there's more than one return the slot closest to index.
  60 + */
  61 +static struct meta_index *locate_meta_index(struct inode *inode, int offset,
  62 + int index)
  63 +{
  64 + struct meta_index *meta = NULL;
  65 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  66 + int i;
  67 +
  68 + mutex_lock(&msblk->meta_index_mutex);
  69 +
  70 + TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
  71 +
  72 + if (msblk->meta_index == NULL)
  73 + goto not_allocated;
  74 +
  75 + for (i = 0; i < SQUASHFS_META_SLOTS; i++) {
  76 + if (msblk->meta_index[i].inode_number == inode->i_ino &&
  77 + msblk->meta_index[i].offset >= offset &&
  78 + msblk->meta_index[i].offset <= index &&
  79 + msblk->meta_index[i].locked == 0) {
  80 + TRACE("locate_meta_index: entry %d, offset %d\n", i,
  81 + msblk->meta_index[i].offset);
  82 + meta = &msblk->meta_index[i];
  83 + offset = meta->offset;
  84 + }
  85 + }
  86 +
  87 + if (meta)
  88 + meta->locked = 1;
  89 +
  90 +not_allocated:
  91 + mutex_unlock(&msblk->meta_index_mutex);
  92 +
  93 + return meta;
  94 +}
  95 +
  96 +
  97 +/*
  98 + * Find and initialise an empty cache slot for index offset.
  99 + */
  100 +static struct meta_index *empty_meta_index(struct inode *inode, int offset,
  101 + int skip)
  102 +{
  103 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  104 + struct meta_index *meta = NULL;
  105 + int i;
  106 +
  107 + mutex_lock(&msblk->meta_index_mutex);
  108 +
  109 + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
  110 +
  111 + if (msblk->meta_index == NULL) {
  112 + /*
  113 + * First time cache index has been used, allocate and
  114 + * initialise. The cache index could be allocated at
  115 + * mount time but doing it here means it is allocated only
  116 + * if a 'large' file is read.
  117 + */
  118 + msblk->meta_index = kcalloc(SQUASHFS_META_SLOTS,
  119 + sizeof(*(msblk->meta_index)), GFP_KERNEL);
  120 + if (msblk->meta_index == NULL) {
  121 + ERROR("Failed to allocate meta_index\n");
  122 + goto failed;
  123 + }
  124 + for (i = 0; i < SQUASHFS_META_SLOTS; i++) {
  125 + msblk->meta_index[i].inode_number = 0;
  126 + msblk->meta_index[i].locked = 0;
  127 + }
  128 + msblk->next_meta_index = 0;
  129 + }
  130 +
  131 + for (i = SQUASHFS_META_SLOTS; i &&
  132 + msblk->meta_index[msblk->next_meta_index].locked; i--)
  133 + msblk->next_meta_index = (msblk->next_meta_index + 1) %
  134 + SQUASHFS_META_SLOTS;
  135 +
  136 + if (i == 0) {
  137 + TRACE("empty_meta_index: failed!\n");
  138 + goto failed;
  139 + }
  140 +
  141 + TRACE("empty_meta_index: returned meta entry %d, %p\n",
  142 + msblk->next_meta_index,
  143 + &msblk->meta_index[msblk->next_meta_index]);
  144 +
  145 + meta = &msblk->meta_index[msblk->next_meta_index];
  146 + msblk->next_meta_index = (msblk->next_meta_index + 1) %
  147 + SQUASHFS_META_SLOTS;
  148 +
  149 + meta->inode_number = inode->i_ino;
  150 + meta->offset = offset;
  151 + meta->skip = skip;
  152 + meta->entries = 0;
  153 + meta->locked = 1;
  154 +
  155 +failed:
  156 + mutex_unlock(&msblk->meta_index_mutex);
  157 + return meta;
  158 +}
  159 +
  160 +
  161 +static void release_meta_index(struct inode *inode, struct meta_index *meta)
  162 +{
  163 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  164 + mutex_lock(&msblk->meta_index_mutex);
  165 + meta->locked = 0;
  166 + mutex_unlock(&msblk->meta_index_mutex);
  167 +}
  168 +
  169 +
  170 +/*
  171 + * Read the next n blocks from the block list, starting from
  172 + * metadata block <start_block, offset>.
  173 + */
  174 +static long long read_indexes(struct super_block *sb, int n,
  175 + u64 *start_block, int *offset)
  176 +{
  177 + int err, i;
  178 + long long block = 0;
  179 + __le32 *blist = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
  180 +
  181 + if (blist == NULL) {
  182 + ERROR("read_indexes: Failed to allocate block_list\n");
  183 + return -ENOMEM;
  184 + }
  185 +
  186 + while (n) {
  187 + int blocks = min_t(int, n, PAGE_CACHE_SIZE >> 2);
  188 +
  189 + err = squashfs_read_metadata(sb, blist, start_block,
  190 + offset, blocks << 2);
  191 + if (err < 0) {
  192 + ERROR("read_indexes: reading block [%llx:%x]\n",
  193 + *start_block, *offset);
  194 + goto failure;
  195 + }
  196 +
  197 + for (i = 0; i < blocks; i++) {
  198 + int size = le32_to_cpu(blist[i]);
  199 + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(size);
  200 + }
  201 + n -= blocks;
  202 + }
  203 +
  204 + kfree(blist);
  205 + return block;
  206 +
  207 +failure:
  208 + kfree(blist);
  209 + return err;
  210 +}
  211 +
  212 +
  213 +/*
  214 + * Each cache index slot has SQUASHFS_META_ENTRIES, each of which
  215 + * can cache one index -> datablock/blocklist-block mapping. We wish
  216 + * to distribute these over the length of the file, entry[0] maps index x,
  217 + * entry[1] maps index x + skip, entry[2] maps index x + 2 * skip, and so on.
  218 + * The larger the file, the greater the skip factor. The skip factor is
  219 + * limited to the size of the metadata cache (SQUASHFS_CACHED_BLKS) to ensure
  220 + * the number of metadata blocks that need to be read fits into the cache.
  221 + * If the skip factor is limited in this way then the file will use multiple
  222 + * slots.
  223 + */
  224 +static inline int calculate_skip(int blocks)
  225 +{
  226 + int skip = blocks / ((SQUASHFS_META_ENTRIES + 1)
  227 + * SQUASHFS_META_INDEXES);
  228 + return min(SQUASHFS_CACHED_BLKS - 1, skip + 1);
  229 +}
  230 +
  231 +
  232 +/*
  233 + * Search and grow the index cache for the specified inode, returning the
  234 + * on-disk locations of the datablock and block list metadata block
  235 + * <index_block, index_offset> for index (scaled to nearest cache index).
  236 + */
  237 +static int fill_meta_index(struct inode *inode, int index,
  238 + u64 *index_block, int *index_offset, u64 *data_block)
  239 +{
  240 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  241 + int skip = calculate_skip(i_size_read(inode) >> msblk->block_log);
  242 + int offset = 0;
  243 + struct meta_index *meta;
  244 + struct meta_entry *meta_entry;
  245 + u64 cur_index_block = squashfs_i(inode)->block_list_start;
  246 + int cur_offset = squashfs_i(inode)->offset;
  247 + u64 cur_data_block = squashfs_i(inode)->start;
  248 + int err, i;
  249 +
  250 + /*
  251 + * Scale index to cache index (cache slot entry)
  252 + */
  253 + index /= SQUASHFS_META_INDEXES * skip;
  254 +
  255 + while (offset < index) {
  256 + meta = locate_meta_index(inode, offset + 1, index);
  257 +
  258 + if (meta == NULL) {
  259 + meta = empty_meta_index(inode, offset + 1, skip);
  260 + if (meta == NULL)
  261 + goto all_done;
  262 + } else {
  263 + offset = index < meta->offset + meta->entries ? index :
  264 + meta->offset + meta->entries - 1;
  265 + meta_entry = &meta->meta_entry[offset - meta->offset];
  266 + cur_index_block = meta_entry->index_block +
  267 + msblk->inode_table;
  268 + cur_offset = meta_entry->offset;
  269 + cur_data_block = meta_entry->data_block;
  270 + TRACE("get_meta_index: offset %d, meta->offset %d, "
  271 + "meta->entries %d\n", offset, meta->offset,
  272 + meta->entries);
  273 + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
  274 + " data_block 0x%llx\n", cur_index_block,
  275 + cur_offset, cur_data_block);
  276 + }
  277 +
  278 + /*
  279 + * If necessary grow cache slot by reading block list. Cache
  280 + * slot is extended up to index or to the end of the slot, in
  281 + * which case further slots will be used.
  282 + */
  283 + for (i = meta->offset + meta->entries; i <= index &&
  284 + i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
  285 + int blocks = skip * SQUASHFS_META_INDEXES;
  286 + long long res = read_indexes(inode->i_sb, blocks,
  287 + &cur_index_block, &cur_offset);
  288 +
  289 + if (res < 0) {
  290 + if (meta->entries == 0)
  291 + /*
  292 + * Don't leave an empty slot on read
  293 + * error allocated to this inode...
  294 + */
  295 + meta->inode_number = 0;
  296 + err = res;
  297 + goto failed;
  298 + }
  299 +
  300 + cur_data_block += res;
  301 + meta_entry = &meta->meta_entry[i - meta->offset];
  302 + meta_entry->index_block = cur_index_block -
  303 + msblk->inode_table;
  304 + meta_entry->offset = cur_offset;
  305 + meta_entry->data_block = cur_data_block;
  306 + meta->entries++;
  307 + offset++;
  308 + }
  309 +
  310 + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
  311 + meta->offset, meta->entries);
  312 +
  313 + release_meta_index(inode, meta);
  314 + }
  315 +
  316 +all_done:
  317 + *index_block = cur_index_block;
  318 + *index_offset = cur_offset;
  319 + *data_block = cur_data_block;
  320 +
  321 + /*
  322 + * Scale cache index (cache slot entry) to index
  323 + */
  324 + return offset * SQUASHFS_META_INDEXES * skip;
  325 +
  326 +failed:
  327 + release_meta_index(inode, meta);
  328 + return err;
  329 +}
  330 +
  331 +
  332 +/*
  333 + * Get the on-disk location and compressed size of the datablock
  334 + * specified by index. Fill_meta_index() does most of the work.
  335 + */
  336 +static int read_blocklist(struct inode *inode, int index, u64 *block)
  337 +{
  338 + u64 start;
  339 + long long blks;
  340 + int offset;
  341 + __le32 size;
  342 + int res = fill_meta_index(inode, index, &start, &offset, block);
  343 +
  344 + TRACE("read_blocklist: res %d, index %d, start 0x%llx, offset"
  345 + " 0x%x, block 0x%llx\n", res, index, start, offset,
  346 + *block);
  347 +
  348 + if (res < 0)
  349 + return res;
  350 +
  351 + /*
  352 + * res contains the index of the mapping returned by fill_meta_index(),
  353 + * this will likely be less than the desired index (because the
  354 + * meta_index cache works at a higher granularity). Read any
  355 + * extra block indexes needed.
  356 + */
  357 + if (res < index) {
  358 + blks = read_indexes(inode->i_sb, index - res, &start, &offset);
  359 + if (blks < 0)
  360 + return (int) blks;
  361 + *block += blks;
  362 + }
  363 +
  364 + /*
  365 + * Read length of block specified by index.
  366 + */
  367 + res = squashfs_read_metadata(inode->i_sb, &size, &start, &offset,
  368 + sizeof(size));
  369 + if (res < 0)
  370 + return res;
  371 + return le32_to_cpu(size);
  372 +}
  373 +
  374 +
  375 +static int squashfs_readpage(struct file *file, struct page *page)
  376 +{
  377 + struct inode *inode = page->mapping->host;
  378 + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
  379 + int bytes, i, offset = 0, sparse = 0;
  380 + struct squashfs_cache_entry *buffer = NULL;
  381 + void *pageaddr;
  382 +
  383 + int mask = (1 << (msblk->block_log - PAGE_CACHE_SHIFT)) - 1;
  384 + int index = page->index >> (msblk->block_log - PAGE_CACHE_SHIFT);
  385 + int start_index = page->index & ~mask;
  386 + int end_index = start_index | mask;
  387 + int file_end = i_size_read(inode) >> msblk->block_log;
  388 +
  389 + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
  390 + page->index, squashfs_i(inode)->start);
  391 +
  392 + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
  393 + PAGE_CACHE_SHIFT))
  394 + goto out;
  395 +
  396 + if (index < file_end || squashfs_i(inode)->fragment_block ==
  397 + SQUASHFS_INVALID_BLK) {
  398 + /*
  399 + * Reading a datablock from disk. Need to read block list
  400 + * to get location and block size.
  401 + */
  402 + u64 block = 0;
  403 + int bsize = read_blocklist(inode, index, &block);
  404 + if (bsize < 0)
  405 + goto error_out;
  406 +
  407 + if (bsize == 0) { /* hole */
  408 + bytes = index == file_end ?
  409 + (i_size_read(inode) & (msblk->block_size - 1)) :
  410 + msblk->block_size;
  411 + sparse = 1;
  412 + } else {
  413 + /*
  414 + * Read and decompress datablock.
  415 + */
  416 + buffer = squashfs_get_datablock(inode->i_sb,
  417 + block, bsize);
  418 + if (buffer->error) {
  419 + ERROR("Unable to read page, block %llx, size %x"
  420 + "\n", block, bsize);
  421 + squashfs_cache_put(buffer);
  422 + goto error_out;
  423 + }
  424 + bytes = buffer->length;
  425 + }
  426 + } else {
  427 + /*
  428 + * Datablock is stored inside a fragment (tail-end packed
  429 + * block).
  430 + */
  431 + buffer = squashfs_get_fragment(inode->i_sb,
  432 + squashfs_i(inode)->fragment_block,
  433 + squashfs_i(inode)->fragment_size);
  434 +
  435 + if (buffer->error) {
  436 + ERROR("Unable to read page, block %llx, size %x\n",
  437 + squashfs_i(inode)->fragment_block,
  438 + squashfs_i(inode)->fragment_size);
  439 + squashfs_cache_put(buffer);
  440 + goto error_out;
  441 + }
  442 + bytes = i_size_read(inode) & (msblk->block_size - 1);
  443 + offset = squashfs_i(inode)->fragment_offset;
  444 + }
  445 +
  446 + /*
  447 + * Loop copying datablock into pages. As the datablock likely covers
  448 + * many PAGE_CACHE_SIZE pages (default block size is 128 KiB) explicitly
  449 + * grab the pages from the page cache, except for the page that we've
  450 + * been called to fill.
  451 + */
  452 + for (i = start_index; i <= end_index && bytes > 0; i++,
  453 + bytes -= PAGE_CACHE_SIZE, offset += PAGE_CACHE_SIZE) {
  454 + struct page *push_page;
  455 + int avail = sparse ? 0 : min_t(int, bytes, PAGE_CACHE_SIZE);
  456 +
  457 + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail);
  458 +
  459 + push_page = (i == page->index) ? page :
  460 + grab_cache_page_nowait(page->mapping, i);
  461 +
  462 + if (!push_page)
  463 + continue;
  464 +
  465 + if (PageUptodate(push_page))
  466 + goto skip_page;
  467 +
  468 + pageaddr = kmap_atomic(push_page, KM_USER0);
  469 + squashfs_copy_data(pageaddr, buffer, offset, avail);
  470 + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
  471 + kunmap_atomic(pageaddr, KM_USER0);
  472 + flush_dcache_page(push_page);
  473 + SetPageUptodate(push_page);
  474 +skip_page:
  475 + unlock_page(push_page);
  476 + if (i != page->index)
  477 + page_cache_release(push_page);
  478 + }
  479 +
  480 + if (!sparse)
  481 + squashfs_cache_put(buffer);
  482 +
  483 + return 0;
  484 +
  485 +error_out:
  486 + SetPageError(page);
  487 +out:
  488 + pageaddr = kmap_atomic(page, KM_USER0);
  489 + memset(pageaddr, 0, PAGE_CACHE_SIZE);
  490 + kunmap_atomic(pageaddr, KM_USER0);
  491 + flush_dcache_page(page);
  492 + if (!PageError(page))
  493 + SetPageUptodate(page);
  494 + unlock_page(page);
  495 +
  496 + return 0;
  497 +}
  498 +
  499 +
  500 +const struct address_space_operations squashfs_aops = {
  501 + .readpage = squashfs_readpage
  502 +};
fs/squashfs/fragment.c
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * fragment.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to handle compressed fragments (tail-end packed
  26 + * datablocks).
  27 + *
  28 + * Regular files contain a fragment index which is mapped to a fragment
  29 + * location on disk and compressed size using a fragment lookup table.
  30 + * Like everything in Squashfs this fragment lookup table is itself stored
  31 + * compressed into metadata blocks. A second index table is used to locate
  32 + * these. This second index table for speed of access (and because it
  33 + * is small) is read at mount time and cached in memory.
  34 + */
  35 +
  36 +#include <linux/fs.h>
  37 +#include <linux/vfs.h>
  38 +#include <linux/slab.h>
  39 +#include <linux/zlib.h>
  40 +
  41 +#include "squashfs_fs.h"
  42 +#include "squashfs_fs_sb.h"
  43 +#include "squashfs_fs_i.h"
  44 +#include "squashfs.h"
  45 +
  46 +/*
  47 + * Look-up fragment using the fragment index table. Return the on disk
  48 + * location of the fragment and its compressed size
  49 + */
  50 +int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment,
  51 + u64 *fragment_block)
  52 +{
  53 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  54 + int block = SQUASHFS_FRAGMENT_INDEX(fragment);
  55 + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
  56 + u64 start_block = le64_to_cpu(msblk->fragment_index[block]);
  57 + struct squashfs_fragment_entry fragment_entry;
  58 + int size;
  59 +
  60 + size = squashfs_read_metadata(sb, &fragment_entry, &start_block,
  61 + &offset, sizeof(fragment_entry));
  62 + if (size < 0)
  63 + return size;
  64 +
  65 + *fragment_block = le64_to_cpu(fragment_entry.start_block);
  66 + size = le32_to_cpu(fragment_entry.size);
  67 +
  68 + return size;
  69 +}
  70 +
  71 +
  72 +/*
  73 + * Read the uncompressed fragment lookup table indexes off disk into memory
  74 + */
  75 +__le64 *squashfs_read_fragment_index_table(struct super_block *sb,
  76 + u64 fragment_table_start, unsigned int fragments)
  77 +{
  78 + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(fragments);
  79 + __le64 *fragment_index;
  80 + int err;
  81 +
  82 + /* Allocate fragment lookup table indexes */
  83 + fragment_index = kmalloc(length, GFP_KERNEL);
  84 + if (fragment_index == NULL) {
  85 + ERROR("Failed to allocate fragment index table\n");
  86 + return ERR_PTR(-ENOMEM);
  87 + }
  88 +
  89 + err = squashfs_read_table(sb, fragment_index, fragment_table_start,
  90 + length);
  91 + if (err < 0) {
  92 + ERROR("unable to read fragment index table\n");
  93 + kfree(fragment_index);
  94 + return ERR_PTR(err);
  95 + }
  96 +
  97 + return fragment_index;
  98 +}
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * id.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to handle uids and gids.
  26 + *
  27 + * For space efficiency regular files store uid and gid indexes, which are
  28 + * converted to 32-bit uids/gids using an id look up table. This table is
  29 + * stored compressed into metadata blocks. A second index table is used to
  30 + * locate these. This second index table for speed of access (and because it
  31 + * is small) is read at mount time and cached in memory.
  32 + */
  33 +
  34 +#include <linux/fs.h>
  35 +#include <linux/vfs.h>
  36 +#include <linux/slab.h>
  37 +#include <linux/zlib.h>
  38 +
  39 +#include "squashfs_fs.h"
  40 +#include "squashfs_fs_sb.h"
  41 +#include "squashfs_fs_i.h"
  42 +#include "squashfs.h"
  43 +
  44 +/*
  45 + * Map uid/gid index into real 32-bit uid/gid using the id look up table
  46 + */
  47 +int squashfs_get_id(struct super_block *sb, unsigned int index,
  48 + unsigned int *id)
  49 +{
  50 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  51 + int block = SQUASHFS_ID_BLOCK(index);
  52 + int offset = SQUASHFS_ID_BLOCK_OFFSET(index);
  53 + u64 start_block = le64_to_cpu(msblk->id_table[block]);
  54 + __le32 disk_id;
  55 + int err;
  56 +
  57 + err = squashfs_read_metadata(sb, &disk_id, &start_block, &offset,
  58 + sizeof(disk_id));
  59 + if (err < 0)
  60 + return err;
  61 +
  62 + *id = le32_to_cpu(disk_id);
  63 + return 0;
  64 +}
  65 +
  66 +
  67 +/*
  68 + * Read uncompressed id lookup table indexes from disk into memory
  69 + */
  70 +__le64 *squashfs_read_id_index_table(struct super_block *sb,
  71 + u64 id_table_start, unsigned short no_ids)
  72 +{
  73 + unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids);
  74 + __le64 *id_table;
  75 + int err;
  76 +
  77 + TRACE("In read_id_index_table, length %d\n", length);
  78 +
  79 + /* Allocate id lookup table indexes */
  80 + id_table = kmalloc(length, GFP_KERNEL);
  81 + if (id_table == NULL) {
  82 + ERROR("Failed to allocate id index table\n");
  83 + return ERR_PTR(-ENOMEM);
  84 + }
  85 +
  86 + err = squashfs_read_table(sb, id_table, id_table_start, length);
  87 + if (err < 0) {
  88 + ERROR("unable to read id index table\n");
  89 + kfree(id_table);
  90 + return ERR_PTR(err);
  91 + }
  92 +
  93 + return id_table;
  94 +}
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * inode.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to create and read inodes from disk.
  26 + *
  27 + * Inodes in Squashfs are identified by a 48-bit inode which encodes the
  28 + * location of the compressed metadata block containing the inode, and the byte
  29 + * offset into that block where the inode is placed (<block, offset>).
  30 + *
  31 + * To maximise compression there are different inodes for each file type
  32 + * (regular file, directory, device, etc.), the inode contents and length
  33 + * varying with the type.
  34 + *
  35 + * To further maximise compression, two types of regular file inode and
  36 + * directory inode are defined: inodes optimised for frequently occurring
  37 + * regular files and directories, and extended types where extra
  38 + * information has to be stored.
  39 + */
  40 +
  41 +#include <linux/fs.h>
  42 +#include <linux/vfs.h>
  43 +#include <linux/zlib.h>
  44 +
  45 +#include "squashfs_fs.h"
  46 +#include "squashfs_fs_sb.h"
  47 +#include "squashfs_fs_i.h"
  48 +#include "squashfs.h"
  49 +
  50 +/*
  51 + * Initialise VFS inode with the base inode information common to all
  52 + * Squashfs inode types. Sqsh_ino contains the unswapped base inode
  53 + * off disk.
  54 + */
  55 +static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
  56 + struct squashfs_base_inode *sqsh_ino)
  57 +{
  58 + int err;
  59 +
  60 + err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &inode->i_uid);
  61 + if (err)
  62 + return err;
  63 +
  64 + err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->guid), &inode->i_gid);
  65 + if (err)
  66 + return err;
  67 +
  68 + inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
  69 + inode->i_mtime.tv_sec = le32_to_cpu(sqsh_ino->mtime);
  70 + inode->i_atime.tv_sec = inode->i_mtime.tv_sec;
  71 + inode->i_ctime.tv_sec = inode->i_mtime.tv_sec;
  72 + inode->i_mode = le16_to_cpu(sqsh_ino->mode);
  73 + inode->i_size = 0;
  74 +
  75 + return err;
  76 +}
  77 +
  78 +
  79 +struct inode *squashfs_iget(struct super_block *sb, long long ino,
  80 + unsigned int ino_number)
  81 +{
  82 + struct inode *inode = iget_locked(sb, ino_number);
  83 + int err;
  84 +
  85 + TRACE("Entered squashfs_iget\n");
  86 +
  87 + if (!inode)
  88 + return ERR_PTR(-ENOMEM);
  89 + if (!(inode->i_state & I_NEW))
  90 + return inode;
  91 +
  92 + err = squashfs_read_inode(inode, ino);
  93 + if (err) {
  94 + iget_failed(inode);
  95 + return ERR_PTR(err);
  96 + }
  97 +
  98 + unlock_new_inode(inode);
  99 + return inode;
  100 +}
  101 +
  102 +
  103 +/*
  104 + * Initialise VFS inode by reading inode from inode table (compressed
  105 + * metadata). The format and amount of data read depends on type.
  106 + */
  107 +int squashfs_read_inode(struct inode *inode, long long ino)
  108 +{
  109 + struct super_block *sb = inode->i_sb;
  110 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  111 + u64 block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
  112 + int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
  113 + union squashfs_inode squashfs_ino;
  114 + struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
  115 +
  116 + TRACE("Entered squashfs_read_inode\n");
  117 +
  118 + /*
  119 + * Read inode base common to all inode types.
  120 + */
  121 + err = squashfs_read_metadata(sb, sqshb_ino, &block,
  122 + &offset, sizeof(*sqshb_ino));
  123 + if (err < 0)
  124 + goto failed_read;
  125 +
  126 + err = squashfs_new_inode(sb, inode, sqshb_ino);
  127 + if (err)
  128 + goto failed_read;
  129 +
  130 + block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
  131 + offset = SQUASHFS_INODE_OFFSET(ino);
  132 +
  133 + type = le16_to_cpu(sqshb_ino->inode_type);
  134 + switch (type) {
  135 + case SQUASHFS_REG_TYPE: {
  136 + unsigned int frag_offset, frag_size, frag;
  137 + u64 frag_blk;
  138 + struct squashfs_reg_inode *sqsh_ino = &squashfs_ino.reg;
  139 +
  140 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  141 + sizeof(*sqsh_ino));
  142 + if (err < 0)
  143 + goto failed_read;
  144 +
  145 + frag = le32_to_cpu(sqsh_ino->fragment);
  146 + if (frag != SQUASHFS_INVALID_FRAG) {
  147 + frag_offset = le32_to_cpu(sqsh_ino->offset);
  148 + frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
  149 + if (frag_size < 0) {
  150 + err = frag_size;
  151 + goto failed_read;
  152 + }
  153 + } else {
  154 + frag_blk = SQUASHFS_INVALID_BLK;
  155 + frag_size = 0;
  156 + frag_offset = 0;
  157 + }
  158 +
  159 + inode->i_nlink = 1;
  160 + inode->i_size = le32_to_cpu(sqsh_ino->file_size);
  161 + inode->i_fop = &generic_ro_fops;
  162 + inode->i_mode |= S_IFREG;
  163 + inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
  164 + squashfs_i(inode)->fragment_block = frag_blk;
  165 + squashfs_i(inode)->fragment_size = frag_size;
  166 + squashfs_i(inode)->fragment_offset = frag_offset;
  167 + squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
  168 + squashfs_i(inode)->block_list_start = block;
  169 + squashfs_i(inode)->offset = offset;
  170 + inode->i_data.a_ops = &squashfs_aops;
  171 +
  172 + TRACE("File inode %x:%x, start_block %llx, block_list_start "
  173 + "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
  174 + offset, squashfs_i(inode)->start, block, offset);
  175 + break;
  176 + }
  177 + case SQUASHFS_LREG_TYPE: {
  178 + unsigned int frag_offset, frag_size, frag;
  179 + u64 frag_blk;
  180 + struct squashfs_lreg_inode *sqsh_ino = &squashfs_ino.lreg;
  181 +
  182 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  183 + sizeof(*sqsh_ino));
  184 + if (err < 0)
  185 + goto failed_read;
  186 +
  187 + frag = le32_to_cpu(sqsh_ino->fragment);
  188 + if (frag != SQUASHFS_INVALID_FRAG) {
  189 + frag_offset = le32_to_cpu(sqsh_ino->offset);
  190 + frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
  191 + if (frag_size < 0) {
  192 + err = frag_size;
  193 + goto failed_read;
  194 + }
  195 + } else {
  196 + frag_blk = SQUASHFS_INVALID_BLK;
  197 + frag_size = 0;
  198 + frag_offset = 0;
  199 + }
  200 +
  201 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  202 + inode->i_size = le64_to_cpu(sqsh_ino->file_size);
  203 + inode->i_fop = &generic_ro_fops;
  204 + inode->i_mode |= S_IFREG;
  205 + inode->i_blocks = ((inode->i_size -
  206 + le64_to_cpu(sqsh_ino->sparse) - 1) >> 9) + 1;
  207 +
  208 + squashfs_i(inode)->fragment_block = frag_blk;
  209 + squashfs_i(inode)->fragment_size = frag_size;
  210 + squashfs_i(inode)->fragment_offset = frag_offset;
  211 + squashfs_i(inode)->start = le64_to_cpu(sqsh_ino->start_block);
  212 + squashfs_i(inode)->block_list_start = block;
  213 + squashfs_i(inode)->offset = offset;
  214 + inode->i_data.a_ops = &squashfs_aops;
  215 +
  216 + TRACE("File inode %x:%x, start_block %llx, block_list_start "
  217 + "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
  218 + offset, squashfs_i(inode)->start, block, offset);
  219 + break;
  220 + }
  221 + case SQUASHFS_DIR_TYPE: {
  222 + struct squashfs_dir_inode *sqsh_ino = &squashfs_ino.dir;
  223 +
  224 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  225 + sizeof(*sqsh_ino));
  226 + if (err < 0)
  227 + goto failed_read;
  228 +
  229 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  230 + inode->i_size = le16_to_cpu(sqsh_ino->file_size);
  231 + inode->i_op = &squashfs_dir_inode_ops;
  232 + inode->i_fop = &squashfs_dir_ops;
  233 + inode->i_mode |= S_IFDIR;
  234 + squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
  235 + squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
  236 + squashfs_i(inode)->dir_idx_cnt = 0;
  237 + squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
  238 +
  239 + TRACE("Directory inode %x:%x, start_block %llx, offset %x\n",
  240 + SQUASHFS_INODE_BLK(ino), offset,
  241 + squashfs_i(inode)->start,
  242 + le16_to_cpu(sqsh_ino->offset));
  243 + break;
  244 + }
  245 + case SQUASHFS_LDIR_TYPE: {
  246 + struct squashfs_ldir_inode *sqsh_ino = &squashfs_ino.ldir;
  247 +
  248 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  249 + sizeof(*sqsh_ino));
  250 + if (err < 0)
  251 + goto failed_read;
  252 +
  253 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  254 + inode->i_size = le32_to_cpu(sqsh_ino->file_size);
  255 + inode->i_op = &squashfs_dir_inode_ops;
  256 + inode->i_fop = &squashfs_dir_ops;
  257 + inode->i_mode |= S_IFDIR;
  258 + squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
  259 + squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
  260 + squashfs_i(inode)->dir_idx_start = block;
  261 + squashfs_i(inode)->dir_idx_offset = offset;
  262 + squashfs_i(inode)->dir_idx_cnt = le16_to_cpu(sqsh_ino->i_count);
  263 + squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
  264 +
  265 + TRACE("Long directory inode %x:%x, start_block %llx, offset "
  266 + "%x\n", SQUASHFS_INODE_BLK(ino), offset,
  267 + squashfs_i(inode)->start,
  268 + le16_to_cpu(sqsh_ino->offset));
  269 + break;
  270 + }
  271 + case SQUASHFS_SYMLINK_TYPE:
  272 + case SQUASHFS_LSYMLINK_TYPE: {
  273 + struct squashfs_symlink_inode *sqsh_ino = &squashfs_ino.symlink;
  274 +
  275 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  276 + sizeof(*sqsh_ino));
  277 + if (err < 0)
  278 + goto failed_read;
  279 +
  280 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  281 + inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
  282 + inode->i_op = &page_symlink_inode_operations;
  283 + inode->i_data.a_ops = &squashfs_symlink_aops;
  284 + inode->i_mode |= S_IFLNK;
  285 + squashfs_i(inode)->start = block;
  286 + squashfs_i(inode)->offset = offset;
  287 +
  288 + TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
  289 + "%x\n", SQUASHFS_INODE_BLK(ino), offset,
  290 + block, offset);
  291 + break;
  292 + }
  293 + case SQUASHFS_BLKDEV_TYPE:
  294 + case SQUASHFS_CHRDEV_TYPE:
  295 + case SQUASHFS_LBLKDEV_TYPE:
  296 + case SQUASHFS_LCHRDEV_TYPE: {
  297 + struct squashfs_dev_inode *sqsh_ino = &squashfs_ino.dev;
  298 + unsigned int rdev;
  299 +
  300 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  301 + sizeof(*sqsh_ino));
  302 + if (err < 0)
  303 + goto failed_read;
  304 +
  305 + if (type == SQUASHFS_CHRDEV_TYPE)
  306 + inode->i_mode |= S_IFCHR;
  307 + else
  308 + inode->i_mode |= S_IFBLK;
  309 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  310 + rdev = le32_to_cpu(sqsh_ino->rdev);
  311 + init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
  312 +
  313 + TRACE("Device inode %x:%x, rdev %x\n",
  314 + SQUASHFS_INODE_BLK(ino), offset, rdev);
  315 + break;
  316 + }
  317 + case SQUASHFS_FIFO_TYPE:
  318 + case SQUASHFS_SOCKET_TYPE:
  319 + case SQUASHFS_LFIFO_TYPE:
  320 + case SQUASHFS_LSOCKET_TYPE: {
  321 + struct squashfs_ipc_inode *sqsh_ino = &squashfs_ino.ipc;
  322 +
  323 + err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  324 + sizeof(*sqsh_ino));
  325 + if (err < 0)
  326 + goto failed_read;
  327 +
  328 + if (type == SQUASHFS_FIFO_TYPE)
  329 + inode->i_mode |= S_IFIFO;
  330 + else
  331 + inode->i_mode |= S_IFSOCK;
  332 + inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
  333 + init_special_inode(inode, inode->i_mode, 0);
  334 + break;
  335 + }
  336 + default:
  337 + ERROR("Unknown inode type %d in squashfs_iget!\n", type);
  338 + return -EINVAL;
  339 + }
  340 +
  341 + return 0;
  342 +
  343 +failed_read:
  344 + ERROR("Unable to read inode 0x%llx\n", ino);
  345 + return err;
  346 +}
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * namei.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to do filename lookup in directories.
  26 + *
  27 + * Like inodes, directories are packed into compressed metadata blocks, stored
  28 + * in a directory table. Directories are accessed using the start address of
  29 + * the metablock containing the directory and the offset into the
  30 + * decompressed block (<block, offset>).
  31 + *
  32 + * Directories are organised in a slightly complex way, and are not simply
  33 + * a list of file names. The organisation takes advantage of the
  34 + * fact that (in most cases) the inodes of the files will be in the same
  35 + * compressed metadata block, and therefore, can share the start block.
  36 + * Directories are therefore organised in a two level list, a directory
  37 + * header containing the shared start block value, and a sequence of directory
  38 + * entries, each of which share the shared start block. A new directory header
  39 + * is written once/if the inode start block changes. The directory
  40 + * header/directory entry list is repeated as many times as necessary.
  41 + *
  42 + * Directories are sorted, and can contain a directory index to speed up
  43 + * file lookup. Directory indexes store one entry per metablock, each entry
  44 + * storing the index/filename mapping to the first directory header
  45 + * in each metadata block. Directories are sorted in alphabetical order,
  46 + * and at lookup the index is scanned linearly looking for the first filename
  47 + * alphabetically larger than the filename being looked up. At this point the
  48 + * location of the metadata block the filename is in has been found.
  49 + * The general idea of the index is ensure only one metadata block needs to be
  50 + * decompressed to do a lookup irrespective of the length of the directory.
  51 + * This scheme has the advantage that it doesn't require extra memory overhead
  52 + * and doesn't require much extra storage on disk.
  53 + */
  54 +
  55 +#include <linux/fs.h>
  56 +#include <linux/vfs.h>
  57 +#include <linux/slab.h>
  58 +#include <linux/string.h>
  59 +#include <linux/dcache.h>
  60 +#include <linux/zlib.h>
  61 +
  62 +#include "squashfs_fs.h"
  63 +#include "squashfs_fs_sb.h"
  64 +#include "squashfs_fs_i.h"
  65 +#include "squashfs.h"
  66 +
  67 +/*
  68 + * Lookup name in the directory index, returning the location of the metadata
  69 + * block containing it, and the directory index this represents.
  70 + *
  71 + * If we get an error reading the index then return the part of the index
  72 + * (if any) we have managed to read - the index isn't essential, just
  73 + * quicker.
  74 + */
  75 +static int get_dir_index_using_name(struct super_block *sb,
  76 + u64 *next_block, int *next_offset, u64 index_start,
  77 + int index_offset, int i_count, const char *name,
  78 + int len)
  79 +{
  80 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  81 + int i, size, length = 0, err;
  82 + struct squashfs_dir_index *index;
  83 + char *str;
  84 +
  85 + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
  86 +
  87 + index = kmalloc(sizeof(*index) + SQUASHFS_NAME_LEN * 2 + 2, GFP_KERNEL);
  88 + if (index == NULL) {
  89 + ERROR("Failed to allocate squashfs_dir_index\n");
  90 + goto out;
  91 + }
  92 +
  93 + str = &index->name[SQUASHFS_NAME_LEN + 1];
  94 + strncpy(str, name, len);
  95 + str[len] = '\0';
  96 +
  97 + for (i = 0; i < i_count; i++) {
  98 + err = squashfs_read_metadata(sb, index, &index_start,
  99 + &index_offset, sizeof(*index));
  100 + if (err < 0)
  101 + break;
  102 +
  103 +
  104 + size = le32_to_cpu(index->size) + 1;
  105 +
  106 + err = squashfs_read_metadata(sb, index->name, &index_start,
  107 + &index_offset, size);
  108 + if (err < 0)
  109 + break;
  110 +
  111 + index->name[size] = '\0';
  112 +
  113 + if (strcmp(index->name, str) > 0)
  114 + break;
  115 +
  116 + length = le32_to_cpu(index->index);
  117 + *next_block = le32_to_cpu(index->start_block) +
  118 + msblk->directory_table;
  119 + }
  120 +
  121 + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
  122 + kfree(index);
  123 +
  124 +out:
  125 + /*
  126 + * Return index (f_pos) of the looked up metadata block. Translate
  127 + * from internal f_pos to external f_pos which is offset by 3 because
  128 + * we invent "." and ".." entries which are not actually stored in the
  129 + * directory.
  130 + */
  131 + return length + 3;
  132 +}
  133 +
  134 +
  135 +static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
  136 + struct nameidata *nd)
  137 +{
  138 + const unsigned char *name = dentry->d_name.name;
  139 + int len = dentry->d_name.len;
  140 + struct inode *inode = NULL;
  141 + struct squashfs_sb_info *msblk = dir->i_sb->s_fs_info;
  142 + struct squashfs_dir_header dirh;
  143 + struct squashfs_dir_entry *dire;
  144 + u64 block = squashfs_i(dir)->start + msblk->directory_table;
  145 + int offset = squashfs_i(dir)->offset;
  146 + int err, length = 0, dir_count, size;
  147 +
  148 + TRACE("Entered squashfs_lookup [%llx:%x]\n", block, offset);
  149 +
  150 + dire = kmalloc(sizeof(*dire) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL);
  151 + if (dire == NULL) {
  152 + ERROR("Failed to allocate squashfs_dir_entry\n");
  153 + return ERR_PTR(-ENOMEM);
  154 + }
  155 +
  156 + if (len > SQUASHFS_NAME_LEN) {
  157 + err = -ENAMETOOLONG;
  158 + goto failed;
  159 + }
  160 +
  161 + length = get_dir_index_using_name(dir->i_sb, &block, &offset,
  162 + squashfs_i(dir)->dir_idx_start,
  163 + squashfs_i(dir)->dir_idx_offset,
  164 + squashfs_i(dir)->dir_idx_cnt, name, len);
  165 +
  166 + while (length < i_size_read(dir)) {
  167 + /*
  168 + * Read directory header.
  169 + */
  170 + err = squashfs_read_metadata(dir->i_sb, &dirh, &block,
  171 + &offset, sizeof(dirh));
  172 + if (err < 0)
  173 + goto read_failure;
  174 +
  175 + length += sizeof(dirh);
  176 +
  177 + dir_count = le32_to_cpu(dirh.count) + 1;
  178 + while (dir_count--) {
  179 + /*
  180 + * Read directory entry.
  181 + */
  182 + err = squashfs_read_metadata(dir->i_sb, dire, &block,
  183 + &offset, sizeof(*dire));
  184 + if (err < 0)
  185 + goto read_failure;
  186 +
  187 + size = le16_to_cpu(dire->size) + 1;
  188 +
  189 + err = squashfs_read_metadata(dir->i_sb, dire->name,
  190 + &block, &offset, size);
  191 + if (err < 0)
  192 + goto read_failure;
  193 +
  194 + length += sizeof(*dire) + size;
  195 +
  196 + if (name[0] < dire->name[0])
  197 + goto exit_lookup;
  198 +
  199 + if (len == size && !strncmp(name, dire->name, len)) {
  200 + unsigned int blk, off, ino_num;
  201 + long long ino;
  202 + blk = le32_to_cpu(dirh.start_block);
  203 + off = le16_to_cpu(dire->offset);
  204 + ino_num = le32_to_cpu(dirh.inode_number) +
  205 + (short) le16_to_cpu(dire->inode_number);
  206 + ino = SQUASHFS_MKINODE(blk, off);
  207 +
  208 + TRACE("calling squashfs_iget for directory "
  209 + "entry %s, inode %x:%x, %d\n", name,
  210 + blk, off, ino_num);
  211 +
  212 + inode = squashfs_iget(dir->i_sb, ino, ino_num);
  213 + if (IS_ERR(inode)) {
  214 + err = PTR_ERR(inode);
  215 + goto failed;
  216 + }
  217 +
  218 + goto exit_lookup;
  219 + }
  220 + }
  221 + }
  222 +
  223 +exit_lookup:
  224 + kfree(dire);
  225 + if (inode)
  226 + return d_splice_alias(inode, dentry);
  227 + d_add(dentry, inode);
  228 + return ERR_PTR(0);
  229 +
  230 +read_failure:
  231 + ERROR("Unable to read directory block [%llx:%x]\n",
  232 + squashfs_i(dir)->start + msblk->directory_table,
  233 + squashfs_i(dir)->offset);
  234 +failed:
  235 + kfree(dire);
  236 + return ERR_PTR(err);
  237 +}
  238 +
  239 +
  240 +const struct inode_operations squashfs_dir_inode_ops = {
  241 + .lookup = squashfs_lookup
  242 +};
fs/squashfs/squashfs.h
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * squashfs.h
  22 + */
  23 +
  24 +#define TRACE(s, args...) pr_debug("SQUASHFS: "s, ## args)
  25 +
  26 +#define ERROR(s, args...) pr_err("SQUASHFS error: "s, ## args)
  27 +
  28 +#define WARNING(s, args...) pr_warning("SQUASHFS: "s, ## args)
  29 +
  30 +static inline struct squashfs_inode_info *squashfs_i(struct inode *inode)
  31 +{
  32 + return list_entry(inode, struct squashfs_inode_info, vfs_inode);
  33 +}
  34 +
  35 +/* block.c */
  36 +extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *,
  37 + int);
  38 +
  39 +/* cache.c */
  40 +extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
  41 +extern void squashfs_cache_delete(struct squashfs_cache *);
  42 +extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *,
  43 + struct squashfs_cache *, u64, int);
  44 +extern void squashfs_cache_put(struct squashfs_cache_entry *);
  45 +extern int squashfs_copy_data(void *, struct squashfs_cache_entry *, int, int);
  46 +extern int squashfs_read_metadata(struct super_block *, void *, u64 *,
  47 + int *, int);
  48 +extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *,
  49 + u64, int);
  50 +extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *,
  51 + u64, int);
  52 +extern int squashfs_read_table(struct super_block *, void *, u64, int);
  53 +
  54 +/* export.c */
  55 +extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
  56 + unsigned int);
  57 +
  58 +/* fragment.c */
  59 +extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *);
  60 +extern __le64 *squashfs_read_fragment_index_table(struct super_block *,
  61 + u64, unsigned int);
  62 +
  63 +/* id.c */
  64 +extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
  65 +extern __le64 *squashfs_read_id_index_table(struct super_block *, u64,
  66 + unsigned short);
  67 +
  68 +/* inode.c */
  69 +extern struct inode *squashfs_iget(struct super_block *, long long,
  70 + unsigned int);
  71 +extern int squashfs_read_inode(struct inode *, long long);
  72 +
  73 +/*
  74 + * Inodes and files operations
  75 + */
  76 +
  77 +/* dir.c */
  78 +extern const struct file_operations squashfs_dir_ops;
  79 +
  80 +/* export.c */
  81 +extern const struct export_operations squashfs_export_ops;
  82 +
  83 +/* file.c */
  84 +extern const struct address_space_operations squashfs_aops;
  85 +
  86 +/* namei.c */
  87 +extern const struct inode_operations squashfs_dir_inode_ops;
  88 +
  89 +/* symlink.c */
  90 +extern const struct address_space_operations squashfs_symlink_aops;
fs/squashfs/squashfs_fs.h
  1 +#ifndef SQUASHFS_FS
  2 +#define SQUASHFS_FS
  3 +/*
  4 + * Squashfs
  5 + *
  6 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  7 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  8 + *
  9 + * This program is free software; you can redistribute it and/or
  10 + * modify it under the terms of the GNU General Public License
  11 + * as published by the Free Software Foundation; either version 2,
  12 + * or (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program; if not, write to the Free Software
  21 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22 + *
  23 + * squashfs_fs.h
  24 + */
  25 +
  26 +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
  27 +#define SQUASHFS_MAJOR 4
  28 +#define SQUASHFS_MINOR 0
  29 +#define SQUASHFS_MAGIC 0x73717368
  30 +#define SQUASHFS_START 0
  31 +
  32 +/* size of metadata (inode and directory) blocks */
  33 +#define SQUASHFS_METADATA_SIZE 8192
  34 +#define SQUASHFS_METADATA_LOG 13
  35 +
  36 +/* default size of data blocks */
  37 +#define SQUASHFS_FILE_SIZE 131072
  38 +#define SQUASHFS_FILE_LOG 17
  39 +
  40 +#define SQUASHFS_FILE_MAX_SIZE 1048576
  41 +#define SQUASHFS_FILE_MAX_LOG 20
  42 +
  43 +/* Max number of uids and gids */
  44 +#define SQUASHFS_IDS 65536
  45 +
  46 +/* Max length of filename (not 255) */
  47 +#define SQUASHFS_NAME_LEN 256
  48 +
  49 +#define SQUASHFS_INVALID_FRAG (0xffffffffU)
  50 +#define SQUASHFS_INVALID_BLK (-1LL)
  51 +
  52 +/* Filesystem flags */
  53 +#define SQUASHFS_NOI 0
  54 +#define SQUASHFS_NOD 1
  55 +#define SQUASHFS_NOF 3
  56 +#define SQUASHFS_NO_FRAG 4
  57 +#define SQUASHFS_ALWAYS_FRAG 5
  58 +#define SQUASHFS_DUPLICATE 6
  59 +#define SQUASHFS_EXPORT 7
  60 +
  61 +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
  62 +
  63 +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
  64 + SQUASHFS_NOI)
  65 +
  66 +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
  67 + SQUASHFS_NOD)
  68 +
  69 +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  70 + SQUASHFS_NOF)
  71 +
  72 +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  73 + SQUASHFS_NO_FRAG)
  74 +
  75 +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
  76 + SQUASHFS_ALWAYS_FRAG)
  77 +
  78 +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
  79 + SQUASHFS_DUPLICATE)
  80 +
  81 +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
  82 + SQUASHFS_EXPORT)
  83 +
  84 +/* Max number of types and file types */
  85 +#define SQUASHFS_DIR_TYPE 1
  86 +#define SQUASHFS_REG_TYPE 2
  87 +#define SQUASHFS_SYMLINK_TYPE 3
  88 +#define SQUASHFS_BLKDEV_TYPE 4
  89 +#define SQUASHFS_CHRDEV_TYPE 5
  90 +#define SQUASHFS_FIFO_TYPE 6
  91 +#define SQUASHFS_SOCKET_TYPE 7
  92 +#define SQUASHFS_LDIR_TYPE 8
  93 +#define SQUASHFS_LREG_TYPE 9
  94 +#define SQUASHFS_LSYMLINK_TYPE 10
  95 +#define SQUASHFS_LBLKDEV_TYPE 11
  96 +#define SQUASHFS_LCHRDEV_TYPE 12
  97 +#define SQUASHFS_LFIFO_TYPE 13
  98 +#define SQUASHFS_LSOCKET_TYPE 14
  99 +
  100 +/* Flag whether block is compressed or uncompressed, bit is set if block is
  101 + * uncompressed */
  102 +#define SQUASHFS_COMPRESSED_BIT (1 << 15)
  103 +
  104 +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
  105 + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
  106 +
  107 +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
  108 +
  109 +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
  110 +
  111 +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \
  112 + ~SQUASHFS_COMPRESSED_BIT_BLOCK)
  113 +
  114 +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
  115 +
  116 +/*
  117 + * Inode number ops. Inodes consist of a compressed block number, and an
  118 + * uncompressed offset within that block
  119 + */
  120 +#define SQUASHFS_INODE_BLK(A) ((unsigned int) ((A) >> 16))
  121 +
  122 +#define SQUASHFS_INODE_OFFSET(A) ((unsigned int) ((A) & 0xffff))
  123 +
  124 +#define SQUASHFS_MKINODE(A, B) ((long long)(((long long) (A)\
  125 + << 16) + (B)))
  126 +
  127 +/* Translate between VFS mode and squashfs mode */
  128 +#define SQUASHFS_MODE(A) ((A) & 0xfff)
  129 +
  130 +/* fragment and fragment table defines */
  131 +#define SQUASHFS_FRAGMENT_BYTES(A) \
  132 + ((A) * sizeof(struct squashfs_fragment_entry))
  133 +
  134 +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
  135 + SQUASHFS_METADATA_SIZE)
  136 +
  137 +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
  138 + SQUASHFS_METADATA_SIZE)
  139 +
  140 +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
  141 + SQUASHFS_METADATA_SIZE - 1) / \
  142 + SQUASHFS_METADATA_SIZE)
  143 +
  144 +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
  145 + sizeof(u64))
  146 +
  147 +/* inode lookup table defines */
  148 +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(u64))
  149 +
  150 +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
  151 + SQUASHFS_METADATA_SIZE)
  152 +
  153 +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
  154 + SQUASHFS_METADATA_SIZE)
  155 +
  156 +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
  157 + SQUASHFS_METADATA_SIZE - 1) / \
  158 + SQUASHFS_METADATA_SIZE)
  159 +
  160 +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
  161 + sizeof(u64))
  162 +
  163 +/* uid/gid lookup table defines */
  164 +#define SQUASHFS_ID_BYTES(A) ((A) * sizeof(unsigned int))
  165 +
  166 +#define SQUASHFS_ID_BLOCK(A) (SQUASHFS_ID_BYTES(A) / \
  167 + SQUASHFS_METADATA_SIZE)
  168 +
  169 +#define SQUASHFS_ID_BLOCK_OFFSET(A) (SQUASHFS_ID_BYTES(A) % \
  170 + SQUASHFS_METADATA_SIZE)
  171 +
  172 +#define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \
  173 + SQUASHFS_METADATA_SIZE - 1) / \
  174 + SQUASHFS_METADATA_SIZE)
  175 +
  176 +#define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\
  177 + sizeof(u64))
  178 +
  179 +/* cached data constants for filesystem */
  180 +#define SQUASHFS_CACHED_BLKS 8
  181 +
  182 +#define SQUASHFS_MAX_FILE_SIZE_LOG 64
  183 +
  184 +#define SQUASHFS_MAX_FILE_SIZE (1LL << \
  185 + (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
  186 +
  187 +#define SQUASHFS_MARKER_BYTE 0xff
  188 +
  189 +/* meta index cache */
  190 +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
  191 +#define SQUASHFS_META_ENTRIES 127
  192 +#define SQUASHFS_META_SLOTS 8
  193 +
  194 +struct meta_entry {
  195 + u64 data_block;
  196 + unsigned int index_block;
  197 + unsigned short offset;
  198 + unsigned short pad;
  199 +};
  200 +
  201 +struct meta_index {
  202 + unsigned int inode_number;
  203 + unsigned int offset;
  204 + unsigned short entries;
  205 + unsigned short skip;
  206 + unsigned short locked;
  207 + unsigned short pad;
  208 + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
  209 +};
  210 +
  211 +
  212 +/*
  213 + * definitions for structures on disk
  214 + */
  215 +#define ZLIB_COMPRESSION 1
  216 +
  217 +struct squashfs_super_block {
  218 + __le32 s_magic;
  219 + __le32 inodes;
  220 + __le32 mkfs_time;
  221 + __le32 block_size;
  222 + __le32 fragments;
  223 + __le16 compression;
  224 + __le16 block_log;
  225 + __le16 flags;
  226 + __le16 no_ids;
  227 + __le16 s_major;
  228 + __le16 s_minor;
  229 + __le64 root_inode;
  230 + __le64 bytes_used;
  231 + __le64 id_table_start;
  232 + __le64 xattr_table_start;
  233 + __le64 inode_table_start;
  234 + __le64 directory_table_start;
  235 + __le64 fragment_table_start;
  236 + __le64 lookup_table_start;
  237 +};
  238 +
  239 +struct squashfs_dir_index {
  240 + __le32 index;
  241 + __le32 start_block;
  242 + __le32 size;
  243 + unsigned char name[0];
  244 +};
  245 +
  246 +struct squashfs_base_inode {
  247 + __le16 inode_type;
  248 + __le16 mode;
  249 + __le16 uid;
  250 + __le16 guid;
  251 + __le32 mtime;
  252 + __le32 inode_number;
  253 +};
  254 +
  255 +struct squashfs_ipc_inode {
  256 + __le16 inode_type;
  257 + __le16 mode;
  258 + __le16 uid;
  259 + __le16 guid;
  260 + __le32 mtime;
  261 + __le32 inode_number;
  262 + __le32 nlink;
  263 +};
  264 +
  265 +struct squashfs_dev_inode {
  266 + __le16 inode_type;
  267 + __le16 mode;
  268 + __le16 uid;
  269 + __le16 guid;
  270 + __le32 mtime;
  271 + __le32 inode_number;
  272 + __le32 nlink;
  273 + __le32 rdev;
  274 +};
  275 +
  276 +struct squashfs_symlink_inode {
  277 + __le16 inode_type;
  278 + __le16 mode;
  279 + __le16 uid;
  280 + __le16 guid;
  281 + __le32 mtime;
  282 + __le32 inode_number;
  283 + __le32 nlink;
  284 + __le32 symlink_size;
  285 + char symlink[0];
  286 +};
  287 +
  288 +struct squashfs_reg_inode {
  289 + __le16 inode_type;
  290 + __le16 mode;
  291 + __le16 uid;
  292 + __le16 guid;
  293 + __le32 mtime;
  294 + __le32 inode_number;
  295 + __le32 start_block;
  296 + __le32 fragment;
  297 + __le32 offset;
  298 + __le32 file_size;
  299 + __le16 block_list[0];
  300 +};
  301 +
  302 +struct squashfs_lreg_inode {
  303 + __le16 inode_type;
  304 + __le16 mode;
  305 + __le16 uid;
  306 + __le16 guid;
  307 + __le32 mtime;
  308 + __le32 inode_number;
  309 + __le64 start_block;
  310 + __le64 file_size;
  311 + __le64 sparse;
  312 + __le32 nlink;
  313 + __le32 fragment;
  314 + __le32 offset;
  315 + __le32 xattr;
  316 + __le16 block_list[0];
  317 +};
  318 +
  319 +struct squashfs_dir_inode {
  320 + __le16 inode_type;
  321 + __le16 mode;
  322 + __le16 uid;
  323 + __le16 guid;
  324 + __le32 mtime;
  325 + __le32 inode_number;
  326 + __le32 start_block;
  327 + __le32 nlink;
  328 + __le16 file_size;
  329 + __le16 offset;
  330 + __le32 parent_inode;
  331 +};
  332 +
  333 +struct squashfs_ldir_inode {
  334 + __le16 inode_type;
  335 + __le16 mode;
  336 + __le16 uid;
  337 + __le16 guid;
  338 + __le32 mtime;
  339 + __le32 inode_number;
  340 + __le32 nlink;
  341 + __le32 file_size;
  342 + __le32 start_block;
  343 + __le32 parent_inode;
  344 + __le16 i_count;
  345 + __le16 offset;
  346 + __le32 xattr;
  347 + struct squashfs_dir_index index[0];
  348 +};
  349 +
  350 +union squashfs_inode {
  351 + struct squashfs_base_inode base;
  352 + struct squashfs_dev_inode dev;
  353 + struct squashfs_symlink_inode symlink;
  354 + struct squashfs_reg_inode reg;
  355 + struct squashfs_lreg_inode lreg;
  356 + struct squashfs_dir_inode dir;
  357 + struct squashfs_ldir_inode ldir;
  358 + struct squashfs_ipc_inode ipc;
  359 +};
  360 +
  361 +struct squashfs_dir_entry {
  362 + __le16 offset;
  363 + __le16 inode_number;
  364 + __le16 type;
  365 + __le16 size;
  366 + char name[0];
  367 +};
  368 +
  369 +struct squashfs_dir_header {
  370 + __le32 count;
  371 + __le32 start_block;
  372 + __le32 inode_number;
  373 +};
  374 +
  375 +struct squashfs_fragment_entry {
  376 + __le64 start_block;
  377 + __le32 size;
  378 + unsigned int unused;
  379 +};
  380 +
  381 +#endif
fs/squashfs/squashfs_fs_i.h
  1 +#ifndef SQUASHFS_FS_I
  2 +#define SQUASHFS_FS_I
  3 +/*
  4 + * Squashfs
  5 + *
  6 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  7 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  8 + *
  9 + * This program is free software; you can redistribute it and/or
  10 + * modify it under the terms of the GNU General Public License
  11 + * as published by the Free Software Foundation; either version 2,
  12 + * or (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program; if not, write to the Free Software
  21 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22 + *
  23 + * squashfs_fs_i.h
  24 + */
  25 +
  26 +struct squashfs_inode_info {
  27 + u64 start;
  28 + int offset;
  29 + union {
  30 + struct {
  31 + u64 fragment_block;
  32 + int fragment_size;
  33 + int fragment_offset;
  34 + u64 block_list_start;
  35 + };
  36 + struct {
  37 + u64 dir_idx_start;
  38 + int dir_idx_offset;
  39 + int dir_idx_cnt;
  40 + int parent;
  41 + };
  42 + };
  43 + struct inode vfs_inode;
  44 +};
  45 +#endif
fs/squashfs/squashfs_fs_sb.h
  1 +#ifndef SQUASHFS_FS_SB
  2 +#define SQUASHFS_FS_SB
  3 +/*
  4 + * Squashfs
  5 + *
  6 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  7 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  8 + *
  9 + * This program is free software; you can redistribute it and/or
  10 + * modify it under the terms of the GNU General Public License
  11 + * as published by the Free Software Foundation; either version 2,
  12 + * or (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program; if not, write to the Free Software
  21 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22 + *
  23 + * squashfs_fs_sb.h
  24 + */
  25 +
  26 +#include "squashfs_fs.h"
  27 +
  28 +struct squashfs_cache {
  29 + char *name;
  30 + int entries;
  31 + int next_blk;
  32 + int num_waiters;
  33 + int unused;
  34 + int block_size;
  35 + int pages;
  36 + spinlock_t lock;
  37 + wait_queue_head_t wait_queue;
  38 + struct squashfs_cache_entry *entry;
  39 +};
  40 +
  41 +struct squashfs_cache_entry {
  42 + u64 block;
  43 + int length;
  44 + int refcount;
  45 + u64 next_index;
  46 + int pending;
  47 + int error;
  48 + int num_waiters;
  49 + wait_queue_head_t wait_queue;
  50 + struct squashfs_cache *cache;
  51 + void **data;
  52 +};
  53 +
  54 +struct squashfs_sb_info {
  55 + int devblksize;
  56 + int devblksize_log2;
  57 + struct squashfs_cache *block_cache;
  58 + struct squashfs_cache *fragment_cache;
  59 + struct squashfs_cache *read_page;
  60 + int next_meta_index;
  61 + __le64 *id_table;
  62 + __le64 *fragment_index;
  63 + unsigned int *fragment_index_2;
  64 + struct mutex read_data_mutex;
  65 + struct mutex meta_index_mutex;
  66 + struct meta_index *meta_index;
  67 + z_stream stream;
  68 + __le64 *inode_lookup_table;
  69 + u64 inode_table;
  70 + u64 directory_table;
  71 + unsigned int block_size;
  72 + unsigned short block_log;
  73 + long long bytes_used;
  74 + unsigned int inodes;
  75 +};
  76 +#endif
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * super.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to read the superblock, read and initialise
  26 + * in-memory structures at mount time, and all the VFS glue code to register
  27 + * the filesystem.
  28 + */
  29 +
  30 +#include <linux/fs.h>
  31 +#include <linux/vfs.h>
  32 +#include <linux/slab.h>
  33 +#include <linux/mutex.h>
  34 +#include <linux/pagemap.h>
  35 +#include <linux/init.h>
  36 +#include <linux/module.h>
  37 +#include <linux/zlib.h>
  38 +
  39 +#include "squashfs_fs.h"
  40 +#include "squashfs_fs_sb.h"
  41 +#include "squashfs_fs_i.h"
  42 +#include "squashfs.h"
  43 +
  44 +static struct file_system_type squashfs_fs_type;
  45 +static struct super_operations squashfs_super_ops;
  46 +
  47 +static int supported_squashfs_filesystem(short major, short minor, short comp)
  48 +{
  49 + if (major < SQUASHFS_MAJOR) {
  50 + ERROR("Major/Minor mismatch, older Squashfs %d.%d "
  51 + "filesystems are unsupported\n", major, minor);
  52 + return -EINVAL;
  53 + } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
  54 + ERROR("Major/Minor mismatch, trying to mount newer "
  55 + "%d.%d filesystem\n", major, minor);
  56 + ERROR("Please update your kernel\n");
  57 + return -EINVAL;
  58 + }
  59 +
  60 + if (comp != ZLIB_COMPRESSION)
  61 + return -EINVAL;
  62 +
  63 + return 0;
  64 +}
  65 +
  66 +
  67 +static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
  68 +{
  69 + struct squashfs_sb_info *msblk;
  70 + struct squashfs_super_block *sblk = NULL;
  71 + char b[BDEVNAME_SIZE];
  72 + struct inode *root;
  73 + long long root_inode;
  74 + unsigned short flags;
  75 + unsigned int fragments;
  76 + u64 lookup_table_start;
  77 + int err;
  78 +
  79 + TRACE("Entered squashfs_fill_superblock\n");
  80 +
  81 + sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL);
  82 + if (sb->s_fs_info == NULL) {
  83 + ERROR("Failed to allocate squashfs_sb_info\n");
  84 + return -ENOMEM;
  85 + }
  86 + msblk = sb->s_fs_info;
  87 +
  88 + msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
  89 + GFP_KERNEL);
  90 + if (msblk->stream.workspace == NULL) {
  91 + ERROR("Failed to allocate zlib workspace\n");
  92 + goto failure;
  93 + }
  94 +
  95 + sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
  96 + if (sblk == NULL) {
  97 + ERROR("Failed to allocate squashfs_super_block\n");
  98 + goto failure;
  99 + }
  100 +
  101 + msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE);
  102 + msblk->devblksize_log2 = ffz(~msblk->devblksize);
  103 +
  104 + mutex_init(&msblk->read_data_mutex);
  105 + mutex_init(&msblk->meta_index_mutex);
  106 +
  107 + /*
  108 + * msblk->bytes_used is checked in squashfs_read_table to ensure reads
  109 + * are not beyond filesystem end. But as we're using
  110 + * squashfs_read_table here to read the superblock (including the value
  111 + * of bytes_used) we need to set it to an initial sensible dummy value
  112 + */
  113 + msblk->bytes_used = sizeof(*sblk);
  114 + err = squashfs_read_table(sb, sblk, SQUASHFS_START, sizeof(*sblk));
  115 +
  116 + if (err < 0) {
  117 + ERROR("unable to read squashfs_super_block\n");
  118 + goto failed_mount;
  119 + }
  120 +
  121 + /* Check it is a SQUASHFS superblock */
  122 + sb->s_magic = le32_to_cpu(sblk->s_magic);
  123 + if (sb->s_magic != SQUASHFS_MAGIC) {
  124 + if (!silent)
  125 + ERROR("Can't find a SQUASHFS superblock on %s\n",
  126 + bdevname(sb->s_bdev, b));
  127 + err = -EINVAL;
  128 + goto failed_mount;
  129 + }
  130 +
  131 + /* Check the MAJOR & MINOR versions and compression type */
  132 + err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
  133 + le16_to_cpu(sblk->s_minor),
  134 + le16_to_cpu(sblk->compression));
  135 + if (err < 0)
  136 + goto failed_mount;
  137 +
  138 + err = -EINVAL;
  139 +
  140 + /*
  141 + * Check if there's xattrs in the filesystem. These are not
  142 + * supported in this version, so warn that they will be ignored.
  143 + */
  144 + if (le64_to_cpu(sblk->xattr_table_start) != SQUASHFS_INVALID_BLK)
  145 + ERROR("Xattrs in filesystem, these will be ignored\n");
  146 +
  147 + /* Check the filesystem does not extend beyond the end of the
  148 + block device */
  149 + msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
  150 + if (msblk->bytes_used < 0 || msblk->bytes_used >
  151 + i_size_read(sb->s_bdev->bd_inode))
  152 + goto failed_mount;
  153 +
  154 + /* Check block size for sanity */
  155 + msblk->block_size = le32_to_cpu(sblk->block_size);
  156 + if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
  157 + goto failed_mount;
  158 +
  159 + msblk->block_log = le16_to_cpu(sblk->block_log);
  160 + if (msblk->block_log > SQUASHFS_FILE_MAX_LOG)
  161 + goto failed_mount;
  162 +
  163 + /* Check the root inode for sanity */
  164 + root_inode = le64_to_cpu(sblk->root_inode);
  165 + if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
  166 + goto failed_mount;
  167 +
  168 + msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
  169 + msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
  170 + msblk->inodes = le32_to_cpu(sblk->inodes);
  171 + flags = le16_to_cpu(sblk->flags);
  172 +
  173 + TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b));
  174 + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(flags)
  175 + ? "un" : "");
  176 + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(flags)
  177 + ? "un" : "");
  178 + TRACE("Filesystem size %lld bytes\n", msblk->bytes_used);
  179 + TRACE("Block size %d\n", msblk->block_size);
  180 + TRACE("Number of inodes %d\n", msblk->inodes);
  181 + TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments));
  182 + TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids));
  183 + TRACE("sblk->inode_table_start %llx\n", msblk->inode_table);
  184 + TRACE("sblk->directory_table_start %llx\n", msblk->directory_table);
  185 + TRACE("sblk->fragment_table_start %llx\n",
  186 + (u64) le64_to_cpu(sblk->fragment_table_start));
  187 + TRACE("sblk->id_table_start %llx\n",
  188 + (u64) le64_to_cpu(sblk->id_table_start));
  189 +
  190 + sb->s_maxbytes = MAX_LFS_FILESIZE;
  191 + sb->s_flags |= MS_RDONLY;
  192 + sb->s_op = &squashfs_super_ops;
  193 +
  194 + err = -ENOMEM;
  195 +
  196 + msblk->block_cache = squashfs_cache_init("metadata",
  197 + SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
  198 + if (msblk->block_cache == NULL)
  199 + goto failed_mount;
  200 +
  201 + /* Allocate read_page block */
  202 + msblk->read_page = squashfs_cache_init("data", 1, msblk->block_size);
  203 + if (msblk->read_page == NULL) {
  204 + ERROR("Failed to allocate read_page block\n");
  205 + goto failed_mount;
  206 + }
  207 +
  208 + /* Allocate and read id index table */
  209 + msblk->id_table = squashfs_read_id_index_table(sb,
  210 + le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids));
  211 + if (IS_ERR(msblk->id_table)) {
  212 + err = PTR_ERR(msblk->id_table);
  213 + msblk->id_table = NULL;
  214 + goto failed_mount;
  215 + }
  216 +
  217 + fragments = le32_to_cpu(sblk->fragments);
  218 + if (fragments == 0)
  219 + goto allocate_lookup_table;
  220 +
  221 + msblk->fragment_cache = squashfs_cache_init("fragment",
  222 + SQUASHFS_CACHED_FRAGMENTS, msblk->block_size);
  223 + if (msblk->fragment_cache == NULL) {
  224 + err = -ENOMEM;
  225 + goto failed_mount;
  226 + }
  227 +
  228 + /* Allocate and read fragment index table */
  229 + msblk->fragment_index = squashfs_read_fragment_index_table(sb,
  230 + le64_to_cpu(sblk->fragment_table_start), fragments);
  231 + if (IS_ERR(msblk->fragment_index)) {
  232 + err = PTR_ERR(msblk->fragment_index);
  233 + msblk->fragment_index = NULL;
  234 + goto failed_mount;
  235 + }
  236 +
  237 +allocate_lookup_table:
  238 + lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
  239 + if (lookup_table_start == SQUASHFS_INVALID_BLK)
  240 + goto allocate_root;
  241 +
  242 + /* Allocate and read inode lookup table */
  243 + msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
  244 + lookup_table_start, msblk->inodes);
  245 + if (IS_ERR(msblk->inode_lookup_table)) {
  246 + err = PTR_ERR(msblk->inode_lookup_table);
  247 + msblk->inode_lookup_table = NULL;
  248 + goto failed_mount;
  249 + }
  250 +
  251 + sb->s_export_op = &squashfs_export_ops;
  252 +
  253 +allocate_root:
  254 + root = new_inode(sb);
  255 + if (!root) {
  256 + err = -ENOMEM;
  257 + goto failed_mount;
  258 + }
  259 +
  260 + err = squashfs_read_inode(root, root_inode);
  261 + if (err) {
  262 + iget_failed(root);
  263 + goto failed_mount;
  264 + }
  265 + insert_inode_hash(root);
  266 +
  267 + sb->s_root = d_alloc_root(root);
  268 + if (sb->s_root == NULL) {
  269 + ERROR("Root inode create failed\n");
  270 + err = -ENOMEM;
  271 + iput(root);
  272 + goto failed_mount;
  273 + }
  274 +
  275 + TRACE("Leaving squashfs_fill_super\n");
  276 + kfree(sblk);
  277 + return 0;
  278 +
  279 +failed_mount:
  280 + squashfs_cache_delete(msblk->block_cache);
  281 + squashfs_cache_delete(msblk->fragment_cache);
  282 + squashfs_cache_delete(msblk->read_page);
  283 + kfree(msblk->inode_lookup_table);
  284 + kfree(msblk->fragment_index);
  285 + kfree(msblk->id_table);
  286 + kfree(msblk->stream.workspace);
  287 + kfree(sb->s_fs_info);
  288 + sb->s_fs_info = NULL;
  289 + kfree(sblk);
  290 + return err;
  291 +
  292 +failure:
  293 + kfree(msblk->stream.workspace);
  294 + kfree(sb->s_fs_info);
  295 + sb->s_fs_info = NULL;
  296 + return -ENOMEM;
  297 +}
  298 +
  299 +
  300 +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  301 +{
  302 + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
  303 +
  304 + TRACE("Entered squashfs_statfs\n");
  305 +
  306 + buf->f_type = SQUASHFS_MAGIC;
  307 + buf->f_bsize = msblk->block_size;
  308 + buf->f_blocks = ((msblk->bytes_used - 1) >> msblk->block_log) + 1;
  309 + buf->f_bfree = buf->f_bavail = 0;
  310 + buf->f_files = msblk->inodes;
  311 + buf->f_ffree = 0;
  312 + buf->f_namelen = SQUASHFS_NAME_LEN;
  313 +
  314 + return 0;
  315 +}
  316 +
  317 +
  318 +static int squashfs_remount(struct super_block *sb, int *flags, char *data)
  319 +{
  320 + *flags |= MS_RDONLY;
  321 + return 0;
  322 +}
  323 +
  324 +
  325 +static void squashfs_put_super(struct super_block *sb)
  326 +{
  327 + if (sb->s_fs_info) {
  328 + struct squashfs_sb_info *sbi = sb->s_fs_info;
  329 + squashfs_cache_delete(sbi->block_cache);
  330 + squashfs_cache_delete(sbi->fragment_cache);
  331 + squashfs_cache_delete(sbi->read_page);
  332 + kfree(sbi->id_table);
  333 + kfree(sbi->fragment_index);
  334 + kfree(sbi->meta_index);
  335 + kfree(sbi->stream.workspace);
  336 + kfree(sb->s_fs_info);
  337 + sb->s_fs_info = NULL;
  338 + }
  339 +}
  340 +
  341 +
  342 +static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
  343 + const char *dev_name, void *data,
  344 + struct vfsmount *mnt)
  345 +{
  346 + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
  347 + mnt);
  348 +}
  349 +
  350 +
  351 +static struct kmem_cache *squashfs_inode_cachep;
  352 +
  353 +
  354 +static void init_once(void *foo)
  355 +{
  356 + struct squashfs_inode_info *ei = foo;
  357 +
  358 + inode_init_once(&ei->vfs_inode);
  359 +}
  360 +
  361 +
  362 +static int __init init_inodecache(void)
  363 +{
  364 + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
  365 + sizeof(struct squashfs_inode_info), 0,
  366 + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once);
  367 +
  368 + return squashfs_inode_cachep ? 0 : -ENOMEM;
  369 +}
  370 +
  371 +
  372 +static void destroy_inodecache(void)
  373 +{
  374 + kmem_cache_destroy(squashfs_inode_cachep);
  375 +}
  376 +
  377 +
  378 +static int __init init_squashfs_fs(void)
  379 +{
  380 + int err = init_inodecache();
  381 +
  382 + if (err)
  383 + return err;
  384 +
  385 + err = register_filesystem(&squashfs_fs_type);
  386 + if (err) {
  387 + destroy_inodecache();
  388 + return err;
  389 + }
  390 +
  391 + printk(KERN_INFO "squashfs: version 4.0 (2009/01/03) "
  392 + "Phillip Lougher\n");
  393 +
  394 + return 0;
  395 +}
  396 +
  397 +
  398 +static void __exit exit_squashfs_fs(void)
  399 +{
  400 + unregister_filesystem(&squashfs_fs_type);
  401 + destroy_inodecache();
  402 +}
  403 +
  404 +
  405 +static struct inode *squashfs_alloc_inode(struct super_block *sb)
  406 +{
  407 + struct squashfs_inode_info *ei =
  408 + kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
  409 +
  410 + return ei ? &ei->vfs_inode : NULL;
  411 +}
  412 +
  413 +
  414 +static void squashfs_destroy_inode(struct inode *inode)
  415 +{
  416 + kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode));
  417 +}
  418 +
  419 +
  420 +static struct file_system_type squashfs_fs_type = {
  421 + .owner = THIS_MODULE,
  422 + .name = "squashfs",
  423 + .get_sb = squashfs_get_sb,
  424 + .kill_sb = kill_block_super,
  425 + .fs_flags = FS_REQUIRES_DEV
  426 +};
  427 +
  428 +static struct super_operations squashfs_super_ops = {
  429 + .alloc_inode = squashfs_alloc_inode,
  430 + .destroy_inode = squashfs_destroy_inode,
  431 + .statfs = squashfs_statfs,
  432 + .put_super = squashfs_put_super,
  433 + .remount_fs = squashfs_remount
  434 +};
  435 +
  436 +module_init(init_squashfs_fs);
  437 +module_exit(exit_squashfs_fs);
  438 +MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem");
  439 +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
  440 +MODULE_LICENSE("GPL");
fs/squashfs/symlink.c
  1 +/*
  2 + * Squashfs - a compressed read only filesystem for Linux
  3 + *
  4 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
  5 + * Phillip Lougher <phillip@lougher.demon.co.uk>
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * as published by the Free Software Foundation; either version 2,
  10 + * or (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20 + *
  21 + * symlink.c
  22 + */
  23 +
  24 +/*
  25 + * This file implements code to handle symbolic links.
  26 + *
  27 + * The data contents of symbolic links are stored inside the symbolic
  28 + * link inode within the inode table. This allows the normally small symbolic
  29 + * link to be compressed as part of the inode table, achieving much greater
  30 + * compression than if the symbolic link was compressed individually.
  31 + */
  32 +
  33 +#include <linux/fs.h>
  34 +#include <linux/vfs.h>
  35 +#include <linux/kernel.h>
  36 +#include <linux/slab.h>
  37 +#include <linux/string.h>
  38 +#include <linux/pagemap.h>
  39 +#include <linux/zlib.h>
  40 +
  41 +#include "squashfs_fs.h"
  42 +#include "squashfs_fs_sb.h"
  43 +#include "squashfs_fs_i.h"
  44 +#include "squashfs.h"
  45 +
  46 +static int squashfs_symlink_readpage(struct file *file, struct page *page)
  47 +{
  48 + struct inode *inode = page->mapping->host;
  49 + struct super_block *sb = inode->i_sb;
  50 + struct squashfs_sb_info *msblk = sb->s_fs_info;
  51 + int index = page->index << PAGE_CACHE_SHIFT;
  52 + u64 block = squashfs_i(inode)->start;
  53 + int offset = squashfs_i(inode)->offset;
  54 + int length = min_t(int, i_size_read(inode) - index, PAGE_CACHE_SIZE);
  55 + int bytes, copied;
  56 + void *pageaddr;
  57 + struct squashfs_cache_entry *entry;
  58 +
  59 + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
  60 + "%llx, offset %x\n", page->index, block, offset);
  61 +
  62 + /*
  63 + * Skip index bytes into symlink metadata.
  64 + */
  65 + if (index) {
  66 + bytes = squashfs_read_metadata(sb, NULL, &block, &offset,
  67 + index);
  68 + if (bytes < 0) {
  69 + ERROR("Unable to read symlink [%llx:%x]\n",
  70 + squashfs_i(inode)->start,
  71 + squashfs_i(inode)->offset);
  72 + goto error_out;
  73 + }
  74 + }
  75 +
  76 + /*
  77 + * Read length bytes from symlink metadata. Squashfs_read_metadata
  78 + * is not used here because it can sleep and we want to use
  79 + * kmap_atomic to map the page. Instead call the underlying
  80 + * squashfs_cache_get routine. As length bytes may overlap metadata
  81 + * blocks, we may need to call squashfs_cache_get multiple times.
  82 + */
  83 + for (bytes = 0; bytes < length; offset = 0, bytes += copied) {
  84 + entry = squashfs_cache_get(sb, msblk->block_cache, block, 0);
  85 + if (entry->error) {
  86 + ERROR("Unable to read symlink [%llx:%x]\n",
  87 + squashfs_i(inode)->start,
  88 + squashfs_i(inode)->offset);
  89 + squashfs_cache_put(entry);
  90 + goto error_out;
  91 + }
  92 +
  93 + pageaddr = kmap_atomic(page, KM_USER0);
  94 + copied = squashfs_copy_data(pageaddr + bytes, entry, offset,
  95 + length - bytes);
  96 + if (copied == length - bytes)
  97 + memset(pageaddr + length, 0, PAGE_CACHE_SIZE - length);
  98 + else
  99 + block = entry->next_index;
  100 + kunmap_atomic(pageaddr, KM_USER0);
  101 + squashfs_cache_put(entry);
  102 + }
  103 +
  104 + flush_dcache_page(page);
  105 + SetPageUptodate(page);
  106 + unlock_page(page);
  107 + return 0;
  108 +
  109 +error_out:
  110 + SetPageError(page);
  111 + unlock_page(page);
  112 + return 0;
  113 +}
  114 +
  115 +
  116 +const struct address_space_operations squashfs_symlink_aops = {
  117 + .readpage = squashfs_symlink_readpage
  118 +};
... ... @@ -9,6 +9,7 @@
9 9 #include <linux/string.h>
10 10  
11 11 #include "do_mounts.h"
  12 +#include "../fs/squashfs/squashfs_fs.h"
12 13  
13 14 int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */
14 15  
... ... @@ -41,6 +42,7 @@
41 42 * ext2
42 43 * romfs
43 44 * cramfs
  45 + * squashfs
44 46 * gzip
45 47 */
46 48 static int __init
... ... @@ -51,6 +53,7 @@
51 53 struct ext2_super_block *ext2sb;
52 54 struct romfs_super_block *romfsb;
53 55 struct cramfs_super *cramfsb;
  56 + struct squashfs_super_block *squashfsb;
54 57 int nblocks = -1;
55 58 unsigned char *buf;
56 59  
... ... @@ -62,6 +65,7 @@
62 65 ext2sb = (struct ext2_super_block *) buf;
63 66 romfsb = (struct romfs_super_block *) buf;
64 67 cramfsb = (struct cramfs_super *) buf;
  68 + squashfsb = (struct squashfs_super_block *) buf;
65 69 memset(buf, 0xe5, size);
66 70  
67 71 /*
... ... @@ -96,6 +100,16 @@
96 100 "RAMDISK: cramfs filesystem found at block %d\n",
97 101 start_block);
98 102 nblocks = (cramfsb->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
  103 + goto done;
  104 + }
  105 +
  106 + /* squashfs is at block zero too */
  107 + if (le32_to_cpu(squashfsb->s_magic) == SQUASHFS_MAGIC) {
  108 + printk(KERN_NOTICE
  109 + "RAMDISK: squashfs filesystem found at block %d\n",
  110 + start_block);
  111 + nblocks = (le64_to_cpu(squashfsb->bytes_used) + BLOCK_SIZE - 1)
  112 + >> BLOCK_SIZE_BITS;
99 113 goto done;
100 114 }
101 115