aboutsummaryrefslogtreecommitdiffstats
path: root/fs/squashfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/squashfs')
-rw-r--r--fs/squashfs/Kconfig51
-rw-r--r--fs/squashfs/Makefile8
-rw-r--r--fs/squashfs/block.c274
-rw-r--r--fs/squashfs/cache.c412
-rw-r--r--fs/squashfs/dir.c235
-rw-r--r--fs/squashfs/export.c155
-rw-r--r--fs/squashfs/file.c502
-rw-r--r--fs/squashfs/fragment.c98
-rw-r--r--fs/squashfs/id.c94
-rw-r--r--fs/squashfs/inode.c346
-rw-r--r--fs/squashfs/namei.c242
-rw-r--r--fs/squashfs/squashfs.h90
-rw-r--r--fs/squashfs/squashfs_fs.h380
-rw-r--r--fs/squashfs/squashfs_fs_i.h45
-rw-r--r--fs/squashfs/squashfs_fs_sb.h76
-rw-r--r--fs/squashfs/super.c441
-rw-r--r--fs/squashfs/symlink.c118
17 files changed, 3567 insertions, 0 deletions
diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
new file mode 100644
index 000000000000..25a00d19d686
--- /dev/null
+++ b/fs/squashfs/Kconfig
@@ -0,0 +1,51 @@
1config SQUASHFS
2 tristate "SquashFS 4.0 - Squashed file system support"
3 depends on BLOCK
4 select ZLIB_INFLATE
5 help
6 Saying Y here includes support for SquashFS 4.0 (a Compressed
7 Read-Only File System). Squashfs is a highly compressed read-only
8 filesystem for Linux. It uses zlib compression to compress both
9 files, inodes and directories. Inodes in the system are very small
10 and all blocks are packed to minimise data overhead. Block sizes
11 greater than 4K are supported up to a maximum of 1 Mbytes (default
12 block size 128K). SquashFS 4.0 supports 64 bit filesystems and files
13 (larger than 4GB), full uid/gid information, hard links and
14 timestamps.
15
16 Squashfs is intended for general read-only filesystem use, for
17 archival use (i.e. in cases where a .tar.gz file may be used), and in
18 embedded systems where low overhead is needed. Further information
19 and tools are available from http://squashfs.sourceforge.net.
20
21 If you want to compile this as a module ( = code which can be
22 inserted in and removed from the running kernel whenever you want),
23 say M here and read <file:Documentation/modules.txt>. The module
24 will be called squashfs. Note that the root file system (the one
25 containing the directory /) cannot be compiled as a module.
26
27 If unsure, say N.
28
29config SQUASHFS_EMBEDDED
30
31 bool "Additional option for memory-constrained systems"
32 depends on SQUASHFS
33 default n
34 help
35 Saying Y here allows you to specify cache size.
36
37 If unsure, say N.
38
39config SQUASHFS_FRAGMENT_CACHE_SIZE
40 int "Number of fragments cached" if SQUASHFS_EMBEDDED
41 depends on SQUASHFS
42 default "3"
43 help
44 By default SquashFS caches the last 3 fragments read from
45 the filesystem. Increasing this amount may mean SquashFS
46 has to re-read fragments less often from disk, at the expense
47 of extra system memory. Decreasing this amount will mean
48 SquashFS uses less memory at the expense of extra reads from disk.
49
50 Note there must be at least one cached fragment. Anything
51 much more than three will probably not make much difference.
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
new file mode 100644
index 000000000000..8258cf9a0317
--- /dev/null
+++ b/fs/squashfs/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the linux squashfs routines.
3#
4
5obj-$(CONFIG_SQUASHFS) += squashfs.o
6squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
7squashfs-y += namei.o super.o symlink.o
8#squashfs-y += squashfs2_0.o
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
new file mode 100644
index 000000000000..c837dfc2b3c6
--- /dev/null
+++ b/fs/squashfs/block.c
@@ -0,0 +1,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 * 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 */
46static 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 */
82int 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
263release_mutex:
264 mutex_unlock(&msblk->read_data_mutex);
265
266block_release:
267 for (; k < b; k++)
268 put_bh(bh[k]);
269
270read_failure:
271 ERROR("sb_bread failed reading block 0x%llx\n", cur_index);
272 kfree(bh);
273 return -EIO;
274}
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
new file mode 100644
index 000000000000..f29eda16d25e
--- /dev/null
+++ b/fs/squashfs/cache.c
@@ -0,0 +1,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 * 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 */
66struct 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
170out:
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 */
184void 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 */
208void 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 */
233struct 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
283cleanup:
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 */
294int 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 */
332int 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 */
370struct 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 */
385struct 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 */
397int 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}
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
new file mode 100644
index 000000000000..566b0eaed868
--- /dev/null
+++ b/fs/squashfs/dir.c
@@ -0,0 +1,235 @@
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
40static 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 */
52static 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
104static 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
221finish:
222 kfree(dire);
223 return 0;
224
225failed_read:
226 ERROR("Unable to read directory block [%llx:%x]\n", block, offset);
227 kfree(dire);
228 return 0;
229}
230
231
232const struct file_operations squashfs_dir_ops = {
233 .read = generic_read_dir,
234 .readdir = squashfs_readdir
235};
diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c
new file mode 100644
index 000000000000..69e971d5ddc1
--- /dev/null
+++ b/fs/squashfs/export.c
@@ -0,0 +1,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 * 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 */
52static 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
74static 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
90static 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
101static 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
111static 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
151const 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};
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
new file mode 100644
index 000000000000..717767d831df
--- /dev/null
+++ b/fs/squashfs/file.c
@@ -0,0 +1,502 @@
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 */
61static 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
90not_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 */
100static 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
155failed:
156 mutex_unlock(&msblk->meta_index_mutex);
157 return meta;
158}
159
160
161static 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 */
174static 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
207failure:
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 */
224static 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 */
237static 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
316all_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
326failed:
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 */
336static 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
375static 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);
474skip_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
485error_out:
486 SetPageError(page);
487out:
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
500const struct address_space_operations squashfs_aops = {
501 .readpage = squashfs_readpage
502};
diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
new file mode 100644
index 000000000000..b5a2c15bbbc7
--- /dev/null
+++ b/fs/squashfs/fragment.c
@@ -0,0 +1,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 * 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 */
50int 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}
diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c
new file mode 100644
index 000000000000..3795b837ba28
--- /dev/null
+++ b/fs/squashfs/id.c
@@ -0,0 +1,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 * 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 */
47int 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}
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
new file mode 100644
index 000000000000..7a63398bb855
--- /dev/null
+++ b/fs/squashfs/inode.c
@@ -0,0 +1,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 * 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 */
55static 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
79struct 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 */
107int 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
343failed_read:
344 ERROR("Unable to read inode 0x%llx\n", ino);
345 return err;
346}
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
new file mode 100644
index 000000000000..9e398653b22b
--- /dev/null
+++ b/fs/squashfs/namei.c
@@ -0,0 +1,242 @@
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 */
75static 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
124out:
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
135static 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
223exit_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
230read_failure:
231 ERROR("Unable to read directory block [%llx:%x]\n",
232 squashfs_i(dir)->start + msblk->directory_table,
233 squashfs_i(dir)->offset);
234failed:
235 kfree(dire);
236 return ERR_PTR(err);
237}
238
239
240const struct inode_operations squashfs_dir_inode_ops = {
241 .lookup = squashfs_lookup
242};
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
new file mode 100644
index 000000000000..6b2515d027d5
--- /dev/null
+++ b/fs/squashfs/squashfs.h
@@ -0,0 +1,90 @@
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
30static 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 */
36extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *,
37 int);
38
39/* cache.c */
40extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
41extern void squashfs_cache_delete(struct squashfs_cache *);
42extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *,
43 struct squashfs_cache *, u64, int);
44extern void squashfs_cache_put(struct squashfs_cache_entry *);
45extern int squashfs_copy_data(void *, struct squashfs_cache_entry *, int, int);
46extern int squashfs_read_metadata(struct super_block *, void *, u64 *,
47 int *, int);
48extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *,
49 u64, int);
50extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *,
51 u64, int);
52extern int squashfs_read_table(struct super_block *, void *, u64, int);
53
54/* export.c */
55extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
56 unsigned int);
57
58/* fragment.c */
59extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *);
60extern __le64 *squashfs_read_fragment_index_table(struct super_block *,
61 u64, unsigned int);
62
63/* id.c */
64extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
65extern __le64 *squashfs_read_id_index_table(struct super_block *, u64,
66 unsigned short);
67
68/* inode.c */
69extern struct inode *squashfs_iget(struct super_block *, long long,
70 unsigned int);
71extern int squashfs_read_inode(struct inode *, long long);
72
73/*
74 * Inodes and files operations
75 */
76
77/* dir.c */
78extern const struct file_operations squashfs_dir_ops;
79
80/* export.c */
81extern const struct export_operations squashfs_export_ops;
82
83/* file.c */
84extern const struct address_space_operations squashfs_aops;
85
86/* namei.c */
87extern const struct inode_operations squashfs_dir_inode_ops;
88
89/* symlink.c */
90extern const struct address_space_operations squashfs_symlink_aops;
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
new file mode 100644
index 000000000000..283daafc568e
--- /dev/null
+++ b/fs/squashfs/squashfs_fs.h
@@ -0,0 +1,380 @@
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_START 0
30
31/* size of metadata (inode and directory) blocks */
32#define SQUASHFS_METADATA_SIZE 8192
33#define SQUASHFS_METADATA_LOG 13
34
35/* default size of data blocks */
36#define SQUASHFS_FILE_SIZE 131072
37#define SQUASHFS_FILE_LOG 17
38
39#define SQUASHFS_FILE_MAX_SIZE 1048576
40#define SQUASHFS_FILE_MAX_LOG 20
41
42/* Max number of uids and gids */
43#define SQUASHFS_IDS 65536
44
45/* Max length of filename (not 255) */
46#define SQUASHFS_NAME_LEN 256
47
48#define SQUASHFS_INVALID_FRAG (0xffffffffU)
49#define SQUASHFS_INVALID_BLK (-1LL)
50
51/* Filesystem flags */
52#define SQUASHFS_NOI 0
53#define SQUASHFS_NOD 1
54#define SQUASHFS_NOF 3
55#define SQUASHFS_NO_FRAG 4
56#define SQUASHFS_ALWAYS_FRAG 5
57#define SQUASHFS_DUPLICATE 6
58#define SQUASHFS_EXPORT 7
59
60#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
61
62#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
63 SQUASHFS_NOI)
64
65#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
66 SQUASHFS_NOD)
67
68#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
69 SQUASHFS_NOF)
70
71#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
72 SQUASHFS_NO_FRAG)
73
74#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
75 SQUASHFS_ALWAYS_FRAG)
76
77#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
78 SQUASHFS_DUPLICATE)
79
80#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
81 SQUASHFS_EXPORT)
82
83/* Max number of types and file types */
84#define SQUASHFS_DIR_TYPE 1
85#define SQUASHFS_REG_TYPE 2
86#define SQUASHFS_SYMLINK_TYPE 3
87#define SQUASHFS_BLKDEV_TYPE 4
88#define SQUASHFS_CHRDEV_TYPE 5
89#define SQUASHFS_FIFO_TYPE 6
90#define SQUASHFS_SOCKET_TYPE 7
91#define SQUASHFS_LDIR_TYPE 8
92#define SQUASHFS_LREG_TYPE 9
93#define SQUASHFS_LSYMLINK_TYPE 10
94#define SQUASHFS_LBLKDEV_TYPE 11
95#define SQUASHFS_LCHRDEV_TYPE 12
96#define SQUASHFS_LFIFO_TYPE 13
97#define SQUASHFS_LSOCKET_TYPE 14
98
99/* Flag whether block is compressed or uncompressed, bit is set if block is
100 * uncompressed */
101#define SQUASHFS_COMPRESSED_BIT (1 << 15)
102
103#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
104 (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
105
106#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
107
108#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
109
110#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \
111 ~SQUASHFS_COMPRESSED_BIT_BLOCK)
112
113#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
114
115/*
116 * Inode number ops. Inodes consist of a compressed block number, and an
117 * uncompressed offset within that block
118 */
119#define SQUASHFS_INODE_BLK(A) ((unsigned int) ((A) >> 16))
120
121#define SQUASHFS_INODE_OFFSET(A) ((unsigned int) ((A) & 0xffff))
122
123#define SQUASHFS_MKINODE(A, B) ((long long)(((long long) (A)\
124 << 16) + (B)))
125
126/* Translate between VFS mode and squashfs mode */
127#define SQUASHFS_MODE(A) ((A) & 0xfff)
128
129/* fragment and fragment table defines */
130#define SQUASHFS_FRAGMENT_BYTES(A) \
131 ((A) * sizeof(struct squashfs_fragment_entry))
132
133#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
134 SQUASHFS_METADATA_SIZE)
135
136#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
137 SQUASHFS_METADATA_SIZE)
138
139#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
140 SQUASHFS_METADATA_SIZE - 1) / \
141 SQUASHFS_METADATA_SIZE)
142
143#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
144 sizeof(u64))
145
146/* inode lookup table defines */
147#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(u64))
148
149#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
150 SQUASHFS_METADATA_SIZE)
151
152#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
153 SQUASHFS_METADATA_SIZE)
154
155#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
156 SQUASHFS_METADATA_SIZE - 1) / \
157 SQUASHFS_METADATA_SIZE)
158
159#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
160 sizeof(u64))
161
162/* uid/gid lookup table defines */
163#define SQUASHFS_ID_BYTES(A) ((A) * sizeof(unsigned int))
164
165#define SQUASHFS_ID_BLOCK(A) (SQUASHFS_ID_BYTES(A) / \
166 SQUASHFS_METADATA_SIZE)
167
168#define SQUASHFS_ID_BLOCK_OFFSET(A) (SQUASHFS_ID_BYTES(A) % \
169 SQUASHFS_METADATA_SIZE)
170
171#define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \
172 SQUASHFS_METADATA_SIZE - 1) / \
173 SQUASHFS_METADATA_SIZE)
174
175#define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\
176 sizeof(u64))
177
178/* cached data constants for filesystem */
179#define SQUASHFS_CACHED_BLKS 8
180
181#define SQUASHFS_MAX_FILE_SIZE_LOG 64
182
183#define SQUASHFS_MAX_FILE_SIZE (1LL << \
184 (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
185
186#define SQUASHFS_MARKER_BYTE 0xff
187
188/* meta index cache */
189#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
190#define SQUASHFS_META_ENTRIES 127
191#define SQUASHFS_META_SLOTS 8
192
193struct meta_entry {
194 u64 data_block;
195 unsigned int index_block;
196 unsigned short offset;
197 unsigned short pad;
198};
199
200struct meta_index {
201 unsigned int inode_number;
202 unsigned int offset;
203 unsigned short entries;
204 unsigned short skip;
205 unsigned short locked;
206 unsigned short pad;
207 struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
208};
209
210
211/*
212 * definitions for structures on disk
213 */
214#define ZLIB_COMPRESSION 1
215
216struct squashfs_super_block {
217 __le32 s_magic;
218 __le32 inodes;
219 __le32 mkfs_time;
220 __le32 block_size;
221 __le32 fragments;
222 __le16 compression;
223 __le16 block_log;
224 __le16 flags;
225 __le16 no_ids;
226 __le16 s_major;
227 __le16 s_minor;
228 __le64 root_inode;
229 __le64 bytes_used;
230 __le64 id_table_start;
231 __le64 xattr_table_start;
232 __le64 inode_table_start;
233 __le64 directory_table_start;
234 __le64 fragment_table_start;
235 __le64 lookup_table_start;
236};
237
238struct squashfs_dir_index {
239 __le32 index;
240 __le32 start_block;
241 __le32 size;
242 unsigned char name[0];
243};
244
245struct squashfs_base_inode {
246 __le16 inode_type;
247 __le16 mode;
248 __le16 uid;
249 __le16 guid;
250 __le32 mtime;
251 __le32 inode_number;
252};
253
254struct squashfs_ipc_inode {
255 __le16 inode_type;
256 __le16 mode;
257 __le16 uid;
258 __le16 guid;
259 __le32 mtime;
260 __le32 inode_number;
261 __le32 nlink;
262};
263
264struct squashfs_dev_inode {
265 __le16 inode_type;
266 __le16 mode;
267 __le16 uid;
268 __le16 guid;
269 __le32 mtime;
270 __le32 inode_number;
271 __le32 nlink;
272 __le32 rdev;
273};
274
275struct squashfs_symlink_inode {
276 __le16 inode_type;
277 __le16 mode;
278 __le16 uid;
279 __le16 guid;
280 __le32 mtime;
281 __le32 inode_number;
282 __le32 nlink;
283 __le32 symlink_size;
284 char symlink[0];
285};
286
287struct squashfs_reg_inode {
288 __le16 inode_type;
289 __le16 mode;
290 __le16 uid;
291 __le16 guid;
292 __le32 mtime;
293 __le32 inode_number;
294 __le32 start_block;
295 __le32 fragment;
296 __le32 offset;
297 __le32 file_size;
298 __le16 block_list[0];
299};
300
301struct squashfs_lreg_inode {
302 __le16 inode_type;
303 __le16 mode;
304 __le16 uid;
305 __le16 guid;
306 __le32 mtime;
307 __le32 inode_number;
308 __le64 start_block;
309 __le64 file_size;
310 __le64 sparse;
311 __le32 nlink;
312 __le32 fragment;
313 __le32 offset;
314 __le32 xattr;
315 __le16 block_list[0];
316};
317
318struct squashfs_dir_inode {
319 __le16 inode_type;
320 __le16 mode;
321 __le16 uid;
322 __le16 guid;
323 __le32 mtime;
324 __le32 inode_number;
325 __le32 start_block;
326 __le32 nlink;
327 __le16 file_size;
328 __le16 offset;
329 __le32 parent_inode;
330};
331
332struct squashfs_ldir_inode {
333 __le16 inode_type;
334 __le16 mode;
335 __le16 uid;
336 __le16 guid;
337 __le32 mtime;
338 __le32 inode_number;
339 __le32 nlink;
340 __le32 file_size;
341 __le32 start_block;
342 __le32 parent_inode;
343 __le16 i_count;
344 __le16 offset;
345 __le32 xattr;
346 struct squashfs_dir_index index[0];
347};
348
349union squashfs_inode {
350 struct squashfs_base_inode base;
351 struct squashfs_dev_inode dev;
352 struct squashfs_symlink_inode symlink;
353 struct squashfs_reg_inode reg;
354 struct squashfs_lreg_inode lreg;
355 struct squashfs_dir_inode dir;
356 struct squashfs_ldir_inode ldir;
357 struct squashfs_ipc_inode ipc;
358};
359
360struct squashfs_dir_entry {
361 __le16 offset;
362 __le16 inode_number;
363 __le16 type;
364 __le16 size;
365 char name[0];
366};
367
368struct squashfs_dir_header {
369 __le32 count;
370 __le32 start_block;
371 __le32 inode_number;
372};
373
374struct squashfs_fragment_entry {
375 __le64 start_block;
376 __le32 size;
377 unsigned int unused;
378};
379
380#endif
diff --git a/fs/squashfs/squashfs_fs_i.h b/fs/squashfs/squashfs_fs_i.h
new file mode 100644
index 000000000000..fbfca30c0c68
--- /dev/null
+++ b/fs/squashfs/squashfs_fs_i.h
@@ -0,0 +1,45 @@
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
26struct 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
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
new file mode 100644
index 000000000000..c8c65614dd1c
--- /dev/null
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -0,0 +1,76 @@
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
28struct 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
41struct 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
54struct 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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
new file mode 100644
index 000000000000..071df5b5b491
--- /dev/null
+++ b/fs/squashfs/super.c
@@ -0,0 +1,441 @@
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#include <linux/magic.h>
39
40#include "squashfs_fs.h"
41#include "squashfs_fs_sb.h"
42#include "squashfs_fs_i.h"
43#include "squashfs.h"
44
45static struct file_system_type squashfs_fs_type;
46static struct super_operations squashfs_super_ops;
47
48static int supported_squashfs_filesystem(short major, short minor, short comp)
49{
50 if (major < SQUASHFS_MAJOR) {
51 ERROR("Major/Minor mismatch, older Squashfs %d.%d "
52 "filesystems are unsupported\n", major, minor);
53 return -EINVAL;
54 } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
55 ERROR("Major/Minor mismatch, trying to mount newer "
56 "%d.%d filesystem\n", major, minor);
57 ERROR("Please update your kernel\n");
58 return -EINVAL;
59 }
60
61 if (comp != ZLIB_COMPRESSION)
62 return -EINVAL;
63
64 return 0;
65}
66
67
68static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
69{
70 struct squashfs_sb_info *msblk;
71 struct squashfs_super_block *sblk = NULL;
72 char b[BDEVNAME_SIZE];
73 struct inode *root;
74 long long root_inode;
75 unsigned short flags;
76 unsigned int fragments;
77 u64 lookup_table_start;
78 int err;
79
80 TRACE("Entered squashfs_fill_superblock\n");
81
82 sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL);
83 if (sb->s_fs_info == NULL) {
84 ERROR("Failed to allocate squashfs_sb_info\n");
85 return -ENOMEM;
86 }
87 msblk = sb->s_fs_info;
88
89 msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
90 GFP_KERNEL);
91 if (msblk->stream.workspace == NULL) {
92 ERROR("Failed to allocate zlib workspace\n");
93 goto failure;
94 }
95
96 sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
97 if (sblk == NULL) {
98 ERROR("Failed to allocate squashfs_super_block\n");
99 goto failure;
100 }
101
102 msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE);
103 msblk->devblksize_log2 = ffz(~msblk->devblksize);
104
105 mutex_init(&msblk->read_data_mutex);
106 mutex_init(&msblk->meta_index_mutex);
107
108 /*
109 * msblk->bytes_used is checked in squashfs_read_table to ensure reads
110 * are not beyond filesystem end. But as we're using
111 * squashfs_read_table here to read the superblock (including the value
112 * of bytes_used) we need to set it to an initial sensible dummy value
113 */
114 msblk->bytes_used = sizeof(*sblk);
115 err = squashfs_read_table(sb, sblk, SQUASHFS_START, sizeof(*sblk));
116
117 if (err < 0) {
118 ERROR("unable to read squashfs_super_block\n");
119 goto failed_mount;
120 }
121
122 /* Check it is a SQUASHFS superblock */
123 sb->s_magic = le32_to_cpu(sblk->s_magic);
124 if (sb->s_magic != SQUASHFS_MAGIC) {
125 if (!silent)
126 ERROR("Can't find a SQUASHFS superblock on %s\n",
127 bdevname(sb->s_bdev, b));
128 err = -EINVAL;
129 goto failed_mount;
130 }
131
132 /* Check the MAJOR & MINOR versions and compression type */
133 err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
134 le16_to_cpu(sblk->s_minor),
135 le16_to_cpu(sblk->compression));
136 if (err < 0)
137 goto failed_mount;
138
139 err = -EINVAL;
140
141 /*
142 * Check if there's xattrs in the filesystem. These are not
143 * supported in this version, so warn that they will be ignored.
144 */
145 if (le64_to_cpu(sblk->xattr_table_start) != SQUASHFS_INVALID_BLK)
146 ERROR("Xattrs in filesystem, these will be ignored\n");
147
148 /* Check the filesystem does not extend beyond the end of the
149 block device */
150 msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
151 if (msblk->bytes_used < 0 || msblk->bytes_used >
152 i_size_read(sb->s_bdev->bd_inode))
153 goto failed_mount;
154
155 /* Check block size for sanity */
156 msblk->block_size = le32_to_cpu(sblk->block_size);
157 if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
158 goto failed_mount;
159
160 msblk->block_log = le16_to_cpu(sblk->block_log);
161 if (msblk->block_log > SQUASHFS_FILE_MAX_LOG)
162 goto failed_mount;
163
164 /* Check the root inode for sanity */
165 root_inode = le64_to_cpu(sblk->root_inode);
166 if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
167 goto failed_mount;
168
169 msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
170 msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
171 msblk->inodes = le32_to_cpu(sblk->inodes);
172 flags = le16_to_cpu(sblk->flags);
173
174 TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b));
175 TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(flags)
176 ? "un" : "");
177 TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(flags)
178 ? "un" : "");
179 TRACE("Filesystem size %lld bytes\n", msblk->bytes_used);
180 TRACE("Block size %d\n", msblk->block_size);
181 TRACE("Number of inodes %d\n", msblk->inodes);
182 TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments));
183 TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids));
184 TRACE("sblk->inode_table_start %llx\n", msblk->inode_table);
185 TRACE("sblk->directory_table_start %llx\n", msblk->directory_table);
186 TRACE("sblk->fragment_table_start %llx\n",
187 (u64) le64_to_cpu(sblk->fragment_table_start));
188 TRACE("sblk->id_table_start %llx\n",
189 (u64) le64_to_cpu(sblk->id_table_start));
190
191 sb->s_maxbytes = MAX_LFS_FILESIZE;
192 sb->s_flags |= MS_RDONLY;
193 sb->s_op = &squashfs_super_ops;
194
195 err = -ENOMEM;
196
197 msblk->block_cache = squashfs_cache_init("metadata",
198 SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
199 if (msblk->block_cache == NULL)
200 goto failed_mount;
201
202 /* Allocate read_page block */
203 msblk->read_page = squashfs_cache_init("data", 1, msblk->block_size);
204 if (msblk->read_page == NULL) {
205 ERROR("Failed to allocate read_page block\n");
206 goto failed_mount;
207 }
208
209 /* Allocate and read id index table */
210 msblk->id_table = squashfs_read_id_index_table(sb,
211 le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids));
212 if (IS_ERR(msblk->id_table)) {
213 err = PTR_ERR(msblk->id_table);
214 msblk->id_table = NULL;
215 goto failed_mount;
216 }
217
218 fragments = le32_to_cpu(sblk->fragments);
219 if (fragments == 0)
220 goto allocate_lookup_table;
221
222 msblk->fragment_cache = squashfs_cache_init("fragment",
223 SQUASHFS_CACHED_FRAGMENTS, msblk->block_size);
224 if (msblk->fragment_cache == NULL) {
225 err = -ENOMEM;
226 goto failed_mount;
227 }
228
229 /* Allocate and read fragment index table */
230 msblk->fragment_index = squashfs_read_fragment_index_table(sb,
231 le64_to_cpu(sblk->fragment_table_start), fragments);
232 if (IS_ERR(msblk->fragment_index)) {
233 err = PTR_ERR(msblk->fragment_index);
234 msblk->fragment_index = NULL;
235 goto failed_mount;
236 }
237
238allocate_lookup_table:
239 lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
240 if (lookup_table_start == SQUASHFS_INVALID_BLK)
241 goto allocate_root;
242
243 /* Allocate and read inode lookup table */
244 msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
245 lookup_table_start, msblk->inodes);
246 if (IS_ERR(msblk->inode_lookup_table)) {
247 err = PTR_ERR(msblk->inode_lookup_table);
248 msblk->inode_lookup_table = NULL;
249 goto failed_mount;
250 }
251
252 sb->s_export_op = &squashfs_export_ops;
253
254allocate_root:
255 root = new_inode(sb);
256 if (!root) {
257 err = -ENOMEM;
258 goto failed_mount;
259 }
260
261 err = squashfs_read_inode(root, root_inode);
262 if (err) {
263 iget_failed(root);
264 goto failed_mount;
265 }
266 insert_inode_hash(root);
267
268 sb->s_root = d_alloc_root(root);
269 if (sb->s_root == NULL) {
270 ERROR("Root inode create failed\n");
271 err = -ENOMEM;
272 iput(root);
273 goto failed_mount;
274 }
275
276 TRACE("Leaving squashfs_fill_super\n");
277 kfree(sblk);
278 return 0;
279
280failed_mount:
281 squashfs_cache_delete(msblk->block_cache);
282 squashfs_cache_delete(msblk->fragment_cache);
283 squashfs_cache_delete(msblk->read_page);
284 kfree(msblk->inode_lookup_table);
285 kfree(msblk->fragment_index);
286 kfree(msblk->id_table);
287 kfree(msblk->stream.workspace);
288 kfree(sb->s_fs_info);
289 sb->s_fs_info = NULL;
290 kfree(sblk);
291 return err;
292
293failure:
294 kfree(msblk->stream.workspace);
295 kfree(sb->s_fs_info);
296 sb->s_fs_info = NULL;
297 return -ENOMEM;
298}
299
300
301static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
302{
303 struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
304
305 TRACE("Entered squashfs_statfs\n");
306
307 buf->f_type = SQUASHFS_MAGIC;
308 buf->f_bsize = msblk->block_size;
309 buf->f_blocks = ((msblk->bytes_used - 1) >> msblk->block_log) + 1;
310 buf->f_bfree = buf->f_bavail = 0;
311 buf->f_files = msblk->inodes;
312 buf->f_ffree = 0;
313 buf->f_namelen = SQUASHFS_NAME_LEN;
314
315 return 0;
316}
317
318
319static int squashfs_remount(struct super_block *sb, int *flags, char *data)
320{
321 *flags |= MS_RDONLY;
322 return 0;
323}
324
325
326static void squashfs_put_super(struct super_block *sb)
327{
328 if (sb->s_fs_info) {
329 struct squashfs_sb_info *sbi = sb->s_fs_info;
330 squashfs_cache_delete(sbi->block_cache);
331 squashfs_cache_delete(sbi->fragment_cache);
332 squashfs_cache_delete(sbi->read_page);
333 kfree(sbi->id_table);
334 kfree(sbi->fragment_index);
335 kfree(sbi->meta_index);
336 kfree(sbi->stream.workspace);
337 kfree(sb->s_fs_info);
338 sb->s_fs_info = NULL;
339 }
340}
341
342
343static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
344 const char *dev_name, void *data,
345 struct vfsmount *mnt)
346{
347 return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
348 mnt);
349}
350
351
352static struct kmem_cache *squashfs_inode_cachep;
353
354
355static void init_once(void *foo)
356{
357 struct squashfs_inode_info *ei = foo;
358
359 inode_init_once(&ei->vfs_inode);
360}
361
362
363static int __init init_inodecache(void)
364{
365 squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
366 sizeof(struct squashfs_inode_info), 0,
367 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once);
368
369 return squashfs_inode_cachep ? 0 : -ENOMEM;
370}
371
372
373static void destroy_inodecache(void)
374{
375 kmem_cache_destroy(squashfs_inode_cachep);
376}
377
378
379static int __init init_squashfs_fs(void)
380{
381 int err = init_inodecache();
382
383 if (err)
384 return err;
385
386 err = register_filesystem(&squashfs_fs_type);
387 if (err) {
388 destroy_inodecache();
389 return err;
390 }
391
392 printk(KERN_INFO "squashfs: version 4.0 (2009/01/03) "
393 "Phillip Lougher\n");
394
395 return 0;
396}
397
398
399static void __exit exit_squashfs_fs(void)
400{
401 unregister_filesystem(&squashfs_fs_type);
402 destroy_inodecache();
403}
404
405
406static struct inode *squashfs_alloc_inode(struct super_block *sb)
407{
408 struct squashfs_inode_info *ei =
409 kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
410
411 return ei ? &ei->vfs_inode : NULL;
412}
413
414
415static void squashfs_destroy_inode(struct inode *inode)
416{
417 kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode));
418}
419
420
421static struct file_system_type squashfs_fs_type = {
422 .owner = THIS_MODULE,
423 .name = "squashfs",
424 .get_sb = squashfs_get_sb,
425 .kill_sb = kill_block_super,
426 .fs_flags = FS_REQUIRES_DEV
427};
428
429static struct super_operations squashfs_super_ops = {
430 .alloc_inode = squashfs_alloc_inode,
431 .destroy_inode = squashfs_destroy_inode,
432 .statfs = squashfs_statfs,
433 .put_super = squashfs_put_super,
434 .remount_fs = squashfs_remount
435};
436
437module_init(init_squashfs_fs);
438module_exit(exit_squashfs_fs);
439MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem");
440MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
441MODULE_LICENSE("GPL");
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
new file mode 100644
index 000000000000..83d87880aac8
--- /dev/null
+++ b/fs/squashfs/symlink.c
@@ -0,0 +1,118 @@
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
46static 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
109error_out:
110 SetPageError(page);
111 unlock_page(page);
112 return 0;
113}
114
115
116const struct address_space_operations squashfs_symlink_aops = {
117 .readpage = squashfs_symlink_readpage
118};