Commit 82de647e1f81fd89afc48608d889dd3b33cb8983

Authored by Phillip Lougher
1 parent 117a91e0f2

Squashfs: move table allocation into squashfs_read_table()

This eliminates a lot of duplicate code.

Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>

Showing 7 changed files with 44 additions and 98 deletions Inline Diff

1 /* 1 /*
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@lougher.demon.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2, 9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version. 10 * or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 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 18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * 20 *
21 * cache.c 21 * cache.c
22 */ 22 */
23 23
24 /* 24 /*
25 * Blocks in Squashfs are compressed. To avoid repeatedly decompressing 25 * Blocks in Squashfs are compressed. To avoid repeatedly decompressing
26 * recently accessed data Squashfs uses two small metadata and fragment caches. 26 * recently accessed data Squashfs uses two small metadata and fragment caches.
27 * 27 *
28 * This file implements a generic cache implementation used for both caches, 28 * This file implements a generic cache implementation used for both caches,
29 * plus functions layered ontop of the generic cache implementation to 29 * plus functions layered ontop of the generic cache implementation to
30 * access the metadata and fragment caches. 30 * access the metadata and fragment caches.
31 * 31 *
32 * To avoid out of memory and fragmentation isssues with vmalloc the cache 32 * To avoid out of memory and fragmentation isssues with vmalloc the cache
33 * uses sequences of kmalloced PAGE_CACHE_SIZE buffers. 33 * uses sequences of kmalloced PAGE_CACHE_SIZE buffers.
34 * 34 *
35 * It should be noted that the cache is not used for file datablocks, these 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 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 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 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 39 * directory) or fragment access. Because metadata and fragments are packed
40 * together into blocks (to gain greater compression) the read of a particular 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 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 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 43 * in the near future. Temporarily caching them ensures they are available for
44 * near future access without requiring an additional read and decompress. 44 * near future access without requiring an additional read and decompress.
45 */ 45 */
46 46
47 #include <linux/fs.h> 47 #include <linux/fs.h>
48 #include <linux/vfs.h> 48 #include <linux/vfs.h>
49 #include <linux/slab.h> 49 #include <linux/slab.h>
50 #include <linux/vmalloc.h> 50 #include <linux/vmalloc.h>
51 #include <linux/sched.h> 51 #include <linux/sched.h>
52 #include <linux/spinlock.h> 52 #include <linux/spinlock.h>
53 #include <linux/wait.h> 53 #include <linux/wait.h>
54 #include <linux/pagemap.h> 54 #include <linux/pagemap.h>
55 55
56 #include "squashfs_fs.h" 56 #include "squashfs_fs.h"
57 #include "squashfs_fs_sb.h" 57 #include "squashfs_fs_sb.h"
58 #include "squashfs.h" 58 #include "squashfs.h"
59 59
60 /* 60 /*
61 * Look-up block in cache, and increment usage count. If not in cache, read 61 * Look-up block in cache, and increment usage count. If not in cache, read
62 * and decompress it from disk. 62 * and decompress it from disk.
63 */ 63 */
64 struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb, 64 struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb,
65 struct squashfs_cache *cache, u64 block, int length) 65 struct squashfs_cache *cache, u64 block, int length)
66 { 66 {
67 int i, n; 67 int i, n;
68 struct squashfs_cache_entry *entry; 68 struct squashfs_cache_entry *entry;
69 69
70 spin_lock(&cache->lock); 70 spin_lock(&cache->lock);
71 71
72 while (1) { 72 while (1) {
73 for (i = 0; i < cache->entries; i++) 73 for (i = 0; i < cache->entries; i++)
74 if (cache->entry[i].block == block) 74 if (cache->entry[i].block == block)
75 break; 75 break;
76 76
77 if (i == cache->entries) { 77 if (i == cache->entries) {
78 /* 78 /*
79 * Block not in cache, if all cache entries are used 79 * Block not in cache, if all cache entries are used
80 * go to sleep waiting for one to become available. 80 * go to sleep waiting for one to become available.
81 */ 81 */
82 if (cache->unused == 0) { 82 if (cache->unused == 0) {
83 cache->num_waiters++; 83 cache->num_waiters++;
84 spin_unlock(&cache->lock); 84 spin_unlock(&cache->lock);
85 wait_event(cache->wait_queue, cache->unused); 85 wait_event(cache->wait_queue, cache->unused);
86 spin_lock(&cache->lock); 86 spin_lock(&cache->lock);
87 cache->num_waiters--; 87 cache->num_waiters--;
88 continue; 88 continue;
89 } 89 }
90 90
91 /* 91 /*
92 * At least one unused cache entry. A simple 92 * At least one unused cache entry. A simple
93 * round-robin strategy is used to choose the entry to 93 * round-robin strategy is used to choose the entry to
94 * be evicted from the cache. 94 * be evicted from the cache.
95 */ 95 */
96 i = cache->next_blk; 96 i = cache->next_blk;
97 for (n = 0; n < cache->entries; n++) { 97 for (n = 0; n < cache->entries; n++) {
98 if (cache->entry[i].refcount == 0) 98 if (cache->entry[i].refcount == 0)
99 break; 99 break;
100 i = (i + 1) % cache->entries; 100 i = (i + 1) % cache->entries;
101 } 101 }
102 102
103 cache->next_blk = (i + 1) % cache->entries; 103 cache->next_blk = (i + 1) % cache->entries;
104 entry = &cache->entry[i]; 104 entry = &cache->entry[i];
105 105
106 /* 106 /*
107 * Initialise choosen cache entry, and fill it in from 107 * Initialise choosen cache entry, and fill it in from
108 * disk. 108 * disk.
109 */ 109 */
110 cache->unused--; 110 cache->unused--;
111 entry->block = block; 111 entry->block = block;
112 entry->refcount = 1; 112 entry->refcount = 1;
113 entry->pending = 1; 113 entry->pending = 1;
114 entry->num_waiters = 0; 114 entry->num_waiters = 0;
115 entry->error = 0; 115 entry->error = 0;
116 spin_unlock(&cache->lock); 116 spin_unlock(&cache->lock);
117 117
118 entry->length = squashfs_read_data(sb, entry->data, 118 entry->length = squashfs_read_data(sb, entry->data,
119 block, length, &entry->next_index, 119 block, length, &entry->next_index,
120 cache->block_size, cache->pages); 120 cache->block_size, cache->pages);
121 121
122 spin_lock(&cache->lock); 122 spin_lock(&cache->lock);
123 123
124 if (entry->length < 0) 124 if (entry->length < 0)
125 entry->error = entry->length; 125 entry->error = entry->length;
126 126
127 entry->pending = 0; 127 entry->pending = 0;
128 128
129 /* 129 /*
130 * While filling this entry one or more other processes 130 * While filling this entry one or more other processes
131 * have looked it up in the cache, and have slept 131 * have looked it up in the cache, and have slept
132 * waiting for it to become available. 132 * waiting for it to become available.
133 */ 133 */
134 if (entry->num_waiters) { 134 if (entry->num_waiters) {
135 spin_unlock(&cache->lock); 135 spin_unlock(&cache->lock);
136 wake_up_all(&entry->wait_queue); 136 wake_up_all(&entry->wait_queue);
137 } else 137 } else
138 spin_unlock(&cache->lock); 138 spin_unlock(&cache->lock);
139 139
140 goto out; 140 goto out;
141 } 141 }
142 142
143 /* 143 /*
144 * Block already in cache. Increment refcount so it doesn't 144 * Block already in cache. Increment refcount so it doesn't
145 * get reused until we're finished with it, if it was 145 * get reused until we're finished with it, if it was
146 * previously unused there's one less cache entry available 146 * previously unused there's one less cache entry available
147 * for reuse. 147 * for reuse.
148 */ 148 */
149 entry = &cache->entry[i]; 149 entry = &cache->entry[i];
150 if (entry->refcount == 0) 150 if (entry->refcount == 0)
151 cache->unused--; 151 cache->unused--;
152 entry->refcount++; 152 entry->refcount++;
153 153
154 /* 154 /*
155 * If the entry is currently being filled in by another process 155 * If the entry is currently being filled in by another process
156 * go to sleep waiting for it to become available. 156 * go to sleep waiting for it to become available.
157 */ 157 */
158 if (entry->pending) { 158 if (entry->pending) {
159 entry->num_waiters++; 159 entry->num_waiters++;
160 spin_unlock(&cache->lock); 160 spin_unlock(&cache->lock);
161 wait_event(entry->wait_queue, !entry->pending); 161 wait_event(entry->wait_queue, !entry->pending);
162 } else 162 } else
163 spin_unlock(&cache->lock); 163 spin_unlock(&cache->lock);
164 164
165 goto out; 165 goto out;
166 } 166 }
167 167
168 out: 168 out:
169 TRACE("Got %s %d, start block %lld, refcount %d, error %d\n", 169 TRACE("Got %s %d, start block %lld, refcount %d, error %d\n",
170 cache->name, i, entry->block, entry->refcount, entry->error); 170 cache->name, i, entry->block, entry->refcount, entry->error);
171 171
172 if (entry->error) 172 if (entry->error)
173 ERROR("Unable to read %s cache entry [%llx]\n", cache->name, 173 ERROR("Unable to read %s cache entry [%llx]\n", cache->name,
174 block); 174 block);
175 return entry; 175 return entry;
176 } 176 }
177 177
178 178
179 /* 179 /*
180 * Release cache entry, once usage count is zero it can be reused. 180 * Release cache entry, once usage count is zero it can be reused.
181 */ 181 */
182 void squashfs_cache_put(struct squashfs_cache_entry *entry) 182 void squashfs_cache_put(struct squashfs_cache_entry *entry)
183 { 183 {
184 struct squashfs_cache *cache = entry->cache; 184 struct squashfs_cache *cache = entry->cache;
185 185
186 spin_lock(&cache->lock); 186 spin_lock(&cache->lock);
187 entry->refcount--; 187 entry->refcount--;
188 if (entry->refcount == 0) { 188 if (entry->refcount == 0) {
189 cache->unused++; 189 cache->unused++;
190 /* 190 /*
191 * If there's any processes waiting for a block to become 191 * If there's any processes waiting for a block to become
192 * available, wake one up. 192 * available, wake one up.
193 */ 193 */
194 if (cache->num_waiters) { 194 if (cache->num_waiters) {
195 spin_unlock(&cache->lock); 195 spin_unlock(&cache->lock);
196 wake_up(&cache->wait_queue); 196 wake_up(&cache->wait_queue);
197 return; 197 return;
198 } 198 }
199 } 199 }
200 spin_unlock(&cache->lock); 200 spin_unlock(&cache->lock);
201 } 201 }
202 202
203 /* 203 /*
204 * Delete cache reclaiming all kmalloced buffers. 204 * Delete cache reclaiming all kmalloced buffers.
205 */ 205 */
206 void squashfs_cache_delete(struct squashfs_cache *cache) 206 void squashfs_cache_delete(struct squashfs_cache *cache)
207 { 207 {
208 int i, j; 208 int i, j;
209 209
210 if (cache == NULL) 210 if (cache == NULL)
211 return; 211 return;
212 212
213 for (i = 0; i < cache->entries; i++) { 213 for (i = 0; i < cache->entries; i++) {
214 if (cache->entry[i].data) { 214 if (cache->entry[i].data) {
215 for (j = 0; j < cache->pages; j++) 215 for (j = 0; j < cache->pages; j++)
216 kfree(cache->entry[i].data[j]); 216 kfree(cache->entry[i].data[j]);
217 kfree(cache->entry[i].data); 217 kfree(cache->entry[i].data);
218 } 218 }
219 } 219 }
220 220
221 kfree(cache->entry); 221 kfree(cache->entry);
222 kfree(cache); 222 kfree(cache);
223 } 223 }
224 224
225 225
226 /* 226 /*
227 * Initialise cache allocating the specified number of entries, each of 227 * Initialise cache allocating the specified number of entries, each of
228 * size block_size. To avoid vmalloc fragmentation issues each entry 228 * size block_size. To avoid vmalloc fragmentation issues each entry
229 * is allocated as a sequence of kmalloced PAGE_CACHE_SIZE buffers. 229 * is allocated as a sequence of kmalloced PAGE_CACHE_SIZE buffers.
230 */ 230 */
231 struct squashfs_cache *squashfs_cache_init(char *name, int entries, 231 struct squashfs_cache *squashfs_cache_init(char *name, int entries,
232 int block_size) 232 int block_size)
233 { 233 {
234 int i, j; 234 int i, j;
235 struct squashfs_cache *cache = kzalloc(sizeof(*cache), GFP_KERNEL); 235 struct squashfs_cache *cache = kzalloc(sizeof(*cache), GFP_KERNEL);
236 236
237 if (cache == NULL) { 237 if (cache == NULL) {
238 ERROR("Failed to allocate %s cache\n", name); 238 ERROR("Failed to allocate %s cache\n", name);
239 return NULL; 239 return NULL;
240 } 240 }
241 241
242 cache->entry = kcalloc(entries, sizeof(*(cache->entry)), GFP_KERNEL); 242 cache->entry = kcalloc(entries, sizeof(*(cache->entry)), GFP_KERNEL);
243 if (cache->entry == NULL) { 243 if (cache->entry == NULL) {
244 ERROR("Failed to allocate %s cache\n", name); 244 ERROR("Failed to allocate %s cache\n", name);
245 goto cleanup; 245 goto cleanup;
246 } 246 }
247 247
248 cache->next_blk = 0; 248 cache->next_blk = 0;
249 cache->unused = entries; 249 cache->unused = entries;
250 cache->entries = entries; 250 cache->entries = entries;
251 cache->block_size = block_size; 251 cache->block_size = block_size;
252 cache->pages = block_size >> PAGE_CACHE_SHIFT; 252 cache->pages = block_size >> PAGE_CACHE_SHIFT;
253 cache->pages = cache->pages ? cache->pages : 1; 253 cache->pages = cache->pages ? cache->pages : 1;
254 cache->name = name; 254 cache->name = name;
255 cache->num_waiters = 0; 255 cache->num_waiters = 0;
256 spin_lock_init(&cache->lock); 256 spin_lock_init(&cache->lock);
257 init_waitqueue_head(&cache->wait_queue); 257 init_waitqueue_head(&cache->wait_queue);
258 258
259 for (i = 0; i < entries; i++) { 259 for (i = 0; i < entries; i++) {
260 struct squashfs_cache_entry *entry = &cache->entry[i]; 260 struct squashfs_cache_entry *entry = &cache->entry[i];
261 261
262 init_waitqueue_head(&cache->entry[i].wait_queue); 262 init_waitqueue_head(&cache->entry[i].wait_queue);
263 entry->cache = cache; 263 entry->cache = cache;
264 entry->block = SQUASHFS_INVALID_BLK; 264 entry->block = SQUASHFS_INVALID_BLK;
265 entry->data = kcalloc(cache->pages, sizeof(void *), GFP_KERNEL); 265 entry->data = kcalloc(cache->pages, sizeof(void *), GFP_KERNEL);
266 if (entry->data == NULL) { 266 if (entry->data == NULL) {
267 ERROR("Failed to allocate %s cache entry\n", name); 267 ERROR("Failed to allocate %s cache entry\n", name);
268 goto cleanup; 268 goto cleanup;
269 } 269 }
270 270
271 for (j = 0; j < cache->pages; j++) { 271 for (j = 0; j < cache->pages; j++) {
272 entry->data[j] = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); 272 entry->data[j] = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
273 if (entry->data[j] == NULL) { 273 if (entry->data[j] == NULL) {
274 ERROR("Failed to allocate %s buffer\n", name); 274 ERROR("Failed to allocate %s buffer\n", name);
275 goto cleanup; 275 goto cleanup;
276 } 276 }
277 } 277 }
278 } 278 }
279 279
280 return cache; 280 return cache;
281 281
282 cleanup: 282 cleanup:
283 squashfs_cache_delete(cache); 283 squashfs_cache_delete(cache);
284 return NULL; 284 return NULL;
285 } 285 }
286 286
287 287
288 /* 288 /*
289 * Copy upto length bytes from cache entry to buffer starting at offset bytes 289 * Copy upto length bytes from cache entry to buffer starting at offset bytes
290 * into the cache entry. If there's not length bytes then copy the number of 290 * into the cache entry. If there's not length bytes then copy the number of
291 * bytes available. In all cases return the number of bytes copied. 291 * bytes available. In all cases return the number of bytes copied.
292 */ 292 */
293 int squashfs_copy_data(void *buffer, struct squashfs_cache_entry *entry, 293 int squashfs_copy_data(void *buffer, struct squashfs_cache_entry *entry,
294 int offset, int length) 294 int offset, int length)
295 { 295 {
296 int remaining = length; 296 int remaining = length;
297 297
298 if (length == 0) 298 if (length == 0)
299 return 0; 299 return 0;
300 else if (buffer == NULL) 300 else if (buffer == NULL)
301 return min(length, entry->length - offset); 301 return min(length, entry->length - offset);
302 302
303 while (offset < entry->length) { 303 while (offset < entry->length) {
304 void *buff = entry->data[offset / PAGE_CACHE_SIZE] 304 void *buff = entry->data[offset / PAGE_CACHE_SIZE]
305 + (offset % PAGE_CACHE_SIZE); 305 + (offset % PAGE_CACHE_SIZE);
306 int bytes = min_t(int, entry->length - offset, 306 int bytes = min_t(int, entry->length - offset,
307 PAGE_CACHE_SIZE - (offset % PAGE_CACHE_SIZE)); 307 PAGE_CACHE_SIZE - (offset % PAGE_CACHE_SIZE));
308 308
309 if (bytes >= remaining) { 309 if (bytes >= remaining) {
310 memcpy(buffer, buff, remaining); 310 memcpy(buffer, buff, remaining);
311 remaining = 0; 311 remaining = 0;
312 break; 312 break;
313 } 313 }
314 314
315 memcpy(buffer, buff, bytes); 315 memcpy(buffer, buff, bytes);
316 buffer += bytes; 316 buffer += bytes;
317 remaining -= bytes; 317 remaining -= bytes;
318 offset += bytes; 318 offset += bytes;
319 } 319 }
320 320
321 return length - remaining; 321 return length - remaining;
322 } 322 }
323 323
324 324
325 /* 325 /*
326 * Read length bytes from metadata position <block, offset> (block is the 326 * Read length bytes from metadata position <block, offset> (block is the
327 * start of the compressed block on disk, and offset is the offset into 327 * start of the compressed block on disk, and offset is the offset into
328 * the block once decompressed). Data is packed into consecutive blocks, 328 * the block once decompressed). Data is packed into consecutive blocks,
329 * and length bytes may require reading more than one block. 329 * and length bytes may require reading more than one block.
330 */ 330 */
331 int squashfs_read_metadata(struct super_block *sb, void *buffer, 331 int squashfs_read_metadata(struct super_block *sb, void *buffer,
332 u64 *block, int *offset, int length) 332 u64 *block, int *offset, int length)
333 { 333 {
334 struct squashfs_sb_info *msblk = sb->s_fs_info; 334 struct squashfs_sb_info *msblk = sb->s_fs_info;
335 int bytes, copied = length; 335 int bytes, copied = length;
336 struct squashfs_cache_entry *entry; 336 struct squashfs_cache_entry *entry;
337 337
338 TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset); 338 TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset);
339 339
340 while (length) { 340 while (length) {
341 entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0); 341 entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0);
342 if (entry->error) 342 if (entry->error)
343 return entry->error; 343 return entry->error;
344 else if (*offset >= entry->length) 344 else if (*offset >= entry->length)
345 return -EIO; 345 return -EIO;
346 346
347 bytes = squashfs_copy_data(buffer, entry, *offset, length); 347 bytes = squashfs_copy_data(buffer, entry, *offset, length);
348 if (buffer) 348 if (buffer)
349 buffer += bytes; 349 buffer += bytes;
350 length -= bytes; 350 length -= bytes;
351 *offset += bytes; 351 *offset += bytes;
352 352
353 if (*offset == entry->length) { 353 if (*offset == entry->length) {
354 *block = entry->next_index; 354 *block = entry->next_index;
355 *offset = 0; 355 *offset = 0;
356 } 356 }
357 357
358 squashfs_cache_put(entry); 358 squashfs_cache_put(entry);
359 } 359 }
360 360
361 return copied; 361 return copied;
362 } 362 }
363 363
364 364
365 /* 365 /*
366 * Look-up in the fragmment cache the fragment located at <start_block> in the 366 * Look-up in the fragmment cache the fragment located at <start_block> in the
367 * filesystem. If necessary read and decompress it from disk. 367 * filesystem. If necessary read and decompress it from disk.
368 */ 368 */
369 struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *sb, 369 struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *sb,
370 u64 start_block, int length) 370 u64 start_block, int length)
371 { 371 {
372 struct squashfs_sb_info *msblk = sb->s_fs_info; 372 struct squashfs_sb_info *msblk = sb->s_fs_info;
373 373
374 return squashfs_cache_get(sb, msblk->fragment_cache, start_block, 374 return squashfs_cache_get(sb, msblk->fragment_cache, start_block,
375 length); 375 length);
376 } 376 }
377 377
378 378
379 /* 379 /*
380 * Read and decompress the datablock located at <start_block> in the 380 * Read and decompress the datablock located at <start_block> in the
381 * filesystem. The cache is used here to avoid duplicating locking and 381 * filesystem. The cache is used here to avoid duplicating locking and
382 * read/decompress code. 382 * read/decompress code.
383 */ 383 */
384 struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb, 384 struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb,
385 u64 start_block, int length) 385 u64 start_block, int length)
386 { 386 {
387 struct squashfs_sb_info *msblk = sb->s_fs_info; 387 struct squashfs_sb_info *msblk = sb->s_fs_info;
388 388
389 return squashfs_cache_get(sb, msblk->read_page, start_block, length); 389 return squashfs_cache_get(sb, msblk->read_page, start_block, length);
390 } 390 }
391 391
392 392
393 /* 393 /*
394 * Read a filesystem table (uncompressed sequence of bytes) from disk 394 * Read a filesystem table (uncompressed sequence of bytes) from disk
395 */ 395 */
396 int squashfs_read_table(struct super_block *sb, void *buffer, u64 block, 396 void *squashfs_read_table(struct super_block *sb, u64 block, int length)
397 int length)
398 { 397 {
399 int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 398 int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
400 int i, res; 399 int i, res;
401 void **data = kcalloc(pages, sizeof(void *), GFP_KERNEL); 400 void *table, *buffer, **data;
402 if (data == NULL)
403 return -ENOMEM;
404 401
402 table = buffer = kmalloc(length, GFP_KERNEL);
403 if (table == NULL)
404 return ERR_PTR(-ENOMEM);
405
406 data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
407 if (data == NULL) {
408 res = -ENOMEM;
409 goto failed;
410 }
411
405 for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE) 412 for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
406 data[i] = buffer; 413 data[i] = buffer;
414
407 res = squashfs_read_data(sb, data, block, length | 415 res = squashfs_read_data(sb, data, block, length |
408 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages); 416 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages);
417
409 kfree(data); 418 kfree(data);
410 return res; 419
420 if (res < 0)
421 goto failed;
422
423 return table;
424
425 failed:
426 kfree(table);
fs/squashfs/export.c
1 /* 1 /*
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@lougher.demon.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2, 9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version. 10 * or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 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 18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * 20 *
21 * export.c 21 * export.c
22 */ 22 */
23 23
24 /* 24 /*
25 * This file implements code to make Squashfs filesystems exportable (NFS etc.) 25 * This file implements code to make Squashfs filesystems exportable (NFS etc.)
26 * 26 *
27 * The export code uses an inode lookup table to map inode numbers passed in 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 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 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 30 * second index table for speed of access (and because it is small) is read at
31 * mount time and cached in memory. 31 * mount time and cached in memory.
32 * 32 *
33 * The inode lookup table is used only by the export code, inode disk 33 * The inode lookup table is used only by the export code, inode disk
34 * locations are directly encoded in directories, enabling direct access 34 * locations are directly encoded in directories, enabling direct access
35 * without an intermediate lookup for all operations except the export ops. 35 * without an intermediate lookup for all operations except the export ops.
36 */ 36 */
37 37
38 #include <linux/fs.h> 38 #include <linux/fs.h>
39 #include <linux/vfs.h> 39 #include <linux/vfs.h>
40 #include <linux/dcache.h> 40 #include <linux/dcache.h>
41 #include <linux/exportfs.h> 41 #include <linux/exportfs.h>
42 #include <linux/slab.h> 42 #include <linux/slab.h>
43 43
44 #include "squashfs_fs.h" 44 #include "squashfs_fs.h"
45 #include "squashfs_fs_sb.h" 45 #include "squashfs_fs_sb.h"
46 #include "squashfs_fs_i.h" 46 #include "squashfs_fs_i.h"
47 #include "squashfs.h" 47 #include "squashfs.h"
48 48
49 /* 49 /*
50 * Look-up inode number (ino) in table, returning the inode location. 50 * Look-up inode number (ino) in table, returning the inode location.
51 */ 51 */
52 static long long squashfs_inode_lookup(struct super_block *sb, int ino_num) 52 static long long squashfs_inode_lookup(struct super_block *sb, int ino_num)
53 { 53 {
54 struct squashfs_sb_info *msblk = sb->s_fs_info; 54 struct squashfs_sb_info *msblk = sb->s_fs_info;
55 int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1); 55 int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1);
56 int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1); 56 int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1);
57 u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]); 57 u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]);
58 __le64 ino; 58 __le64 ino;
59 int err; 59 int err;
60 60
61 TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num); 61 TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num);
62 62
63 err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino)); 63 err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino));
64 if (err < 0) 64 if (err < 0)
65 return err; 65 return err;
66 66
67 TRACE("squashfs_inode_lookup, inode = 0x%llx\n", 67 TRACE("squashfs_inode_lookup, inode = 0x%llx\n",
68 (u64) le64_to_cpu(ino)); 68 (u64) le64_to_cpu(ino));
69 69
70 return le64_to_cpu(ino); 70 return le64_to_cpu(ino);
71 } 71 }
72 72
73 73
74 static struct dentry *squashfs_export_iget(struct super_block *sb, 74 static struct dentry *squashfs_export_iget(struct super_block *sb,
75 unsigned int ino_num) 75 unsigned int ino_num)
76 { 76 {
77 long long ino; 77 long long ino;
78 struct dentry *dentry = ERR_PTR(-ENOENT); 78 struct dentry *dentry = ERR_PTR(-ENOENT);
79 79
80 TRACE("Entered squashfs_export_iget\n"); 80 TRACE("Entered squashfs_export_iget\n");
81 81
82 ino = squashfs_inode_lookup(sb, ino_num); 82 ino = squashfs_inode_lookup(sb, ino_num);
83 if (ino >= 0) 83 if (ino >= 0)
84 dentry = d_obtain_alias(squashfs_iget(sb, ino, ino_num)); 84 dentry = d_obtain_alias(squashfs_iget(sb, ino, ino_num));
85 85
86 return dentry; 86 return dentry;
87 } 87 }
88 88
89 89
90 static struct dentry *squashfs_fh_to_dentry(struct super_block *sb, 90 static struct dentry *squashfs_fh_to_dentry(struct super_block *sb,
91 struct fid *fid, int fh_len, int fh_type) 91 struct fid *fid, int fh_len, int fh_type)
92 { 92 {
93 if ((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) 93 if ((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT)
94 || fh_len < 2) 94 || fh_len < 2)
95 return NULL; 95 return NULL;
96 96
97 return squashfs_export_iget(sb, fid->i32.ino); 97 return squashfs_export_iget(sb, fid->i32.ino);
98 } 98 }
99 99
100 100
101 static struct dentry *squashfs_fh_to_parent(struct super_block *sb, 101 static struct dentry *squashfs_fh_to_parent(struct super_block *sb,
102 struct fid *fid, int fh_len, int fh_type) 102 struct fid *fid, int fh_len, int fh_type)
103 { 103 {
104 if (fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) 104 if (fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4)
105 return NULL; 105 return NULL;
106 106
107 return squashfs_export_iget(sb, fid->i32.parent_ino); 107 return squashfs_export_iget(sb, fid->i32.parent_ino);
108 } 108 }
109 109
110 110
111 static struct dentry *squashfs_get_parent(struct dentry *child) 111 static struct dentry *squashfs_get_parent(struct dentry *child)
112 { 112 {
113 struct inode *inode = child->d_inode; 113 struct inode *inode = child->d_inode;
114 unsigned int parent_ino = squashfs_i(inode)->parent; 114 unsigned int parent_ino = squashfs_i(inode)->parent;
115 115
116 return squashfs_export_iget(inode->i_sb, parent_ino); 116 return squashfs_export_iget(inode->i_sb, parent_ino);
117 } 117 }
118 118
119 119
120 /* 120 /*
121 * Read uncompressed inode lookup table indexes off disk into memory 121 * Read uncompressed inode lookup table indexes off disk into memory
122 */ 122 */
123 __le64 *squashfs_read_inode_lookup_table(struct super_block *sb, 123 __le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
124 u64 lookup_table_start, unsigned int inodes) 124 u64 lookup_table_start, unsigned int inodes)
125 { 125 {
126 unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes); 126 unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes);
127 __le64 *inode_lookup_table;
128 int err;
129 127
130 TRACE("In read_inode_lookup_table, length %d\n", length); 128 TRACE("In read_inode_lookup_table, length %d\n", length);
131 129
132 /* Allocate inode lookup table indexes */ 130 return squashfs_read_table(sb, lookup_table_start, length);
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 } 131 }
149 132
150 133
151 const struct export_operations squashfs_export_ops = { 134 const struct export_operations squashfs_export_ops = {
152 .fh_to_dentry = squashfs_fh_to_dentry, 135 .fh_to_dentry = squashfs_fh_to_dentry,
153 .fh_to_parent = squashfs_fh_to_parent, 136 .fh_to_parent = squashfs_fh_to_parent,
154 .get_parent = squashfs_get_parent 137 .get_parent = squashfs_get_parent
155 }; 138 };
156 139
fs/squashfs/fragment.c
1 /* 1 /*
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@lougher.demon.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2, 9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version. 10 * or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 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 18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * 20 *
21 * fragment.c 21 * fragment.c
22 */ 22 */
23 23
24 /* 24 /*
25 * This file implements code to handle compressed fragments (tail-end packed 25 * This file implements code to handle compressed fragments (tail-end packed
26 * datablocks). 26 * datablocks).
27 * 27 *
28 * Regular files contain a fragment index which is mapped to a fragment 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. 29 * location on disk and compressed size using a fragment lookup table.
30 * Like everything in Squashfs this fragment lookup table is itself stored 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 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 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. 33 * is small) is read at mount time and cached in memory.
34 */ 34 */
35 35
36 #include <linux/fs.h> 36 #include <linux/fs.h>
37 #include <linux/vfs.h> 37 #include <linux/vfs.h>
38 #include <linux/slab.h> 38 #include <linux/slab.h>
39 39
40 #include "squashfs_fs.h" 40 #include "squashfs_fs.h"
41 #include "squashfs_fs_sb.h" 41 #include "squashfs_fs_sb.h"
42 #include "squashfs.h" 42 #include "squashfs.h"
43 43
44 /* 44 /*
45 * Look-up fragment using the fragment index table. Return the on disk 45 * Look-up fragment using the fragment index table. Return the on disk
46 * location of the fragment and its compressed size 46 * location of the fragment and its compressed size
47 */ 47 */
48 int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment, 48 int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment,
49 u64 *fragment_block) 49 u64 *fragment_block)
50 { 50 {
51 struct squashfs_sb_info *msblk = sb->s_fs_info; 51 struct squashfs_sb_info *msblk = sb->s_fs_info;
52 int block = SQUASHFS_FRAGMENT_INDEX(fragment); 52 int block = SQUASHFS_FRAGMENT_INDEX(fragment);
53 int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); 53 int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
54 u64 start_block = le64_to_cpu(msblk->fragment_index[block]); 54 u64 start_block = le64_to_cpu(msblk->fragment_index[block]);
55 struct squashfs_fragment_entry fragment_entry; 55 struct squashfs_fragment_entry fragment_entry;
56 int size; 56 int size;
57 57
58 size = squashfs_read_metadata(sb, &fragment_entry, &start_block, 58 size = squashfs_read_metadata(sb, &fragment_entry, &start_block,
59 &offset, sizeof(fragment_entry)); 59 &offset, sizeof(fragment_entry));
60 if (size < 0) 60 if (size < 0)
61 return size; 61 return size;
62 62
63 *fragment_block = le64_to_cpu(fragment_entry.start_block); 63 *fragment_block = le64_to_cpu(fragment_entry.start_block);
64 size = le32_to_cpu(fragment_entry.size); 64 size = le32_to_cpu(fragment_entry.size);
65 65
66 return size; 66 return size;
67 } 67 }
68 68
69 69
70 /* 70 /*
71 * Read the uncompressed fragment lookup table indexes off disk into memory 71 * Read the uncompressed fragment lookup table indexes off disk into memory
72 */ 72 */
73 __le64 *squashfs_read_fragment_index_table(struct super_block *sb, 73 __le64 *squashfs_read_fragment_index_table(struct super_block *sb,
74 u64 fragment_table_start, unsigned int fragments) 74 u64 fragment_table_start, unsigned int fragments)
75 { 75 {
76 unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(fragments); 76 unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(fragments);
77 __le64 *fragment_index;
78 int err;
79 77
80 /* Allocate fragment lookup table indexes */ 78 return squashfs_read_table(sb, fragment_table_start, length);
81 fragment_index = kmalloc(length, GFP_KERNEL);
82 if (fragment_index == NULL) {
83 ERROR("Failed to allocate fragment index table\n");
84 return ERR_PTR(-ENOMEM);
85 }
86
87 err = squashfs_read_table(sb, fragment_index, fragment_table_start,
88 length);
89 if (err < 0) {
90 ERROR("unable to read fragment index table\n");
91 kfree(fragment_index);
92 return ERR_PTR(err);
93 }
94
95 return fragment_index;
96 } 79 }
97 80
1 /* 1 /*
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@lougher.demon.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2, 9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version. 10 * or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 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 18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * 20 *
21 * id.c 21 * id.c
22 */ 22 */
23 23
24 /* 24 /*
25 * This file implements code to handle uids and gids. 25 * This file implements code to handle uids and gids.
26 * 26 *
27 * For space efficiency regular files store uid and gid indexes, which are 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 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 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 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. 31 * is small) is read at mount time and cached in memory.
32 */ 32 */
33 33
34 #include <linux/fs.h> 34 #include <linux/fs.h>
35 #include <linux/vfs.h> 35 #include <linux/vfs.h>
36 #include <linux/slab.h> 36 #include <linux/slab.h>
37 37
38 #include "squashfs_fs.h" 38 #include "squashfs_fs.h"
39 #include "squashfs_fs_sb.h" 39 #include "squashfs_fs_sb.h"
40 #include "squashfs.h" 40 #include "squashfs.h"
41 41
42 /* 42 /*
43 * Map uid/gid index into real 32-bit uid/gid using the id look up table 43 * Map uid/gid index into real 32-bit uid/gid using the id look up table
44 */ 44 */
45 int squashfs_get_id(struct super_block *sb, unsigned int index, 45 int squashfs_get_id(struct super_block *sb, unsigned int index,
46 unsigned int *id) 46 unsigned int *id)
47 { 47 {
48 struct squashfs_sb_info *msblk = sb->s_fs_info; 48 struct squashfs_sb_info *msblk = sb->s_fs_info;
49 int block = SQUASHFS_ID_BLOCK(index); 49 int block = SQUASHFS_ID_BLOCK(index);
50 int offset = SQUASHFS_ID_BLOCK_OFFSET(index); 50 int offset = SQUASHFS_ID_BLOCK_OFFSET(index);
51 u64 start_block = le64_to_cpu(msblk->id_table[block]); 51 u64 start_block = le64_to_cpu(msblk->id_table[block]);
52 __le32 disk_id; 52 __le32 disk_id;
53 int err; 53 int err;
54 54
55 err = squashfs_read_metadata(sb, &disk_id, &start_block, &offset, 55 err = squashfs_read_metadata(sb, &disk_id, &start_block, &offset,
56 sizeof(disk_id)); 56 sizeof(disk_id));
57 if (err < 0) 57 if (err < 0)
58 return err; 58 return err;
59 59
60 *id = le32_to_cpu(disk_id); 60 *id = le32_to_cpu(disk_id);
61 return 0; 61 return 0;
62 } 62 }
63 63
64 64
65 /* 65 /*
66 * Read uncompressed id lookup table indexes from disk into memory 66 * Read uncompressed id lookup table indexes from disk into memory
67 */ 67 */
68 __le64 *squashfs_read_id_index_table(struct super_block *sb, 68 __le64 *squashfs_read_id_index_table(struct super_block *sb,
69 u64 id_table_start, unsigned short no_ids) 69 u64 id_table_start, unsigned short no_ids)
70 { 70 {
71 unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids); 71 unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids);
72 __le64 *id_table;
73 int err;
74 72
75 TRACE("In read_id_index_table, length %d\n", length); 73 TRACE("In read_id_index_table, length %d\n", length);
76 74
77 /* Allocate id lookup table indexes */ 75 return squashfs_read_table(sb, id_table_start, length);
78 id_table = kmalloc(length, GFP_KERNEL);
79 if (id_table == NULL) {
80 ERROR("Failed to allocate id index table\n");
81 return ERR_PTR(-ENOMEM);
82 }
83
84 err = squashfs_read_table(sb, id_table, id_table_start, length);
85 if (err < 0) {
86 ERROR("unable to read id index table\n");
87 kfree(id_table);
88 return ERR_PTR(err);
89 }
90
91 return id_table;
92 } 76 }
93 77
fs/squashfs/squashfs.h
1 /* 1 /*
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@lougher.demon.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2, 9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version. 10 * or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 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 18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * 20 *
21 * squashfs.h 21 * squashfs.h
22 */ 22 */
23 23
24 #define TRACE(s, args...) pr_debug("SQUASHFS: "s, ## args) 24 #define TRACE(s, args...) pr_debug("SQUASHFS: "s, ## args)
25 25
26 #define ERROR(s, args...) pr_err("SQUASHFS error: "s, ## args) 26 #define ERROR(s, args...) pr_err("SQUASHFS error: "s, ## args)
27 27
28 #define WARNING(s, args...) pr_warning("SQUASHFS: "s, ## args) 28 #define WARNING(s, args...) pr_warning("SQUASHFS: "s, ## args)
29 29
30 /* block.c */ 30 /* block.c */
31 extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *, 31 extern int squashfs_read_data(struct super_block *, void **, u64, int, u64 *,
32 int, int); 32 int, int);
33 33
34 /* cache.c */ 34 /* cache.c */
35 extern struct squashfs_cache *squashfs_cache_init(char *, int, int); 35 extern struct squashfs_cache *squashfs_cache_init(char *, int, int);
36 extern void squashfs_cache_delete(struct squashfs_cache *); 36 extern void squashfs_cache_delete(struct squashfs_cache *);
37 extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *, 37 extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *,
38 struct squashfs_cache *, u64, int); 38 struct squashfs_cache *, u64, int);
39 extern void squashfs_cache_put(struct squashfs_cache_entry *); 39 extern void squashfs_cache_put(struct squashfs_cache_entry *);
40 extern int squashfs_copy_data(void *, struct squashfs_cache_entry *, int, int); 40 extern int squashfs_copy_data(void *, struct squashfs_cache_entry *, int, int);
41 extern int squashfs_read_metadata(struct super_block *, void *, u64 *, 41 extern int squashfs_read_metadata(struct super_block *, void *, u64 *,
42 int *, int); 42 int *, int);
43 extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *, 43 extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *,
44 u64, int); 44 u64, int);
45 extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *, 45 extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *,
46 u64, int); 46 u64, int);
47 extern int squashfs_read_table(struct super_block *, void *, u64, int); 47 extern void *squashfs_read_table(struct super_block *, u64, int);
48 48
49 /* decompressor.c */ 49 /* decompressor.c */
50 extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); 50 extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
51 extern void *squashfs_decompressor_init(struct super_block *, unsigned short); 51 extern void *squashfs_decompressor_init(struct super_block *, unsigned short);
52 52
53 /* export.c */ 53 /* export.c */
54 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, 54 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
55 unsigned int); 55 unsigned int);
56 56
57 /* fragment.c */ 57 /* fragment.c */
58 extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *); 58 extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *);
59 extern __le64 *squashfs_read_fragment_index_table(struct super_block *, 59 extern __le64 *squashfs_read_fragment_index_table(struct super_block *,
60 u64, unsigned int); 60 u64, unsigned int);
61 61
62 /* id.c */ 62 /* id.c */
63 extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *); 63 extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
64 extern __le64 *squashfs_read_id_index_table(struct super_block *, u64, 64 extern __le64 *squashfs_read_id_index_table(struct super_block *, u64,
65 unsigned short); 65 unsigned short);
66 66
67 /* inode.c */ 67 /* inode.c */
68 extern struct inode *squashfs_iget(struct super_block *, long long, 68 extern struct inode *squashfs_iget(struct super_block *, long long,
69 unsigned int); 69 unsigned int);
70 extern int squashfs_read_inode(struct inode *, long long); 70 extern int squashfs_read_inode(struct inode *, long long);
71 71
72 /* xattr.c */ 72 /* xattr.c */
73 extern ssize_t squashfs_listxattr(struct dentry *, char *, size_t); 73 extern ssize_t squashfs_listxattr(struct dentry *, char *, size_t);
74 74
75 /* 75 /*
76 * Inodes, files, decompressor and xattr operations 76 * Inodes, files, decompressor and xattr operations
77 */ 77 */
78 78
79 /* dir.c */ 79 /* dir.c */
80 extern const struct file_operations squashfs_dir_ops; 80 extern const struct file_operations squashfs_dir_ops;
81 81
82 /* export.c */ 82 /* export.c */
83 extern const struct export_operations squashfs_export_ops; 83 extern const struct export_operations squashfs_export_ops;
84 84
85 /* file.c */ 85 /* file.c */
86 extern const struct address_space_operations squashfs_aops; 86 extern const struct address_space_operations squashfs_aops;
87 87
88 /* inode.c */ 88 /* inode.c */
89 extern const struct inode_operations squashfs_inode_ops; 89 extern const struct inode_operations squashfs_inode_ops;
90 90
91 /* namei.c */ 91 /* namei.c */
92 extern const struct inode_operations squashfs_dir_inode_ops; 92 extern const struct inode_operations squashfs_dir_inode_ops;
93 93
94 /* symlink.c */ 94 /* symlink.c */
95 extern const struct address_space_operations squashfs_symlink_aops; 95 extern const struct address_space_operations squashfs_symlink_aops;
96 extern const struct inode_operations squashfs_symlink_inode_ops; 96 extern const struct inode_operations squashfs_symlink_inode_ops;
97 97
98 /* xattr.c */ 98 /* xattr.c */
99 extern const struct xattr_handler *squashfs_xattr_handlers[]; 99 extern const struct xattr_handler *squashfs_xattr_handlers[];
100 100
101 /* zlib_wrapper.c */ 101 /* zlib_wrapper.c */
102 extern const struct squashfs_decompressor squashfs_zlib_comp_ops; 102 extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
103 103
1 /* 1 /*
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@lougher.demon.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2, 9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version. 10 * or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 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 18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * 20 *
21 * super.c 21 * super.c
22 */ 22 */
23 23
24 /* 24 /*
25 * This file implements code to read the superblock, read and initialise 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 26 * in-memory structures at mount time, and all the VFS glue code to register
27 * the filesystem. 27 * the filesystem.
28 */ 28 */
29 29
30 #include <linux/fs.h> 30 #include <linux/fs.h>
31 #include <linux/vfs.h> 31 #include <linux/vfs.h>
32 #include <linux/slab.h> 32 #include <linux/slab.h>
33 #include <linux/mutex.h> 33 #include <linux/mutex.h>
34 #include <linux/pagemap.h> 34 #include <linux/pagemap.h>
35 #include <linux/init.h> 35 #include <linux/init.h>
36 #include <linux/module.h> 36 #include <linux/module.h>
37 #include <linux/magic.h> 37 #include <linux/magic.h>
38 #include <linux/xattr.h> 38 #include <linux/xattr.h>
39 39
40 #include "squashfs_fs.h" 40 #include "squashfs_fs.h"
41 #include "squashfs_fs_sb.h" 41 #include "squashfs_fs_sb.h"
42 #include "squashfs_fs_i.h" 42 #include "squashfs_fs_i.h"
43 #include "squashfs.h" 43 #include "squashfs.h"
44 #include "decompressor.h" 44 #include "decompressor.h"
45 #include "xattr.h" 45 #include "xattr.h"
46 46
47 static struct file_system_type squashfs_fs_type; 47 static struct file_system_type squashfs_fs_type;
48 static const struct super_operations squashfs_super_ops; 48 static const struct super_operations squashfs_super_ops;
49 49
50 static const struct squashfs_decompressor *supported_squashfs_filesystem(short 50 static const struct squashfs_decompressor *supported_squashfs_filesystem(short
51 major, short minor, short id) 51 major, short minor, short id)
52 { 52 {
53 const struct squashfs_decompressor *decompressor; 53 const struct squashfs_decompressor *decompressor;
54 54
55 if (major < SQUASHFS_MAJOR) { 55 if (major < SQUASHFS_MAJOR) {
56 ERROR("Major/Minor mismatch, older Squashfs %d.%d " 56 ERROR("Major/Minor mismatch, older Squashfs %d.%d "
57 "filesystems are unsupported\n", major, minor); 57 "filesystems are unsupported\n", major, minor);
58 return NULL; 58 return NULL;
59 } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { 59 } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
60 ERROR("Major/Minor mismatch, trying to mount newer " 60 ERROR("Major/Minor mismatch, trying to mount newer "
61 "%d.%d filesystem\n", major, minor); 61 "%d.%d filesystem\n", major, minor);
62 ERROR("Please update your kernel\n"); 62 ERROR("Please update your kernel\n");
63 return NULL; 63 return NULL;
64 } 64 }
65 65
66 decompressor = squashfs_lookup_decompressor(id); 66 decompressor = squashfs_lookup_decompressor(id);
67 if (!decompressor->supported) { 67 if (!decompressor->supported) {
68 ERROR("Filesystem uses \"%s\" compression. This is not " 68 ERROR("Filesystem uses \"%s\" compression. This is not "
69 "supported\n", decompressor->name); 69 "supported\n", decompressor->name);
70 return NULL; 70 return NULL;
71 } 71 }
72 72
73 return decompressor; 73 return decompressor;
74 } 74 }
75 75
76 76
77 static int squashfs_fill_super(struct super_block *sb, void *data, int silent) 77 static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
78 { 78 {
79 struct squashfs_sb_info *msblk; 79 struct squashfs_sb_info *msblk;
80 struct squashfs_super_block *sblk = NULL; 80 struct squashfs_super_block *sblk = NULL;
81 char b[BDEVNAME_SIZE]; 81 char b[BDEVNAME_SIZE];
82 struct inode *root; 82 struct inode *root;
83 long long root_inode; 83 long long root_inode;
84 unsigned short flags; 84 unsigned short flags;
85 unsigned int fragments; 85 unsigned int fragments;
86 u64 lookup_table_start, xattr_id_table_start; 86 u64 lookup_table_start, xattr_id_table_start;
87 int err; 87 int err;
88 88
89 TRACE("Entered squashfs_fill_superblock\n"); 89 TRACE("Entered squashfs_fill_superblock\n");
90 90
91 sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL); 91 sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL);
92 if (sb->s_fs_info == NULL) { 92 if (sb->s_fs_info == NULL) {
93 ERROR("Failed to allocate squashfs_sb_info\n"); 93 ERROR("Failed to allocate squashfs_sb_info\n");
94 return -ENOMEM; 94 return -ENOMEM;
95 } 95 }
96 msblk = sb->s_fs_info; 96 msblk = sb->s_fs_info;
97 97
98 sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
99 if (sblk == NULL) {
100 ERROR("Failed to allocate squashfs_super_block\n");
101 goto failure;
102 }
103
104 msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE); 98 msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE);
105 msblk->devblksize_log2 = ffz(~msblk->devblksize); 99 msblk->devblksize_log2 = ffz(~msblk->devblksize);
106 100
107 mutex_init(&msblk->read_data_mutex); 101 mutex_init(&msblk->read_data_mutex);
108 mutex_init(&msblk->meta_index_mutex); 102 mutex_init(&msblk->meta_index_mutex);
109 103
110 /* 104 /*
111 * msblk->bytes_used is checked in squashfs_read_table to ensure reads 105 * msblk->bytes_used is checked in squashfs_read_table to ensure reads
112 * are not beyond filesystem end. But as we're using 106 * are not beyond filesystem end. But as we're using
113 * squashfs_read_table here to read the superblock (including the value 107 * squashfs_read_table here to read the superblock (including the value
114 * of bytes_used) we need to set it to an initial sensible dummy value 108 * of bytes_used) we need to set it to an initial sensible dummy value
115 */ 109 */
116 msblk->bytes_used = sizeof(*sblk); 110 msblk->bytes_used = sizeof(*sblk);
117 err = squashfs_read_table(sb, sblk, SQUASHFS_START, sizeof(*sblk)); 111 sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk));
118 112
119 if (err < 0) { 113 if (IS_ERR(sblk)) {
120 ERROR("unable to read squashfs_super_block\n"); 114 ERROR("unable to read squashfs_super_block\n");
115 err = PTR_ERR(sblk);
116 sblk = NULL;
121 goto failed_mount; 117 goto failed_mount;
122 } 118 }
123 119
124 err = -EINVAL; 120 err = -EINVAL;
125 121
126 /* Check it is a SQUASHFS superblock */ 122 /* Check it is a SQUASHFS superblock */
127 sb->s_magic = le32_to_cpu(sblk->s_magic); 123 sb->s_magic = le32_to_cpu(sblk->s_magic);
128 if (sb->s_magic != SQUASHFS_MAGIC) { 124 if (sb->s_magic != SQUASHFS_MAGIC) {
129 if (!silent) 125 if (!silent)
130 ERROR("Can't find a SQUASHFS superblock on %s\n", 126 ERROR("Can't find a SQUASHFS superblock on %s\n",
131 bdevname(sb->s_bdev, b)); 127 bdevname(sb->s_bdev, b));
132 goto failed_mount; 128 goto failed_mount;
133 } 129 }
134 130
135 /* Check the MAJOR & MINOR versions and lookup compression type */ 131 /* Check the MAJOR & MINOR versions and lookup compression type */
136 msblk->decompressor = supported_squashfs_filesystem( 132 msblk->decompressor = supported_squashfs_filesystem(
137 le16_to_cpu(sblk->s_major), 133 le16_to_cpu(sblk->s_major),
138 le16_to_cpu(sblk->s_minor), 134 le16_to_cpu(sblk->s_minor),
139 le16_to_cpu(sblk->compression)); 135 le16_to_cpu(sblk->compression));
140 if (msblk->decompressor == NULL) 136 if (msblk->decompressor == NULL)
141 goto failed_mount; 137 goto failed_mount;
142 138
143 /* Check the filesystem does not extend beyond the end of the 139 /* Check the filesystem does not extend beyond the end of the
144 block device */ 140 block device */
145 msblk->bytes_used = le64_to_cpu(sblk->bytes_used); 141 msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
146 if (msblk->bytes_used < 0 || msblk->bytes_used > 142 if (msblk->bytes_used < 0 || msblk->bytes_used >
147 i_size_read(sb->s_bdev->bd_inode)) 143 i_size_read(sb->s_bdev->bd_inode))
148 goto failed_mount; 144 goto failed_mount;
149 145
150 /* Check block size for sanity */ 146 /* Check block size for sanity */
151 msblk->block_size = le32_to_cpu(sblk->block_size); 147 msblk->block_size = le32_to_cpu(sblk->block_size);
152 if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE) 148 if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
153 goto failed_mount; 149 goto failed_mount;
154 150
155 /* 151 /*
156 * Check the system page size is not larger than the filesystem 152 * Check the system page size is not larger than the filesystem
157 * block size (by default 128K). This is currently not supported. 153 * block size (by default 128K). This is currently not supported.
158 */ 154 */
159 if (PAGE_CACHE_SIZE > msblk->block_size) { 155 if (PAGE_CACHE_SIZE > msblk->block_size) {
160 ERROR("Page size > filesystem block size (%d). This is " 156 ERROR("Page size > filesystem block size (%d). This is "
161 "currently not supported!\n", msblk->block_size); 157 "currently not supported!\n", msblk->block_size);
162 goto failed_mount; 158 goto failed_mount;
163 } 159 }
164 160
165 msblk->block_log = le16_to_cpu(sblk->block_log); 161 msblk->block_log = le16_to_cpu(sblk->block_log);
166 if (msblk->block_log > SQUASHFS_FILE_MAX_LOG) 162 if (msblk->block_log > SQUASHFS_FILE_MAX_LOG)
167 goto failed_mount; 163 goto failed_mount;
168 164
169 /* Check the root inode for sanity */ 165 /* Check the root inode for sanity */
170 root_inode = le64_to_cpu(sblk->root_inode); 166 root_inode = le64_to_cpu(sblk->root_inode);
171 if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE) 167 if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
172 goto failed_mount; 168 goto failed_mount;
173 169
174 msblk->inode_table = le64_to_cpu(sblk->inode_table_start); 170 msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
175 msblk->directory_table = le64_to_cpu(sblk->directory_table_start); 171 msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
176 msblk->inodes = le32_to_cpu(sblk->inodes); 172 msblk->inodes = le32_to_cpu(sblk->inodes);
177 flags = le16_to_cpu(sblk->flags); 173 flags = le16_to_cpu(sblk->flags);
178 174
179 TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b)); 175 TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b));
180 TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(flags) 176 TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(flags)
181 ? "un" : ""); 177 ? "un" : "");
182 TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(flags) 178 TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(flags)
183 ? "un" : ""); 179 ? "un" : "");
184 TRACE("Filesystem size %lld bytes\n", msblk->bytes_used); 180 TRACE("Filesystem size %lld bytes\n", msblk->bytes_used);
185 TRACE("Block size %d\n", msblk->block_size); 181 TRACE("Block size %d\n", msblk->block_size);
186 TRACE("Number of inodes %d\n", msblk->inodes); 182 TRACE("Number of inodes %d\n", msblk->inodes);
187 TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments)); 183 TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments));
188 TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids)); 184 TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids));
189 TRACE("sblk->inode_table_start %llx\n", msblk->inode_table); 185 TRACE("sblk->inode_table_start %llx\n", msblk->inode_table);
190 TRACE("sblk->directory_table_start %llx\n", msblk->directory_table); 186 TRACE("sblk->directory_table_start %llx\n", msblk->directory_table);
191 TRACE("sblk->fragment_table_start %llx\n", 187 TRACE("sblk->fragment_table_start %llx\n",
192 (u64) le64_to_cpu(sblk->fragment_table_start)); 188 (u64) le64_to_cpu(sblk->fragment_table_start));
193 TRACE("sblk->id_table_start %llx\n", 189 TRACE("sblk->id_table_start %llx\n",
194 (u64) le64_to_cpu(sblk->id_table_start)); 190 (u64) le64_to_cpu(sblk->id_table_start));
195 191
196 sb->s_maxbytes = MAX_LFS_FILESIZE; 192 sb->s_maxbytes = MAX_LFS_FILESIZE;
197 sb->s_flags |= MS_RDONLY; 193 sb->s_flags |= MS_RDONLY;
198 sb->s_op = &squashfs_super_ops; 194 sb->s_op = &squashfs_super_ops;
199 195
200 err = -ENOMEM; 196 err = -ENOMEM;
201 197
202 msblk->block_cache = squashfs_cache_init("metadata", 198 msblk->block_cache = squashfs_cache_init("metadata",
203 SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); 199 SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
204 if (msblk->block_cache == NULL) 200 if (msblk->block_cache == NULL)
205 goto failed_mount; 201 goto failed_mount;
206 202
207 /* Allocate read_page block */ 203 /* Allocate read_page block */
208 msblk->read_page = squashfs_cache_init("data", 1, msblk->block_size); 204 msblk->read_page = squashfs_cache_init("data", 1, msblk->block_size);
209 if (msblk->read_page == NULL) { 205 if (msblk->read_page == NULL) {
210 ERROR("Failed to allocate read_page block\n"); 206 ERROR("Failed to allocate read_page block\n");
211 goto failed_mount; 207 goto failed_mount;
212 } 208 }
213 209
214 msblk->stream = squashfs_decompressor_init(sb, flags); 210 msblk->stream = squashfs_decompressor_init(sb, flags);
215 if (IS_ERR(msblk->stream)) { 211 if (IS_ERR(msblk->stream)) {
216 err = PTR_ERR(msblk->stream); 212 err = PTR_ERR(msblk->stream);
217 msblk->stream = NULL; 213 msblk->stream = NULL;
218 goto failed_mount; 214 goto failed_mount;
219 } 215 }
220 216
221 /* Allocate and read id index table */ 217 /* Allocate and read id index table */
222 msblk->id_table = squashfs_read_id_index_table(sb, 218 msblk->id_table = squashfs_read_id_index_table(sb,
223 le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids)); 219 le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids));
224 if (IS_ERR(msblk->id_table)) { 220 if (IS_ERR(msblk->id_table)) {
221 ERROR("unable to read id index table\n");
225 err = PTR_ERR(msblk->id_table); 222 err = PTR_ERR(msblk->id_table);
226 msblk->id_table = NULL; 223 msblk->id_table = NULL;
227 goto failed_mount; 224 goto failed_mount;
228 } 225 }
229 226
230 fragments = le32_to_cpu(sblk->fragments); 227 fragments = le32_to_cpu(sblk->fragments);
231 if (fragments == 0) 228 if (fragments == 0)
232 goto allocate_lookup_table; 229 goto allocate_lookup_table;
233 230
234 msblk->fragment_cache = squashfs_cache_init("fragment", 231 msblk->fragment_cache = squashfs_cache_init("fragment",
235 SQUASHFS_CACHED_FRAGMENTS, msblk->block_size); 232 SQUASHFS_CACHED_FRAGMENTS, msblk->block_size);
236 if (msblk->fragment_cache == NULL) { 233 if (msblk->fragment_cache == NULL) {
237 err = -ENOMEM; 234 err = -ENOMEM;
238 goto failed_mount; 235 goto failed_mount;
239 } 236 }
240 237
241 /* Allocate and read fragment index table */ 238 /* Allocate and read fragment index table */
242 msblk->fragment_index = squashfs_read_fragment_index_table(sb, 239 msblk->fragment_index = squashfs_read_fragment_index_table(sb,
243 le64_to_cpu(sblk->fragment_table_start), fragments); 240 le64_to_cpu(sblk->fragment_table_start), fragments);
244 if (IS_ERR(msblk->fragment_index)) { 241 if (IS_ERR(msblk->fragment_index)) {
242 ERROR("unable to read fragment index table\n");
245 err = PTR_ERR(msblk->fragment_index); 243 err = PTR_ERR(msblk->fragment_index);
246 msblk->fragment_index = NULL; 244 msblk->fragment_index = NULL;
247 goto failed_mount; 245 goto failed_mount;
248 } 246 }
249 247
250 allocate_lookup_table: 248 allocate_lookup_table:
251 lookup_table_start = le64_to_cpu(sblk->lookup_table_start); 249 lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
252 if (lookup_table_start == SQUASHFS_INVALID_BLK) 250 if (lookup_table_start == SQUASHFS_INVALID_BLK)
253 goto allocate_xattr_table; 251 goto allocate_xattr_table;
254 252
255 /* Allocate and read inode lookup table */ 253 /* Allocate and read inode lookup table */
256 msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb, 254 msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
257 lookup_table_start, msblk->inodes); 255 lookup_table_start, msblk->inodes);
258 if (IS_ERR(msblk->inode_lookup_table)) { 256 if (IS_ERR(msblk->inode_lookup_table)) {
257 ERROR("unable to read inode lookup table\n");
259 err = PTR_ERR(msblk->inode_lookup_table); 258 err = PTR_ERR(msblk->inode_lookup_table);
260 msblk->inode_lookup_table = NULL; 259 msblk->inode_lookup_table = NULL;
261 goto failed_mount; 260 goto failed_mount;
262 } 261 }
263 262
264 sb->s_export_op = &squashfs_export_ops; 263 sb->s_export_op = &squashfs_export_ops;
265 264
266 allocate_xattr_table: 265 allocate_xattr_table:
267 sb->s_xattr = squashfs_xattr_handlers; 266 sb->s_xattr = squashfs_xattr_handlers;
268 xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start); 267 xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start);
269 if (xattr_id_table_start == SQUASHFS_INVALID_BLK) 268 if (xattr_id_table_start == SQUASHFS_INVALID_BLK)
270 goto allocate_root; 269 goto allocate_root;
271 270
272 /* Allocate and read xattr id lookup table */ 271 /* Allocate and read xattr id lookup table */
273 msblk->xattr_id_table = squashfs_read_xattr_id_table(sb, 272 msblk->xattr_id_table = squashfs_read_xattr_id_table(sb,
274 xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids); 273 xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids);
275 if (IS_ERR(msblk->xattr_id_table)) { 274 if (IS_ERR(msblk->xattr_id_table)) {
275 ERROR("unable to read xattr id index table\n");
276 err = PTR_ERR(msblk->xattr_id_table); 276 err = PTR_ERR(msblk->xattr_id_table);
277 msblk->xattr_id_table = NULL; 277 msblk->xattr_id_table = NULL;
278 if (err != -ENOTSUPP) 278 if (err != -ENOTSUPP)
279 goto failed_mount; 279 goto failed_mount;
280 } 280 }
281 allocate_root: 281 allocate_root:
282 root = new_inode(sb); 282 root = new_inode(sb);
283 if (!root) { 283 if (!root) {
284 err = -ENOMEM; 284 err = -ENOMEM;
285 goto failed_mount; 285 goto failed_mount;
286 } 286 }
287 287
288 err = squashfs_read_inode(root, root_inode); 288 err = squashfs_read_inode(root, root_inode);
289 if (err) { 289 if (err) {
290 make_bad_inode(root); 290 make_bad_inode(root);
291 iput(root); 291 iput(root);
292 goto failed_mount; 292 goto failed_mount;
293 } 293 }
294 insert_inode_hash(root); 294 insert_inode_hash(root);
295 295
296 sb->s_root = d_alloc_root(root); 296 sb->s_root = d_alloc_root(root);
297 if (sb->s_root == NULL) { 297 if (sb->s_root == NULL) {
298 ERROR("Root inode create failed\n"); 298 ERROR("Root inode create failed\n");
299 err = -ENOMEM; 299 err = -ENOMEM;
300 iput(root); 300 iput(root);
301 goto failed_mount; 301 goto failed_mount;
302 } 302 }
303 303
304 TRACE("Leaving squashfs_fill_super\n"); 304 TRACE("Leaving squashfs_fill_super\n");
305 kfree(sblk); 305 kfree(sblk);
306 return 0; 306 return 0;
307 307
308 failed_mount: 308 failed_mount:
309 squashfs_cache_delete(msblk->block_cache); 309 squashfs_cache_delete(msblk->block_cache);
310 squashfs_cache_delete(msblk->fragment_cache); 310 squashfs_cache_delete(msblk->fragment_cache);
311 squashfs_cache_delete(msblk->read_page); 311 squashfs_cache_delete(msblk->read_page);
312 squashfs_decompressor_free(msblk, msblk->stream); 312 squashfs_decompressor_free(msblk, msblk->stream);
313 kfree(msblk->inode_lookup_table); 313 kfree(msblk->inode_lookup_table);
314 kfree(msblk->fragment_index); 314 kfree(msblk->fragment_index);
315 kfree(msblk->id_table); 315 kfree(msblk->id_table);
316 kfree(msblk->xattr_id_table); 316 kfree(msblk->xattr_id_table);
317 kfree(sb->s_fs_info); 317 kfree(sb->s_fs_info);
318 sb->s_fs_info = NULL; 318 sb->s_fs_info = NULL;
319 kfree(sblk); 319 kfree(sblk);
320 return err; 320 return err;
321
322 failure:
323 kfree(sb->s_fs_info);
324 sb->s_fs_info = NULL;
325 return -ENOMEM;
326 } 321 }
327 322
328 323
329 static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) 324 static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
330 { 325 {
331 struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; 326 struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
332 u64 id = huge_encode_dev(dentry->d_sb->s_bdev->bd_dev); 327 u64 id = huge_encode_dev(dentry->d_sb->s_bdev->bd_dev);
333 328
334 TRACE("Entered squashfs_statfs\n"); 329 TRACE("Entered squashfs_statfs\n");
335 330
336 buf->f_type = SQUASHFS_MAGIC; 331 buf->f_type = SQUASHFS_MAGIC;
337 buf->f_bsize = msblk->block_size; 332 buf->f_bsize = msblk->block_size;
338 buf->f_blocks = ((msblk->bytes_used - 1) >> msblk->block_log) + 1; 333 buf->f_blocks = ((msblk->bytes_used - 1) >> msblk->block_log) + 1;
339 buf->f_bfree = buf->f_bavail = 0; 334 buf->f_bfree = buf->f_bavail = 0;
340 buf->f_files = msblk->inodes; 335 buf->f_files = msblk->inodes;
341 buf->f_ffree = 0; 336 buf->f_ffree = 0;
342 buf->f_namelen = SQUASHFS_NAME_LEN; 337 buf->f_namelen = SQUASHFS_NAME_LEN;
343 buf->f_fsid.val[0] = (u32)id; 338 buf->f_fsid.val[0] = (u32)id;
344 buf->f_fsid.val[1] = (u32)(id >> 32); 339 buf->f_fsid.val[1] = (u32)(id >> 32);
345 340
346 return 0; 341 return 0;
347 } 342 }
348 343
349 344
350 static int squashfs_remount(struct super_block *sb, int *flags, char *data) 345 static int squashfs_remount(struct super_block *sb, int *flags, char *data)
351 { 346 {
352 *flags |= MS_RDONLY; 347 *flags |= MS_RDONLY;
353 return 0; 348 return 0;
354 } 349 }
355 350
356 351
357 static void squashfs_put_super(struct super_block *sb) 352 static void squashfs_put_super(struct super_block *sb)
358 { 353 {
359 if (sb->s_fs_info) { 354 if (sb->s_fs_info) {
360 struct squashfs_sb_info *sbi = sb->s_fs_info; 355 struct squashfs_sb_info *sbi = sb->s_fs_info;
361 squashfs_cache_delete(sbi->block_cache); 356 squashfs_cache_delete(sbi->block_cache);
362 squashfs_cache_delete(sbi->fragment_cache); 357 squashfs_cache_delete(sbi->fragment_cache);
363 squashfs_cache_delete(sbi->read_page); 358 squashfs_cache_delete(sbi->read_page);
364 squashfs_decompressor_free(sbi, sbi->stream); 359 squashfs_decompressor_free(sbi, sbi->stream);
365 kfree(sbi->id_table); 360 kfree(sbi->id_table);
366 kfree(sbi->fragment_index); 361 kfree(sbi->fragment_index);
367 kfree(sbi->meta_index); 362 kfree(sbi->meta_index);
368 kfree(sbi->inode_lookup_table); 363 kfree(sbi->inode_lookup_table);
369 kfree(sbi->xattr_id_table); 364 kfree(sbi->xattr_id_table);
370 kfree(sb->s_fs_info); 365 kfree(sb->s_fs_info);
371 sb->s_fs_info = NULL; 366 sb->s_fs_info = NULL;
372 } 367 }
373 } 368 }
374 369
375 370
376 static struct dentry *squashfs_mount(struct file_system_type *fs_type, 371 static struct dentry *squashfs_mount(struct file_system_type *fs_type,
377 int flags, const char *dev_name, void *data) 372 int flags, const char *dev_name, void *data)
378 { 373 {
379 return mount_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); 374 return mount_bdev(fs_type, flags, dev_name, data, squashfs_fill_super);
380 } 375 }
381 376
382 377
383 static struct kmem_cache *squashfs_inode_cachep; 378 static struct kmem_cache *squashfs_inode_cachep;
384 379
385 380
386 static void init_once(void *foo) 381 static void init_once(void *foo)
387 { 382 {
388 struct squashfs_inode_info *ei = foo; 383 struct squashfs_inode_info *ei = foo;
389 384
390 inode_init_once(&ei->vfs_inode); 385 inode_init_once(&ei->vfs_inode);
391 } 386 }
392 387
393 388
394 static int __init init_inodecache(void) 389 static int __init init_inodecache(void)
395 { 390 {
396 squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", 391 squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
397 sizeof(struct squashfs_inode_info), 0, 392 sizeof(struct squashfs_inode_info), 0,
398 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); 393 SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once);
399 394
400 return squashfs_inode_cachep ? 0 : -ENOMEM; 395 return squashfs_inode_cachep ? 0 : -ENOMEM;
401 } 396 }
402 397
403 398
404 static void destroy_inodecache(void) 399 static void destroy_inodecache(void)
405 { 400 {
406 kmem_cache_destroy(squashfs_inode_cachep); 401 kmem_cache_destroy(squashfs_inode_cachep);
407 } 402 }
408 403
409 404
410 static int __init init_squashfs_fs(void) 405 static int __init init_squashfs_fs(void)
411 { 406 {
412 int err = init_inodecache(); 407 int err = init_inodecache();
413 408
414 if (err) 409 if (err)
415 return err; 410 return err;
416 411
417 err = register_filesystem(&squashfs_fs_type); 412 err = register_filesystem(&squashfs_fs_type);
418 if (err) { 413 if (err) {
419 destroy_inodecache(); 414 destroy_inodecache();
420 return err; 415 return err;
421 } 416 }
422 417
423 printk(KERN_INFO "squashfs: version 4.0 (2009/01/31) " 418 printk(KERN_INFO "squashfs: version 4.0 (2009/01/31) "
424 "Phillip Lougher\n"); 419 "Phillip Lougher\n");
425 420
426 return 0; 421 return 0;
427 } 422 }
428 423
429 424
430 static void __exit exit_squashfs_fs(void) 425 static void __exit exit_squashfs_fs(void)
431 { 426 {
432 unregister_filesystem(&squashfs_fs_type); 427 unregister_filesystem(&squashfs_fs_type);
433 destroy_inodecache(); 428 destroy_inodecache();
434 } 429 }
435 430
436 431
437 static struct inode *squashfs_alloc_inode(struct super_block *sb) 432 static struct inode *squashfs_alloc_inode(struct super_block *sb)
438 { 433 {
439 struct squashfs_inode_info *ei = 434 struct squashfs_inode_info *ei =
440 kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); 435 kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
441 436
442 return ei ? &ei->vfs_inode : NULL; 437 return ei ? &ei->vfs_inode : NULL;
443 } 438 }
444 439
445 440
446 static void squashfs_i_callback(struct rcu_head *head) 441 static void squashfs_i_callback(struct rcu_head *head)
447 { 442 {
448 struct inode *inode = container_of(head, struct inode, i_rcu); 443 struct inode *inode = container_of(head, struct inode, i_rcu);
449 INIT_LIST_HEAD(&inode->i_dentry); 444 INIT_LIST_HEAD(&inode->i_dentry);
450 kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode)); 445 kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode));
451 } 446 }
452 447
453 static void squashfs_destroy_inode(struct inode *inode) 448 static void squashfs_destroy_inode(struct inode *inode)
454 { 449 {
455 call_rcu(&inode->i_rcu, squashfs_i_callback); 450 call_rcu(&inode->i_rcu, squashfs_i_callback);
456 } 451 }
457 452
458 453
459 static struct file_system_type squashfs_fs_type = { 454 static struct file_system_type squashfs_fs_type = {
460 .owner = THIS_MODULE, 455 .owner = THIS_MODULE,
461 .name = "squashfs", 456 .name = "squashfs",
462 .mount = squashfs_mount, 457 .mount = squashfs_mount,
463 .kill_sb = kill_block_super, 458 .kill_sb = kill_block_super,
464 .fs_flags = FS_REQUIRES_DEV 459 .fs_flags = FS_REQUIRES_DEV
465 }; 460 };
466 461
467 static const struct super_operations squashfs_super_ops = { 462 static const struct super_operations squashfs_super_ops = {
468 .alloc_inode = squashfs_alloc_inode, 463 .alloc_inode = squashfs_alloc_inode,
469 .destroy_inode = squashfs_destroy_inode, 464 .destroy_inode = squashfs_destroy_inode,
470 .statfs = squashfs_statfs, 465 .statfs = squashfs_statfs,
471 .put_super = squashfs_put_super, 466 .put_super = squashfs_put_super,
472 .remount_fs = squashfs_remount 467 .remount_fs = squashfs_remount
473 }; 468 };
474 469
fs/squashfs/xattr_id.c
1 /* 1 /*
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2010 4 * Copyright (c) 2010
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@lougher.demon.co.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2, 9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version. 10 * or (at your option) any later version.
11 * 11 *
12 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU General Public License 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 18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * 20 *
21 * xattr_id.c 21 * xattr_id.c
22 */ 22 */
23 23
24 /* 24 /*
25 * This file implements code to map the 32-bit xattr id stored in the inode 25 * This file implements code to map the 32-bit xattr id stored in the inode
26 * into the on disk location of the xattr data. 26 * into the on disk location of the xattr data.
27 */ 27 */
28 28
29 #include <linux/fs.h> 29 #include <linux/fs.h>
30 #include <linux/vfs.h> 30 #include <linux/vfs.h>
31 #include <linux/slab.h> 31 #include <linux/slab.h>
32 32
33 #include "squashfs_fs.h" 33 #include "squashfs_fs.h"
34 #include "squashfs_fs_sb.h" 34 #include "squashfs_fs_sb.h"
35 #include "squashfs.h" 35 #include "squashfs.h"
36 #include "xattr.h" 36 #include "xattr.h"
37 37
38 /* 38 /*
39 * Map xattr id using the xattr id look up table 39 * Map xattr id using the xattr id look up table
40 */ 40 */
41 int squashfs_xattr_lookup(struct super_block *sb, unsigned int index, 41 int squashfs_xattr_lookup(struct super_block *sb, unsigned int index,
42 int *count, unsigned int *size, unsigned long long *xattr) 42 int *count, unsigned int *size, unsigned long long *xattr)
43 { 43 {
44 struct squashfs_sb_info *msblk = sb->s_fs_info; 44 struct squashfs_sb_info *msblk = sb->s_fs_info;
45 int block = SQUASHFS_XATTR_BLOCK(index); 45 int block = SQUASHFS_XATTR_BLOCK(index);
46 int offset = SQUASHFS_XATTR_BLOCK_OFFSET(index); 46 int offset = SQUASHFS_XATTR_BLOCK_OFFSET(index);
47 u64 start_block = le64_to_cpu(msblk->xattr_id_table[block]); 47 u64 start_block = le64_to_cpu(msblk->xattr_id_table[block]);
48 struct squashfs_xattr_id id; 48 struct squashfs_xattr_id id;
49 int err; 49 int err;
50 50
51 err = squashfs_read_metadata(sb, &id, &start_block, &offset, 51 err = squashfs_read_metadata(sb, &id, &start_block, &offset,
52 sizeof(id)); 52 sizeof(id));
53 if (err < 0) 53 if (err < 0)
54 return err; 54 return err;
55 55
56 *xattr = le64_to_cpu(id.xattr); 56 *xattr = le64_to_cpu(id.xattr);
57 *size = le32_to_cpu(id.size); 57 *size = le32_to_cpu(id.size);
58 *count = le32_to_cpu(id.count); 58 *count = le32_to_cpu(id.count);
59 return 0; 59 return 0;
60 } 60 }
61 61
62 62
63 /* 63 /*
64 * Read uncompressed xattr id lookup table indexes from disk into memory 64 * Read uncompressed xattr id lookup table indexes from disk into memory
65 */ 65 */
66 __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, 66 __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start,
67 u64 *xattr_table_start, int *xattr_ids) 67 u64 *xattr_table_start, int *xattr_ids)
68 { 68 {
69 unsigned int len; 69 unsigned int len;
70 __le64 *xid_table; 70 struct squashfs_xattr_id_table *id_table;
71 struct squashfs_xattr_id_table id_table;
72 int err;
73 71
74 err = squashfs_read_table(sb, &id_table, start, sizeof(id_table)); 72 id_table = squashfs_read_table(sb, start, sizeof(*id_table));
75 if (err < 0) { 73 if (IS_ERR(id_table))
76 ERROR("unable to read xattr id table\n"); 74 return (__le64 *) id_table;
77 return ERR_PTR(err); 75
78 } 76 *xattr_table_start = le64_to_cpu(id_table->xattr_table_start);
79 *xattr_table_start = le64_to_cpu(id_table.xattr_table_start); 77 *xattr_ids = le32_to_cpu(id_table->xattr_ids);
80 *xattr_ids = le32_to_cpu(id_table.xattr_ids); 78 kfree(id_table);
81 len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); 79 len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids);
82 80
83 TRACE("In read_xattr_index_table, length %d\n", len); 81 TRACE("In read_xattr_index_table, length %d\n", len);
84 82
85 /* Allocate xattr id lookup table indexes */ 83 return squashfs_read_table(sb, start + sizeof(*id_table), len);
86 xid_table = kmalloc(len, GFP_KERNEL);
87 if (xid_table == NULL) {
88 ERROR("Failed to allocate xattr id index table\n");
89 return ERR_PTR(-ENOMEM);
90 }
91
92 err = squashfs_read_table(sb, xid_table, start + sizeof(id_table), len);
93 if (err < 0) {
94 ERROR("unable to read xattr id index table\n");
95 kfree(xid_table);
96 return ERR_PTR(err);
97 }
98
99 return xid_table;
100 } 84 }
101 85