1 /*
2 * Squashfs - a compressed read only filesystem for Linux
3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * inode.c
22 */
23
24 #include <linux/types.h>
25 #include <linux/squashfs_fs.h>
26 #include <linux/module.h>
27 #include <linux/errno.h>
28 #include <linux/slab.h>
29 #include <linux/zlib.h>
30 #include <linux/fs.h>
31 #include <linux/smp_lock.h>
32 #include <linux/locks.h>
33 #include <linux/init.h>
34 #include <linux/dcache.h>
35 #include <linux/wait.h>
36 #include <linux/blkdev.h>
37 #include <linux/vmalloc.h>
38 #include <asm/uaccess.h>
39 #include <asm/semaphore.h>
40
41 #include "squashfs.h"
42
43 static struct super_block *squashfs_read_super(struct super_block *, void *, int);
44 static void squashfs_put_super(struct super_block *);
45 static int squashfs_statfs(struct super_block *, struct statfs *);
46 static int squashfs_symlink_readpage(struct file *file, struct page *page);
47 static int squashfs_readpage(struct file *file, struct page *page);
48 static int squashfs_readpage4K(struct file *file, struct page *page);
49 static int squashfs_readdir(struct file *, void *, filldir_t);
50 static struct dentry *squashfs_lookup(struct inode *, struct dentry *);
51 static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
52 static long long read_blocklist(struct inode *inode, int index,
53 int readahead_blks, char *block_list,
54 unsigned short **block_p, unsigned int *bsize);
55
56 static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super);
57
58 static unsigned char squashfs_filetype_table[] = {
59 DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
60 };
61
62 static struct super_operations squashfs_ops = {
63 .statfs = squashfs_statfs,
64 .put_super = squashfs_put_super,
65 };
66
67 SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
68 .readpage = squashfs_symlink_readpage
69 };
70
71 SQSH_EXTERN struct address_space_operations squashfs_aops = {
72 .readpage = squashfs_readpage
73 };
74
75 SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
76 .readpage = squashfs_readpage4K
77 };
78
79 static struct file_operations squashfs_dir_ops = {
80 .read = generic_read_dir,
81 .readdir = squashfs_readdir
82 };
83
84 static struct inode_operations squashfs_dir_inode_ops = {
85 .lookup = squashfs_lookup
86 };
87
get_block_length(struct super_block * s,int * cur_index,int * offset,int * c_byte)88 static struct buffer_head *get_block_length(struct super_block *s,
89 int *cur_index, int *offset, int *c_byte)
90 {
91 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
92 unsigned short temp;
93 struct buffer_head *bh;
94
95 if (!(bh = sb_bread(s, *cur_index)))
96 goto out;
97
98 if (msblk->devblksize - *offset == 1) {
99 if (msblk->swap)
100 ((unsigned char *) &temp)[1] = *((unsigned char *)
101 (bh->b_data + *offset));
102 else
103 ((unsigned char *) &temp)[0] = *((unsigned char *)
104 (bh->b_data + *offset));
105 brelse(bh);
106 if (!(bh = sb_bread(s, ++(*cur_index))))
107 goto out;
108 if (msblk->swap)
109 ((unsigned char *) &temp)[0] = *((unsigned char *)
110 bh->b_data);
111 else
112 ((unsigned char *) &temp)[1] = *((unsigned char *)
113 bh->b_data);
114 *c_byte = temp;
115 *offset = 1;
116 } else {
117 if (msblk->swap) {
118 ((unsigned char *) &temp)[1] = *((unsigned char *)
119 (bh->b_data + *offset));
120 ((unsigned char *) &temp)[0] = *((unsigned char *)
121 (bh->b_data + *offset + 1));
122 } else {
123 ((unsigned char *) &temp)[0] = *((unsigned char *)
124 (bh->b_data + *offset));
125 ((unsigned char *) &temp)[1] = *((unsigned char *)
126 (bh->b_data + *offset + 1));
127 }
128 *c_byte = temp;
129 *offset += 2;
130 }
131
132 if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
133 if (*offset == msblk->devblksize) {
134 brelse(bh);
135 if (!(bh = sb_bread(s, ++(*cur_index))))
136 goto out;
137 *offset = 0;
138 }
139 if (*((unsigned char *) (bh->b_data + *offset)) !=
140 SQUASHFS_MARKER_BYTE) {
141 ERROR("Metadata block marker corrupt @ %x\n",
142 *cur_index);
143 brelse(bh);
144 goto out;
145 }
146 (*offset)++;
147 }
148 return bh;
149
150 out:
151 return NULL;
152 }
153
154
squashfs_read_data(struct super_block * s,char * buffer,long long index,unsigned int length,long long * next_index)155 SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
156 long long index, unsigned int length,
157 long long *next_index)
158 {
159 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
160 struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
161 msblk->devblksize_log2) + 2];
162 unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
163 unsigned int cur_index = index >> msblk->devblksize_log2;
164 int bytes, avail_bytes, b = 0, k;
165 char *c_buffer;
166 unsigned int compressed;
167 unsigned int c_byte = length;
168
169 if (c_byte) {
170 bytes = msblk->devblksize - offset;
171 compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
172 c_buffer = compressed ? msblk->read_data : buffer;
173 c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
174
175 TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
176 ? "" : "un", (unsigned int) c_byte);
177
178 if (!(bh[0] = sb_getblk(s, cur_index)))
179 goto block_release;
180
181 for (b = 1; bytes < c_byte; b++) {
182 if (!(bh[b] = sb_getblk(s, ++cur_index)))
183 goto block_release;
184 bytes += msblk->devblksize;
185 }
186 ll_rw_block(READ, b, bh);
187 } else {
188 if (!(bh[0] = get_block_length(s, &cur_index, &offset,
189 &c_byte)))
190 goto read_failure;
191
192 bytes = msblk->devblksize - offset;
193 compressed = SQUASHFS_COMPRESSED(c_byte);
194 c_buffer = compressed ? msblk->read_data : buffer;
195 c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
196
197 TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
198 ? "" : "un", (unsigned int) c_byte);
199
200 for (b = 1; bytes < c_byte; b++) {
201 if (!(bh[b] = sb_getblk(s, ++cur_index)))
202 goto block_release;
203 bytes += msblk->devblksize;
204 }
205 ll_rw_block(READ, b - 1, bh + 1);
206 }
207
208 if (compressed)
209 down(&msblk->read_data_mutex);
210
211 for (bytes = 0, k = 0; k < b; k++) {
212 avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
213 msblk->devblksize - offset :
214 c_byte - bytes;
215 wait_on_buffer(bh[k]);
216 if (!buffer_uptodate(bh[k]))
217 goto block_release;
218 memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
219 bytes += avail_bytes;
220 offset = 0;
221 brelse(bh[k]);
222 }
223
224 /*
225 * uncompress block
226 */
227 if (compressed) {
228 int zlib_err;
229
230 msblk->stream.next_in = c_buffer;
231 msblk->stream.avail_in = c_byte;
232 msblk->stream.next_out = buffer;
233 msblk->stream.avail_out = msblk->read_size;
234
235 if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) ||
236 ((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH))
237 != Z_STREAM_END) || ((zlib_err =
238 zlib_inflateEnd(&msblk->stream)) != Z_OK)) {
239 ERROR("zlib_fs returned unexpected result 0x%x\n",
240 zlib_err);
241 bytes = 0;
242 } else
243 bytes = msblk->stream.total_out;
244
245 up(&msblk->read_data_mutex);
246 }
247
248 if (next_index)
249 *next_index = index + c_byte + (length ? 0 :
250 (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
251 ? 3 : 2));
252 return bytes;
253
254 block_release:
255 while (--b >= 0)
256 brelse(bh[b]);
257
258 read_failure:
259 ERROR("sb_bread failed reading block 0x%x\n", cur_index);
260 return 0;
261 }
262
263
squashfs_get_cached_block(struct super_block * s,char * buffer,long long block,unsigned int offset,int length,long long * next_block,unsigned int * next_offset)264 SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
265 long long block, unsigned int offset,
266 int length, long long *next_block,
267 unsigned int *next_offset)
268 {
269 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
270 int n, i, bytes, return_length = length;
271 long long next_index;
272
273 TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
274
275 while ( 1 ) {
276 for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
277 if (msblk->block_cache[i].block == block)
278 break;
279
280 down(&msblk->block_cache_mutex);
281
282 if (i == SQUASHFS_CACHED_BLKS) {
283 /* read inode header block */
284 for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
285 n ; n --, i = (i + 1) %
286 SQUASHFS_CACHED_BLKS)
287 if (msblk->block_cache[i].block !=
288 SQUASHFS_USED_BLK)
289 break;
290
291 if (n == 0) {
292 wait_queue_t wait;
293
294 init_waitqueue_entry(&wait, current);
295 add_wait_queue(&msblk->waitq, &wait);
296 set_current_state(TASK_UNINTERRUPTIBLE);
297 up(&msblk->block_cache_mutex);
298 schedule();
299 set_current_state(TASK_RUNNING);
300 remove_wait_queue(&msblk->waitq, &wait);
301 continue;
302 }
303 msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
304
305 if (msblk->block_cache[i].block ==
306 SQUASHFS_INVALID_BLK) {
307 if (!(msblk->block_cache[i].data =
308 kmalloc(SQUASHFS_METADATA_SIZE,
309 GFP_KERNEL))) {
310 ERROR("Failed to allocate cache"
311 "block\n");
312 up(&msblk->block_cache_mutex);
313 goto out;
314 }
315 }
316
317 msblk->block_cache[i].block = SQUASHFS_USED_BLK;
318 up(&msblk->block_cache_mutex);
319
320 if (!(msblk->block_cache[i].length =
321 squashfs_read_data(s,
322 msblk->block_cache[i].data,
323 block, 0, &next_index))) {
324 ERROR("Unable to read cache block [%llx:%x]\n",
325 block, offset);
326 goto out;
327 }
328
329 down(&msblk->block_cache_mutex);
330 wake_up(&msblk->waitq);
331 msblk->block_cache[i].block = block;
332 msblk->block_cache[i].next_index = next_index;
333 TRACE("Read cache block [%llx:%x]\n", block, offset);
334 }
335
336 if (msblk->block_cache[i].block != block) {
337 up(&msblk->block_cache_mutex);
338 continue;
339 }
340
341 if ((bytes = msblk->block_cache[i].length - offset) >= length) {
342 if (buffer)
343 memcpy(buffer, msblk->block_cache[i].data +
344 offset, length);
345 if (msblk->block_cache[i].length - offset == length) {
346 *next_block = msblk->block_cache[i].next_index;
347 *next_offset = 0;
348 } else {
349 *next_block = block;
350 *next_offset = offset + length;
351 }
352 up(&msblk->block_cache_mutex);
353 goto finish;
354 } else {
355 if (buffer) {
356 memcpy(buffer, msblk->block_cache[i].data +
357 offset, bytes);
358 buffer += bytes;
359 }
360 block = msblk->block_cache[i].next_index;
361 up(&msblk->block_cache_mutex);
362 length -= bytes;
363 offset = 0;
364 }
365 }
366
367 finish:
368 return return_length;
369 out:
370 return 0;
371 }
372
373
get_fragment_location(struct super_block * s,unsigned int fragment,long long * fragment_start_block,unsigned int * fragment_size)374 static int get_fragment_location(struct super_block *s, unsigned int fragment,
375 long long *fragment_start_block,
376 unsigned int *fragment_size)
377 {
378 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
379 long long start_block =
380 msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
381 int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
382 struct squashfs_fragment_entry fragment_entry;
383
384 if (msblk->swap) {
385 struct squashfs_fragment_entry sfragment_entry;
386
387 if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
388 start_block, offset,
389 sizeof(sfragment_entry), &start_block,
390 &offset))
391 goto out;
392 SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
393 } else
394 if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
395 start_block, offset,
396 sizeof(fragment_entry), &start_block,
397 &offset))
398 goto out;
399
400 *fragment_start_block = fragment_entry.start_block;
401 *fragment_size = fragment_entry.size;
402
403 return 1;
404
405 out:
406 return 0;
407 }
408
409
release_cached_fragment(struct squashfs_sb_info * msblk,struct squashfs_fragment_cache * fragment)410 SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
411 squashfs_fragment_cache *fragment)
412 {
413 down(&msblk->fragment_mutex);
414 fragment->locked --;
415 wake_up(&msblk->fragment_wait_queue);
416 up(&msblk->fragment_mutex);
417 }
418
419
get_cached_fragment(struct super_block * s,long long start_block,int length)420 SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
421 *s, long long start_block,
422 int length)
423 {
424 int i, n;
425 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
426
427 while ( 1 ) {
428 down(&msblk->fragment_mutex);
429
430 for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
431 msblk->fragment[i].block != start_block; i++);
432
433 if (i == SQUASHFS_CACHED_FRAGMENTS) {
434 for (i = msblk->next_fragment, n =
435 SQUASHFS_CACHED_FRAGMENTS; n &&
436 msblk->fragment[i].locked; n--, i = (i + 1) %
437 SQUASHFS_CACHED_FRAGMENTS);
438
439 if (n == 0) {
440 wait_queue_t wait;
441
442 init_waitqueue_entry(&wait, current);
443 add_wait_queue(&msblk->fragment_wait_queue,
444 &wait);
445 set_current_state(TASK_UNINTERRUPTIBLE);
446 up(&msblk->fragment_mutex);
447 schedule();
448 set_current_state(TASK_RUNNING);
449 remove_wait_queue(&msblk->fragment_wait_queue,
450 &wait);
451 continue;
452 }
453 msblk->next_fragment = (msblk->next_fragment + 1) %
454 SQUASHFS_CACHED_FRAGMENTS;
455
456 if (msblk->fragment[i].data == NULL)
457 if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
458 (SQUASHFS_FILE_MAX_SIZE))) {
459 ERROR("Failed to allocate fragment "
460 "cache block\n");
461 up(&msblk->fragment_mutex);
462 goto out;
463 }
464
465 msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
466 msblk->fragment[i].locked = 1;
467 up(&msblk->fragment_mutex);
468
469 if (!(msblk->fragment[i].length = squashfs_read_data(s,
470 msblk->fragment[i].data,
471 start_block, length, NULL))) {
472 ERROR("Unable to read fragment cache block "
473 "[%llx]\n", start_block);
474 msblk->fragment[i].locked = 0;
475 goto out;
476 }
477
478 msblk->fragment[i].block = start_block;
479 TRACE("New fragment %d, start block %lld, locked %d\n",
480 i, msblk->fragment[i].block,
481 msblk->fragment[i].locked);
482 break;
483 }
484
485 msblk->fragment[i].locked++;
486 up(&msblk->fragment_mutex);
487 TRACE("Got fragment %d, start block %lld, locked %d\n", i,
488 msblk->fragment[i].block,
489 msblk->fragment[i].locked);
490 break;
491 }
492
493 return &msblk->fragment[i];
494
495 out:
496 return NULL;
497 }
498
499
squashfs_new_inode(struct super_block * s,struct squashfs_base_inode_header * inodeb)500 static struct inode *squashfs_new_inode(struct super_block *s,
501 struct squashfs_base_inode_header *inodeb)
502 {
503 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
504 struct inode *i = new_inode(s);
505
506 if (i) {
507 i->i_ino = inodeb->inode_number;
508 i->i_mtime = inodeb->mtime;
509 i->i_atime = inodeb->mtime;
510 i->i_ctime = inodeb->mtime;
511 i->i_uid = msblk->uid[inodeb->uid];
512 i->i_mode = inodeb->mode;
513 i->i_size = 0;
514 if (inodeb->guid == SQUASHFS_GUIDS)
515 i->i_gid = i->i_uid;
516 else
517 i->i_gid = msblk->guid[inodeb->guid];
518 }
519
520 return i;
521 }
522
523
squashfs_iget(struct super_block * s,squashfs_inode_t inode)524 static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
525 {
526 struct inode *i;
527 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
528 struct squashfs_super_block *sblk = &msblk->sblk;
529 long long block = SQUASHFS_INODE_BLK(inode) +
530 sblk->inode_table_start;
531 unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
532 long long next_block;
533 unsigned int next_offset;
534 union squashfs_inode_header id, sid;
535 struct squashfs_base_inode_header *inodeb = &id.base,
536 *sinodeb = &sid.base;
537
538 TRACE("Entered squashfs_iget\n");
539
540 if (msblk->swap) {
541 if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
542 offset, sizeof(*sinodeb), &next_block,
543 &next_offset))
544 goto failed_read;
545 SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
546 sizeof(*sinodeb));
547 } else
548 if (!squashfs_get_cached_block(s, (char *) inodeb, block,
549 offset, sizeof(*inodeb), &next_block,
550 &next_offset))
551 goto failed_read;
552
553 switch(inodeb->inode_type) {
554 case SQUASHFS_FILE_TYPE: {
555 unsigned int frag_size;
556 long long frag_blk;
557 struct squashfs_reg_inode_header *inodep = &id.reg;
558 struct squashfs_reg_inode_header *sinodep = &sid.reg;
559
560 if (msblk->swap) {
561 if (!squashfs_get_cached_block(s, (char *)
562 sinodep, block, offset,
563 sizeof(*sinodep), &next_block,
564 &next_offset))
565 goto failed_read;
566 SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
567 } else
568 if (!squashfs_get_cached_block(s, (char *)
569 inodep, block, offset,
570 sizeof(*inodep), &next_block,
571 &next_offset))
572 goto failed_read;
573
574 frag_blk = SQUASHFS_INVALID_BLK;
575 if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
576 !get_fragment_location(s,
577 inodep->fragment, &frag_blk, &frag_size))
578 goto failed_read;
579
580 if((i = squashfs_new_inode(s, inodeb)) == NULL)
581 goto failed_read1;
582
583 i->i_nlink = 1;
584 i->i_size = inodep->file_size;
585 i->i_fop = &generic_ro_fops;
586 i->i_mode |= S_IFREG;
587 i->i_blocks = ((i->i_size - 1) >> 9) + 1;
588 i->i_blksize = PAGE_CACHE_SIZE;
589 SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
590 SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
591 SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
592 SQUASHFS_I(i)->start_block = inodep->start_block;
593 SQUASHFS_I(i)->u.s1.block_list_start = next_block;
594 SQUASHFS_I(i)->offset = next_offset;
595 if (sblk->block_size > 4096)
596 i->i_data.a_ops = &squashfs_aops;
597 else
598 i->i_data.a_ops = &squashfs_aops_4K;
599
600 TRACE("File inode %x:%x, start_block %llx, "
601 "block_list_start %llx, offset %x\n",
602 SQUASHFS_INODE_BLK(inode), offset,
603 inodep->start_block, next_block,
604 next_offset);
605 break;
606 }
607 case SQUASHFS_LREG_TYPE: {
608 unsigned int frag_size;
609 long long frag_blk;
610 struct squashfs_lreg_inode_header *inodep = &id.lreg;
611 struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
612
613 if (msblk->swap) {
614 if (!squashfs_get_cached_block(s, (char *)
615 sinodep, block, offset,
616 sizeof(*sinodep), &next_block,
617 &next_offset))
618 goto failed_read;
619 SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
620 } else
621 if (!squashfs_get_cached_block(s, (char *)
622 inodep, block, offset,
623 sizeof(*inodep), &next_block,
624 &next_offset))
625 goto failed_read;
626
627 frag_blk = SQUASHFS_INVALID_BLK;
628 if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
629 !get_fragment_location(s,
630 inodep->fragment, &frag_blk, &frag_size))
631 goto failed_read;
632
633 if((i = squashfs_new_inode(s, inodeb)) == NULL)
634 goto failed_read1;
635
636 i->i_nlink = inodep->nlink;
637 i->i_size = inodep->file_size;
638 i->i_fop = &generic_ro_fops;
639 i->i_mode |= S_IFREG;
640 i->i_blocks = ((i->i_size - 1) >> 9) + 1;
641 i->i_blksize = PAGE_CACHE_SIZE;
642 SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
643 SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
644 SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
645 SQUASHFS_I(i)->start_block = inodep->start_block;
646 SQUASHFS_I(i)->u.s1.block_list_start = next_block;
647 SQUASHFS_I(i)->offset = next_offset;
648 if (sblk->block_size > 4096)
649 i->i_data.a_ops = &squashfs_aops;
650 else
651 i->i_data.a_ops = &squashfs_aops_4K;
652
653 TRACE("File inode %x:%x, start_block %llx, "
654 "block_list_start %llx, offset %x\n",
655 SQUASHFS_INODE_BLK(inode), offset,
656 inodep->start_block, next_block,
657 next_offset);
658 break;
659 }
660 case SQUASHFS_DIR_TYPE: {
661 struct squashfs_dir_inode_header *inodep = &id.dir;
662 struct squashfs_dir_inode_header *sinodep = &sid.dir;
663
664 if (msblk->swap) {
665 if (!squashfs_get_cached_block(s, (char *)
666 sinodep, block, offset,
667 sizeof(*sinodep), &next_block,
668 &next_offset))
669 goto failed_read;
670 SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
671 } else
672 if (!squashfs_get_cached_block(s, (char *)
673 inodep, block, offset,
674 sizeof(*inodep), &next_block,
675 &next_offset))
676 goto failed_read;
677
678 if((i = squashfs_new_inode(s, inodeb)) == NULL)
679 goto failed_read1;
680
681 i->i_nlink = inodep->nlink;
682 i->i_size = inodep->file_size;
683 i->i_op = &squashfs_dir_inode_ops;
684 i->i_fop = &squashfs_dir_ops;
685 i->i_mode |= S_IFDIR;
686 SQUASHFS_I(i)->start_block = inodep->start_block;
687 SQUASHFS_I(i)->offset = inodep->offset;
688 SQUASHFS_I(i)->u.s2.directory_index_count = 0;
689 SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
690
691 TRACE("Directory inode %x:%x, start_block %x, offset "
692 "%x\n", SQUASHFS_INODE_BLK(inode),
693 offset, inodep->start_block,
694 inodep->offset);
695 break;
696 }
697 case SQUASHFS_LDIR_TYPE: {
698 struct squashfs_ldir_inode_header *inodep = &id.ldir;
699 struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
700
701 if (msblk->swap) {
702 if (!squashfs_get_cached_block(s, (char *)
703 sinodep, block, offset,
704 sizeof(*sinodep), &next_block,
705 &next_offset))
706 goto failed_read;
707 SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
708 sinodep);
709 } else
710 if (!squashfs_get_cached_block(s, (char *)
711 inodep, block, offset,
712 sizeof(*inodep), &next_block,
713 &next_offset))
714 goto failed_read;
715
716 if((i = squashfs_new_inode(s, inodeb)) == NULL)
717 goto failed_read1;
718
719 i->i_nlink = inodep->nlink;
720 i->i_size = inodep->file_size;
721 i->i_op = &squashfs_dir_inode_ops;
722 i->i_fop = &squashfs_dir_ops;
723 i->i_mode |= S_IFDIR;
724 SQUASHFS_I(i)->start_block = inodep->start_block;
725 SQUASHFS_I(i)->offset = inodep->offset;
726 SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
727 SQUASHFS_I(i)->u.s2.directory_index_offset =
728 next_offset;
729 SQUASHFS_I(i)->u.s2.directory_index_count =
730 inodep->i_count;
731 SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
732
733 TRACE("Long directory inode %x:%x, start_block %x, "
734 "offset %x\n",
735 SQUASHFS_INODE_BLK(inode), offset,
736 inodep->start_block, inodep->offset);
737 break;
738 }
739 case SQUASHFS_SYMLINK_TYPE: {
740 struct squashfs_symlink_inode_header *inodep =
741 &id.symlink;
742 struct squashfs_symlink_inode_header *sinodep =
743 &sid.symlink;
744
745 if (msblk->swap) {
746 if (!squashfs_get_cached_block(s, (char *)
747 sinodep, block, offset,
748 sizeof(*sinodep), &next_block,
749 &next_offset))
750 goto failed_read;
751 SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
752 sinodep);
753 } else
754 if (!squashfs_get_cached_block(s, (char *)
755 inodep, block, offset,
756 sizeof(*inodep), &next_block,
757 &next_offset))
758 goto failed_read;
759
760 if((i = squashfs_new_inode(s, inodeb)) == NULL)
761 goto failed_read1;
762
763 i->i_nlink = inodep->nlink;
764 i->i_size = inodep->symlink_size;
765 i->i_op = &page_symlink_inode_operations;
766 i->i_data.a_ops = &squashfs_symlink_aops;
767 i->i_mode |= S_IFLNK;
768 SQUASHFS_I(i)->start_block = next_block;
769 SQUASHFS_I(i)->offset = next_offset;
770
771 TRACE("Symbolic link inode %x:%x, start_block %llx, "
772 "offset %x\n",
773 SQUASHFS_INODE_BLK(inode), offset,
774 next_block, next_offset);
775 break;
776 }
777 case SQUASHFS_BLKDEV_TYPE:
778 case SQUASHFS_CHRDEV_TYPE: {
779 struct squashfs_dev_inode_header *inodep = &id.dev;
780 struct squashfs_dev_inode_header *sinodep = &sid.dev;
781
782 if (msblk->swap) {
783 if (!squashfs_get_cached_block(s, (char *)
784 sinodep, block, offset,
785 sizeof(*sinodep), &next_block,
786 &next_offset))
787 goto failed_read;
788 SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
789 } else
790 if (!squashfs_get_cached_block(s, (char *)
791 inodep, block, offset,
792 sizeof(*inodep), &next_block,
793 &next_offset))
794 goto failed_read;
795
796 if ((i = squashfs_new_inode(s, inodeb)) == NULL)
797 goto failed_read1;
798
799 i->i_nlink = inodep->nlink;
800 i->i_mode |= (inodeb->inode_type ==
801 SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
802 S_IFBLK;
803 init_special_inode(i, i->i_mode, inodep->rdev);
804
805 TRACE("Device inode %x:%x, rdev %x\n",
806 SQUASHFS_INODE_BLK(inode), offset,
807 inodep->rdev);
808 break;
809 }
810 case SQUASHFS_FIFO_TYPE:
811 case SQUASHFS_SOCKET_TYPE: {
812 struct squashfs_ipc_inode_header *inodep = &id.ipc;
813 struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
814
815 if (msblk->swap) {
816 if (!squashfs_get_cached_block(s, (char *)
817 sinodep, block, offset,
818 sizeof(*sinodep), &next_block,
819 &next_offset))
820 goto failed_read;
821 SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
822 } else
823 if (!squashfs_get_cached_block(s, (char *)
824 inodep, block, offset,
825 sizeof(*inodep), &next_block,
826 &next_offset))
827 goto failed_read;
828
829 if ((i = squashfs_new_inode(s, inodeb)) == NULL)
830 goto failed_read1;
831
832 i->i_nlink = inodep->nlink;
833 i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
834 ? S_IFIFO : S_IFSOCK;
835 init_special_inode(i, i->i_mode, 0);
836 break;
837 }
838 default:
839 ERROR("Unknown inode type %d in squashfs_iget!\n",
840 inodeb->inode_type);
841 goto failed_read1;
842 }
843
844 insert_inode_hash(i);
845 return i;
846
847 failed_read:
848 ERROR("Unable to read inode [%llx:%x]\n", block, offset);
849
850 failed_read1:
851 return NULL;
852 }
853
854
read_fragment_index_table(struct super_block * s)855 int read_fragment_index_table(struct super_block *s)
856 {
857 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
858 struct squashfs_super_block *sblk = &msblk->sblk;
859
860 if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
861 (sblk->fragments), GFP_KERNEL))) {
862 ERROR("Failed to allocate uid/gid table\n");
863 return 0;
864 }
865
866 if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
867 !squashfs_read_data(s, (char *)
868 msblk->fragment_index,
869 sblk->fragment_table_start,
870 SQUASHFS_FRAGMENT_INDEX_BYTES
871 (sblk->fragments) |
872 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
873 ERROR("unable to read fragment index table\n");
874 return 0;
875 }
876
877 if (msblk->swap) {
878 int i;
879 long long fragment;
880
881 for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
882 i++) {
883 SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
884 &msblk->fragment_index[i], 1);
885 msblk->fragment_index[i] = fragment;
886 }
887 }
888
889 return 1;
890 }
891
892
supported_squashfs_filesystem(struct squashfs_sb_info * msblk,int silent)893 static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
894 {
895 struct squashfs_super_block *sblk = &msblk->sblk;
896
897 msblk->iget = squashfs_iget;
898 msblk->read_blocklist = read_blocklist;
899 msblk->read_fragment_index_table = read_fragment_index_table;
900
901 if (sblk->s_major == 1) {
902 if (!squashfs_1_0_supported(msblk)) {
903 SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
904 "are unsupported\n");
905 SERROR("Please recompile with "
906 "Squashfs 1.0 support enabled\n");
907 return 0;
908 }
909 } else if (sblk->s_major == 2) {
910 if (!squashfs_2_0_supported(msblk)) {
911 SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
912 "are unsupported\n");
913 SERROR("Please recompile with "
914 "Squashfs 2.0 support enabled\n");
915 return 0;
916 }
917 } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
918 SQUASHFS_MINOR) {
919 SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
920 "filesystem\n", sblk->s_major, sblk->s_minor);
921 SERROR("Please update your kernel\n");
922 return 0;
923 }
924
925 return 1;
926 }
927
928
squashfs_read_super(struct super_block * s,void * data,int silent)929 static struct super_block *squashfs_read_super(struct super_block *s,
930 void *data, int silent)
931 {
932 kdev_t dev = s->s_dev;
933 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
934 struct squashfs_super_block *sblk = &msblk->sblk;
935 int i;
936 struct inode *root;
937
938 if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
939 ERROR("Failed to allocate zlib workspace\n");
940 goto failed_mount;
941 }
942
943 msblk->devblksize = get_hardsect_size(dev);
944 if(msblk->devblksize < BLOCK_SIZE)
945 msblk->devblksize = BLOCK_SIZE;
946 msblk->devblksize_log2 = ffz(~msblk->devblksize);
947 set_blocksize(dev, msblk->devblksize);
948 s->s_blocksize = msblk->devblksize;
949 s->s_blocksize_bits = msblk->devblksize_log2;
950
951 init_MUTEX(&msblk->read_data_mutex);
952 init_MUTEX(&msblk->read_page_mutex);
953 init_MUTEX(&msblk->block_cache_mutex);
954 init_MUTEX(&msblk->fragment_mutex);
955
956 init_waitqueue_head(&msblk->waitq);
957 init_waitqueue_head(&msblk->fragment_wait_queue);
958
959 if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
960 sizeof(struct squashfs_super_block) |
961 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
962 SERROR("unable to read superblock\n");
963 goto failed_mount;
964 }
965
966 /* Check it is a SQUASHFS superblock */
967 msblk->swap = 0;
968 if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
969 if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
970 struct squashfs_super_block ssblk;
971
972 WARNING("Mounting a different endian SQUASHFS "
973 "filesystem on %s\n", bdevname(dev));
974
975 SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
976 memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
977 msblk->swap = 1;
978 } else {
979 SERROR("Can't find a SQUASHFS superblock on %s\n",
980 bdevname(dev));
981 goto failed_mount;
982 }
983 }
984
985 /* Check the MAJOR & MINOR versions */
986 if(!supported_squashfs_filesystem(msblk, silent))
987 goto failed_mount;
988
989 TRACE("Found valid superblock on %s\n", bdevname(dev));
990 TRACE("Inodes are %scompressed\n",
991 SQUASHFS_UNCOMPRESSED_INODES
992 (sblk->flags) ? "un" : "");
993 TRACE("Data is %scompressed\n",
994 SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
995 ? "un" : "");
996 TRACE("Check data is %s present in the filesystem\n",
997 SQUASHFS_CHECK_DATA(sblk->flags) ?
998 "" : "not");
999 TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
1000 TRACE("Block size %d\n", sblk->block_size);
1001 TRACE("Number of inodes %d\n", sblk->inodes);
1002 if (sblk->s_major > 1)
1003 TRACE("Number of fragments %d\n", sblk->fragments);
1004 TRACE("Number of uids %d\n", sblk->no_uids);
1005 TRACE("Number of gids %d\n", sblk->no_guids);
1006 TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
1007 TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
1008 if (sblk->s_major > 1)
1009 TRACE("sblk->fragment_table_start %llx\n",
1010 sblk->fragment_table_start);
1011 TRACE("sblk->uid_start %llx\n", sblk->uid_start);
1012
1013 s->s_flags |= MS_RDONLY;
1014 s->s_op = &squashfs_ops;
1015
1016 /* Init inode_table block pointer array */
1017 if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
1018 SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
1019 ERROR("Failed to allocate block cache\n");
1020 goto failed_mount;
1021 }
1022
1023 for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
1024 msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
1025
1026 msblk->next_cache = 0;
1027
1028 /* Allocate read_data block */
1029 msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
1030 SQUASHFS_METADATA_SIZE :
1031 sblk->block_size;
1032
1033 if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
1034 ERROR("Failed to allocate read_data block\n");
1035 goto failed_mount;
1036 }
1037
1038 /* Allocate read_page block */
1039 if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
1040 ERROR("Failed to allocate read_page block\n");
1041 goto failed_mount;
1042 }
1043
1044 /* Allocate uid and gid tables */
1045 if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
1046 sizeof(unsigned int), GFP_KERNEL))) {
1047 ERROR("Failed to allocate uid/gid table\n");
1048 goto failed_mount;
1049 }
1050 msblk->guid = msblk->uid + sblk->no_uids;
1051
1052 if (msblk->swap) {
1053 unsigned int suid[sblk->no_uids + sblk->no_guids];
1054
1055 if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
1056 ((sblk->no_uids + sblk->no_guids) *
1057 sizeof(unsigned int)) |
1058 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1059 ERROR("unable to read uid/gid table\n");
1060 goto failed_mount;
1061 }
1062
1063 SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
1064 sblk->no_guids), (sizeof(unsigned int) * 8));
1065 } else
1066 if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
1067 ((sblk->no_uids + sblk->no_guids) *
1068 sizeof(unsigned int)) |
1069 SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1070 ERROR("unable to read uid/gid table\n");
1071 goto failed_mount;
1072 }
1073
1074
1075 if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
1076 goto allocate_root;
1077
1078 if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
1079 SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
1080 ERROR("Failed to allocate fragment block cache\n");
1081 goto failed_mount;
1082 }
1083
1084 for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
1085 msblk->fragment[i].locked = 0;
1086 msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
1087 msblk->fragment[i].data = NULL;
1088 }
1089
1090 msblk->next_fragment = 0;
1091
1092 /* Allocate fragment index table */
1093 if(msblk->read_fragment_index_table(s) == 0)
1094 goto failed_mount;
1095
1096 allocate_root:
1097 if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
1098 goto failed_mount;
1099
1100 if ((s->s_root = d_alloc_root(root)) == NULL) {
1101 ERROR("Root inode create failed\n");
1102 iput(root);
1103 goto failed_mount;
1104 }
1105
1106 TRACE("Leaving squashfs_read_super\n");
1107 return s;
1108
1109 failed_mount:
1110 kfree(msblk->fragment_index);
1111 kfree(msblk->fragment);
1112 kfree(msblk->uid);
1113 kfree(msblk->read_page);
1114 kfree(msblk->read_data);
1115 kfree(msblk->block_cache);
1116 kfree(msblk->fragment_index_2);
1117 vfree(msblk->stream.workspace);
1118 return NULL;
1119 }
1120
1121
squashfs_statfs(struct super_block * s,struct statfs * buf)1122 static int squashfs_statfs(struct super_block *s, struct statfs *buf)
1123 {
1124 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1125 struct squashfs_super_block *sblk = &msblk->sblk;
1126
1127 TRACE("Entered squashfs_statfs\n");
1128
1129 buf->f_type = SQUASHFS_MAGIC;
1130 buf->f_bsize = sblk->block_size;
1131 buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
1132 buf->f_bfree = buf->f_bavail = 0;
1133 buf->f_files = sblk->inodes;
1134 buf->f_ffree = 0;
1135 buf->f_namelen = SQUASHFS_NAME_LEN;
1136
1137 return 0;
1138 }
1139
1140
squashfs_symlink_readpage(struct file * file,struct page * page)1141 static int squashfs_symlink_readpage(struct file *file, struct page *page)
1142 {
1143 struct inode *inode = page->mapping->host;
1144 int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
1145 long long block = SQUASHFS_I(inode)->start_block;
1146 int offset = SQUASHFS_I(inode)->offset;
1147 void *pageaddr = kmap(page);
1148
1149 TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
1150 "%llx, offset %x\n", page->index,
1151 SQUASHFS_I(inode)->start_block,
1152 SQUASHFS_I(inode)->offset);
1153
1154 for (length = 0; length < index; length += bytes) {
1155 if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
1156 block, offset, PAGE_CACHE_SIZE, &block,
1157 &offset))) {
1158 ERROR("Unable to read symbolic link [%llx:%x]\n", block,
1159 offset);
1160 goto skip_read;
1161 }
1162 }
1163
1164 if (length != index) {
1165 ERROR("(squashfs_symlink_readpage) length != index\n");
1166 bytes = 0;
1167 goto skip_read;
1168 }
1169
1170 bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
1171 i_size_read(inode) - length;
1172
1173 if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
1174 offset, bytes, &block, &offset)))
1175 ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
1176
1177 skip_read:
1178 memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1179 kunmap(page);
1180 SetPageUptodate(page);
1181 UnlockPage(page);
1182
1183 return 0;
1184 }
1185
1186
locate_meta_index(struct inode * inode,int index,int offset)1187 struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
1188 {
1189 struct meta_index *meta = NULL;
1190 struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1191 int i;
1192
1193 down(&msblk->meta_index_mutex);
1194
1195 TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
1196
1197 if(msblk->meta_index == NULL)
1198 goto not_allocated;
1199
1200 for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
1201 if (msblk->meta_index[i].inode_number == inode->i_ino &&
1202 msblk->meta_index[i].offset >= offset &&
1203 msblk->meta_index[i].offset <= index &&
1204 msblk->meta_index[i].locked == 0) {
1205 TRACE("locate_meta_index: entry %d, offset %d\n", i,
1206 msblk->meta_index[i].offset);
1207 meta = &msblk->meta_index[i];
1208 offset = meta->offset;
1209 }
1210
1211 if (meta)
1212 meta->locked = 1;
1213
1214 not_allocated:
1215 up(&msblk->meta_index_mutex);
1216
1217 return meta;
1218 }
1219
1220
empty_meta_index(struct inode * inode,int offset,int skip)1221 struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
1222 {
1223 struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1224 struct meta_index *meta = NULL;
1225 int i;
1226
1227 down(&msblk->meta_index_mutex);
1228
1229 TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
1230
1231 if(msblk->meta_index == NULL) {
1232 if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
1233 SQUASHFS_META_NUMBER, GFP_KERNEL))) {
1234 ERROR("Failed to allocate meta_index\n");
1235 goto failed;
1236 }
1237 for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
1238 msblk->meta_index[i].inode_number = 0;
1239 msblk->meta_index[i].locked = 0;
1240 }
1241 msblk->next_meta_index = 0;
1242 }
1243
1244 for(i = SQUASHFS_META_NUMBER; i &&
1245 msblk->meta_index[msblk->next_meta_index].locked; i --)
1246 msblk->next_meta_index = (msblk->next_meta_index + 1) %
1247 SQUASHFS_META_NUMBER;
1248
1249 if(i == 0) {
1250 TRACE("empty_meta_index: failed!\n");
1251 goto failed;
1252 }
1253
1254 TRACE("empty_meta_index: returned meta entry %d, %p\n",
1255 msblk->next_meta_index,
1256 &msblk->meta_index[msblk->next_meta_index]);
1257
1258 meta = &msblk->meta_index[msblk->next_meta_index];
1259 msblk->next_meta_index = (msblk->next_meta_index + 1) %
1260 SQUASHFS_META_NUMBER;
1261
1262 meta->inode_number = inode->i_ino;
1263 meta->offset = offset;
1264 meta->skip = skip;
1265 meta->entries = 0;
1266 meta->locked = 1;
1267
1268 failed:
1269 up(&msblk->meta_index_mutex);
1270 return meta;
1271 }
1272
1273
release_meta_index(struct inode * inode,struct meta_index * meta)1274 void release_meta_index(struct inode *inode, struct meta_index *meta)
1275 {
1276 meta->locked = 0;
1277 }
1278
1279
read_block_index(struct super_block * s,int blocks,char * block_list,long long * start_block,int * offset)1280 static int read_block_index(struct super_block *s, int blocks, char *block_list,
1281 long long *start_block, int *offset)
1282 {
1283 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1284 unsigned int *block_listp;
1285 int block = 0;
1286
1287 if (msblk->swap) {
1288 char sblock_list[blocks << 2];
1289
1290 if (!squashfs_get_cached_block(s, sblock_list, *start_block,
1291 *offset, blocks << 2, start_block, offset)) {
1292 ERROR("Unable to read block list [%llx:%x]\n",
1293 *start_block, *offset);
1294 goto failure;
1295 }
1296 SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
1297 ((unsigned int *)sblock_list), blocks);
1298 } else
1299 if (!squashfs_get_cached_block(s, block_list, *start_block,
1300 *offset, blocks << 2, start_block, offset)) {
1301 ERROR("Unable to read block list [%llx:%x]\n",
1302 *start_block, *offset);
1303 goto failure;
1304 }
1305
1306 for (block_listp = (unsigned int *) block_list; blocks;
1307 block_listp++, blocks --)
1308 block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
1309
1310 return block;
1311
1312 failure:
1313 return -1;
1314 }
1315
1316
1317 #define SIZE 256
1318
calculate_skip(int blocks)1319 static inline int calculate_skip(int blocks) {
1320 int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
1321 return skip >= 7 ? 7 : skip + 1;
1322 }
1323
1324
get_meta_index(struct inode * inode,int index,long long * index_block,int * index_offset,long long * data_block,char * block_list)1325 static int get_meta_index(struct inode *inode, int index,
1326 long long *index_block, int *index_offset,
1327 long long *data_block, char *block_list)
1328 {
1329 struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1330 struct squashfs_super_block *sblk = &msblk->sblk;
1331 int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
1332 int offset = 0;
1333 struct meta_index *meta;
1334 struct meta_entry *meta_entry;
1335 long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
1336 int cur_offset = SQUASHFS_I(inode)->offset;
1337 long long cur_data_block = SQUASHFS_I(inode)->start_block;
1338 int i;
1339
1340 index /= SQUASHFS_META_INDEXES * skip;
1341
1342 while ( offset < index ) {
1343 meta = locate_meta_index(inode, index, offset + 1);
1344
1345 if (meta == NULL) {
1346 if ((meta = empty_meta_index(inode, offset + 1,
1347 skip)) == NULL)
1348 goto all_done;
1349 } else {
1350 offset = index < meta->offset + meta->entries ? index :
1351 meta->offset + meta->entries - 1;
1352 meta_entry = &meta->meta_entry[offset - meta->offset];
1353 cur_index_block = meta_entry->index_block + sblk->inode_table_start;
1354 cur_offset = meta_entry->offset;
1355 cur_data_block = meta_entry->data_block;
1356 TRACE("get_meta_index: offset %d, meta->offset %d, "
1357 "meta->entries %d\n", offset, meta->offset,
1358 meta->entries);
1359 TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
1360 " data_block 0x%llx\n", cur_index_block,
1361 cur_offset, cur_data_block);
1362 }
1363
1364 for (i = meta->offset + meta->entries; i <= index &&
1365 i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
1366 int blocks = skip * SQUASHFS_META_INDEXES;
1367
1368 while (blocks) {
1369 int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
1370 blocks;
1371 int res = read_block_index(inode->i_sb, block,
1372 block_list, &cur_index_block,
1373 &cur_offset);
1374
1375 if (res == -1)
1376 goto failed;
1377
1378 cur_data_block += res;
1379 blocks -= block;
1380 }
1381
1382 meta_entry = &meta->meta_entry[i - meta->offset];
1383 meta_entry->index_block = cur_index_block - sblk->inode_table_start;
1384 meta_entry->offset = cur_offset;
1385 meta_entry->data_block = cur_data_block;
1386 meta->entries ++;
1387 offset ++;
1388 }
1389
1390 TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
1391 meta->offset, meta->entries);
1392
1393 release_meta_index(inode, meta);
1394 }
1395
1396 all_done:
1397 *index_block = cur_index_block;
1398 *index_offset = cur_offset;
1399 *data_block = cur_data_block;
1400
1401 return offset * SQUASHFS_META_INDEXES * skip;
1402
1403 failed:
1404 release_meta_index(inode, meta);
1405 return -1;
1406 }
1407
1408
read_blocklist(struct inode * inode,int index,int readahead_blks,char * block_list,unsigned short ** block_p,unsigned int * bsize)1409 static long long read_blocklist(struct inode *inode, int index,
1410 int readahead_blks, char *block_list,
1411 unsigned short **block_p, unsigned int *bsize)
1412 {
1413 long long block_ptr;
1414 int offset;
1415 long long block;
1416 int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
1417 block_list);
1418
1419 TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
1420 " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
1421 block);
1422
1423 if(res == -1)
1424 goto failure;
1425
1426 index -= res;
1427
1428 while ( index ) {
1429 int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
1430 int res = read_block_index(inode->i_sb, blocks, block_list,
1431 &block_ptr, &offset);
1432 if (res == -1)
1433 goto failure;
1434 block += res;
1435 index -= blocks;
1436 }
1437
1438 if (read_block_index(inode->i_sb, 1, block_list,
1439 &block_ptr, &offset) == -1)
1440 goto failure;
1441 *bsize = *((unsigned int *) block_list);
1442
1443 return block;
1444
1445 failure:
1446 return 0;
1447 }
1448
1449
squashfs_readpage(struct file * file,struct page * page)1450 static int squashfs_readpage(struct file *file, struct page *page)
1451 {
1452 struct inode *inode = page->mapping->host;
1453 struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1454 struct squashfs_super_block *sblk = &msblk->sblk;
1455 unsigned char block_list[SIZE];
1456 long long block;
1457 unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
1458 int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
1459 void *pageaddr;
1460 struct squashfs_fragment_cache *fragment = NULL;
1461 char *data_ptr = msblk->read_page;
1462
1463 int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
1464 int start_index = page->index & ~mask;
1465 int end_index = start_index | mask;
1466
1467 TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
1468 page->index,
1469 SQUASHFS_I(inode)->start_block);
1470
1471 if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1472 PAGE_CACHE_SHIFT))
1473 goto skip_read;
1474
1475 if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1476 || index < (i_size_read(inode) >>
1477 sblk->block_log)) {
1478 if ((block = (msblk->read_blocklist)(inode, index, 1,
1479 block_list, NULL, &bsize)) == 0)
1480 goto skip_read;
1481
1482 down(&msblk->read_page_mutex);
1483
1484 if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
1485 block, bsize, NULL))) {
1486 ERROR("Unable to read page, block %llx, size %x\n", block,
1487 bsize);
1488 up(&msblk->read_page_mutex);
1489 goto skip_read;
1490 }
1491 } else {
1492 if ((fragment = get_cached_fragment(inode->i_sb,
1493 SQUASHFS_I(inode)->
1494 u.s1.fragment_start_block,
1495 SQUASHFS_I(inode)->u.s1.fragment_size))
1496 == NULL) {
1497 ERROR("Unable to read page, block %llx, size %x\n",
1498 SQUASHFS_I(inode)->
1499 u.s1.fragment_start_block,
1500 (int) SQUASHFS_I(inode)->
1501 u.s1.fragment_size);
1502 goto skip_read;
1503 }
1504 bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
1505 (i_size_read(inode) & (sblk->block_size
1506 - 1));
1507 byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
1508 data_ptr = fragment->data;
1509 }
1510
1511 for (i = start_index; i <= end_index && byte_offset < bytes;
1512 i++, byte_offset += PAGE_CACHE_SIZE) {
1513 struct page *push_page;
1514 int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
1515 PAGE_CACHE_SIZE : bytes - byte_offset;
1516
1517 TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
1518 bytes, i, byte_offset, available_bytes);
1519
1520 if (i == page->index) {
1521 pageaddr = kmap_atomic(page, KM_USER0);
1522 memcpy(pageaddr, data_ptr + byte_offset,
1523 available_bytes);
1524 memset(pageaddr + available_bytes, 0,
1525 PAGE_CACHE_SIZE - available_bytes);
1526 kunmap_atomic(pageaddr, KM_USER0);
1527 flush_dcache_page(page);
1528 SetPageUptodate(page);
1529 UnlockPage(page);
1530 } else if ((push_page =
1531 grab_cache_page_nowait(page->mapping, i))) {
1532 pageaddr = kmap_atomic(push_page, KM_USER0);
1533
1534 memcpy(pageaddr, data_ptr + byte_offset,
1535 available_bytes);
1536 memset(pageaddr + available_bytes, 0,
1537 PAGE_CACHE_SIZE - available_bytes);
1538 kunmap_atomic(pageaddr, KM_USER0);
1539 flush_dcache_page(push_page);
1540 SetPageUptodate(push_page);
1541 UnlockPage(push_page);
1542 page_cache_release(push_page);
1543 }
1544 }
1545
1546 if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1547 || index < (i_size_read(inode) >>
1548 sblk->block_log))
1549 up(&msblk->read_page_mutex);
1550 else
1551 release_cached_fragment(msblk, fragment);
1552
1553 return 0;
1554
1555 skip_read:
1556 pageaddr = kmap_atomic(page, KM_USER0);
1557 memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1558 kunmap_atomic(pageaddr, KM_USER0);
1559 flush_dcache_page(page);
1560 SetPageUptodate(page);
1561 UnlockPage(page);
1562
1563 return 0;
1564 }
1565
1566
squashfs_readpage4K(struct file * file,struct page * page)1567 static int squashfs_readpage4K(struct file *file, struct page *page)
1568 {
1569 struct inode *inode = page->mapping->host;
1570 struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1571 struct squashfs_super_block *sblk = &msblk->sblk;
1572 unsigned char block_list[SIZE];
1573 long long block;
1574 unsigned int bsize, bytes = 0;
1575 void *pageaddr;
1576
1577 TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
1578 page->index,
1579 SQUASHFS_I(inode)->start_block);
1580
1581 if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1582 PAGE_CACHE_SHIFT)) {
1583 pageaddr = kmap_atomic(page, KM_USER0);
1584 goto skip_read;
1585 }
1586
1587 if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1588 || page->index < (i_size_read(inode) >>
1589 sblk->block_log)) {
1590 block = (msblk->read_blocklist)(inode, page->index, 1,
1591 block_list, NULL, &bsize);
1592
1593 down(&msblk->read_page_mutex);
1594 bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
1595 bsize, NULL);
1596 pageaddr = kmap_atomic(page, KM_USER0);
1597 if (bytes)
1598 memcpy(pageaddr, msblk->read_page, bytes);
1599 else
1600 ERROR("Unable to read page, block %llx, size %x\n",
1601 block, bsize);
1602 up(&msblk->read_page_mutex);
1603 } else {
1604 struct squashfs_fragment_cache *fragment =
1605 get_cached_fragment(inode->i_sb,
1606 SQUASHFS_I(inode)->
1607 u.s1.fragment_start_block,
1608 SQUASHFS_I(inode)-> u.s1.fragment_size);
1609 pageaddr = kmap_atomic(page, KM_USER0);
1610 if (fragment) {
1611 bytes = i_size_read(inode) & (sblk->block_size - 1);
1612 memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
1613 u.s1.fragment_offset, bytes);
1614 release_cached_fragment(msblk, fragment);
1615 } else
1616 ERROR("Unable to read page, block %llx, size %x\n",
1617 SQUASHFS_I(inode)->
1618 u.s1.fragment_start_block, (int)
1619 SQUASHFS_I(inode)-> u.s1.fragment_size);
1620 }
1621
1622 skip_read:
1623 memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1624 kunmap_atomic(pageaddr, KM_USER0);
1625 flush_dcache_page(page);
1626 SetPageUptodate(page);
1627 UnlockPage(page);
1628
1629 return 0;
1630 }
1631
1632
get_dir_index_using_offset(struct super_block * s,long long * next_block,unsigned int * next_offset,long long index_start,unsigned int index_offset,int i_count,long long f_pos)1633 static int get_dir_index_using_offset(struct super_block *s, long long
1634 *next_block, unsigned int *next_offset,
1635 long long index_start,
1636 unsigned int index_offset, int i_count,
1637 long long f_pos)
1638 {
1639 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1640 struct squashfs_super_block *sblk = &msblk->sblk;
1641 int i, length = 0;
1642 struct squashfs_dir_index index;
1643
1644 TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
1645 i_count, (unsigned int) f_pos);
1646
1647 f_pos -= 3;
1648 if (f_pos == 0)
1649 goto finish;
1650
1651 for (i = 0; i < i_count; i++) {
1652 if (msblk->swap) {
1653 struct squashfs_dir_index sindex;
1654 squashfs_get_cached_block(s, (char *) &sindex,
1655 index_start, index_offset,
1656 sizeof(sindex), &index_start,
1657 &index_offset);
1658 SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
1659 } else
1660 squashfs_get_cached_block(s, (char *) &index,
1661 index_start, index_offset,
1662 sizeof(index), &index_start,
1663 &index_offset);
1664
1665 if (index.index > f_pos)
1666 break;
1667
1668 squashfs_get_cached_block(s, NULL, index_start, index_offset,
1669 index.size + 1, &index_start,
1670 &index_offset);
1671
1672 length = index.index;
1673 *next_block = index.start_block + sblk->directory_table_start;
1674 }
1675
1676 *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
1677
1678 finish:
1679 return length + 3;
1680 }
1681
1682
get_dir_index_using_name(struct super_block * s,long long * next_block,unsigned int * next_offset,long long index_start,unsigned int index_offset,int i_count,const char * name,int size)1683 static int get_dir_index_using_name(struct super_block *s, long long
1684 *next_block, unsigned int *next_offset,
1685 long long index_start,
1686 unsigned int index_offset, int i_count,
1687 const char *name, int size)
1688 {
1689 struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1690 struct squashfs_super_block *sblk = &msblk->sblk;
1691 int i, length = 0;
1692 char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
1693 struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
1694 char str[SQUASHFS_NAME_LEN + 1];
1695
1696 TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
1697
1698 strncpy(str, name, size);
1699 str[size] = '\0';
1700
1701 for (i = 0; i < i_count; i++) {
1702 if (msblk->swap) {
1703 struct squashfs_dir_index sindex;
1704 squashfs_get_cached_block(s, (char *) &sindex,
1705 index_start, index_offset,
1706 sizeof(sindex), &index_start,
1707 &index_offset);
1708 SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
1709 } else
1710 squashfs_get_cached_block(s, (char *) index,
1711 index_start, index_offset,
1712 sizeof(struct squashfs_dir_index),
1713 &index_start, &index_offset);
1714
1715 squashfs_get_cached_block(s, index->name, index_start,
1716 index_offset, index->size + 1,
1717 &index_start, &index_offset);
1718
1719 index->name[index->size + 1] = '\0';
1720
1721 if (strcmp(index->name, str) > 0)
1722 break;
1723
1724 length = index->index;
1725 *next_block = index->start_block + sblk->directory_table_start;
1726 }
1727
1728 *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
1729 return length + 3;
1730 }
1731
1732
squashfs_readdir(struct file * file,void * dirent,filldir_t filldir)1733 static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
1734 {
1735 struct inode *i = file->f_dentry->d_inode;
1736 struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
1737 struct squashfs_super_block *sblk = &msblk->sblk;
1738 long long next_block = SQUASHFS_I(i)->start_block +
1739 sblk->directory_table_start;
1740 int next_offset = SQUASHFS_I(i)->offset, length = 0,
1741 dir_count;
1742 struct squashfs_dir_header dirh;
1743 char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
1744 struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
1745
1746 TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
1747
1748 while(file->f_pos < 3) {
1749 char *name;
1750 int size, i_ino;
1751
1752 if(file->f_pos == 0) {
1753 name = ".";
1754 size = 1;
1755 i_ino = i->i_ino;
1756 } else {
1757 name = "..";
1758 size = 2;
1759 i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
1760 }
1761 TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
1762 (unsigned int) dirent, name, size, (int)
1763 file->f_pos, i_ino,
1764 squashfs_filetype_table[1]);
1765
1766 if (filldir(dirent, name, size,
1767 file->f_pos, i_ino,
1768 squashfs_filetype_table[1]) < 0) {
1769 TRACE("Filldir returned less than 0\n");
1770 goto finish;
1771 }
1772 file->f_pos += size;
1773 }
1774
1775 length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
1776 SQUASHFS_I(i)->u.s2.directory_index_start,
1777 SQUASHFS_I(i)->u.s2.directory_index_offset,
1778 SQUASHFS_I(i)->u.s2.directory_index_count,
1779 file->f_pos);
1780
1781 while (length < i_size_read(i)) {
1782 /* read directory header */
1783 if (msblk->swap) {
1784 struct squashfs_dir_header sdirh;
1785
1786 if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
1787 next_block, next_offset, sizeof(sdirh),
1788 &next_block, &next_offset))
1789 goto failed_read;
1790
1791 length += sizeof(sdirh);
1792 SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
1793 } else {
1794 if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
1795 next_block, next_offset, sizeof(dirh),
1796 &next_block, &next_offset))
1797 goto failed_read;
1798
1799 length += sizeof(dirh);
1800 }
1801
1802 dir_count = dirh.count + 1;
1803 while (dir_count--) {
1804 if (msblk->swap) {
1805 struct squashfs_dir_entry sdire;
1806 if (!squashfs_get_cached_block(i->i_sb, (char *)
1807 &sdire, next_block, next_offset,
1808 sizeof(sdire), &next_block,
1809 &next_offset))
1810 goto failed_read;
1811
1812 length += sizeof(sdire);
1813 SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
1814 } else {
1815 if (!squashfs_get_cached_block(i->i_sb, (char *)
1816 dire, next_block, next_offset,
1817 sizeof(*dire), &next_block,
1818 &next_offset))
1819 goto failed_read;
1820
1821 length += sizeof(*dire);
1822 }
1823
1824 if (!squashfs_get_cached_block(i->i_sb, dire->name,
1825 next_block, next_offset,
1826 dire->size + 1, &next_block,
1827 &next_offset))
1828 goto failed_read;
1829
1830 length += dire->size + 1;
1831
1832 if (file->f_pos >= length)
1833 continue;
1834
1835 dire->name[dire->size + 1] = '\0';
1836
1837 TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
1838 (unsigned int) dirent, dire->name,
1839 dire->size + 1, (int) file->f_pos,
1840 dirh.start_block, dire->offset,
1841 dirh.inode_number + dire->inode_number,
1842 squashfs_filetype_table[dire->type]);
1843
1844 if (filldir(dirent, dire->name, dire->size + 1,
1845 file->f_pos,
1846 dirh.inode_number + dire->inode_number,
1847 squashfs_filetype_table[dire->type])
1848 < 0) {
1849 TRACE("Filldir returned less than 0\n");
1850 goto finish;
1851 }
1852 file->f_pos = length;
1853 }
1854 }
1855
1856 finish:
1857 return 0;
1858
1859 failed_read:
1860 ERROR("Unable to read directory block [%llx:%x]\n", next_block,
1861 next_offset);
1862 return 0;
1863 }
1864
1865
squashfs_lookup(struct inode * i,struct dentry * dentry)1866 static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry)
1867 {
1868 const unsigned char *name = dentry->d_name.name;
1869 int len = dentry->d_name.len;
1870 struct inode *inode = NULL;
1871 struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
1872 struct squashfs_super_block *sblk = &msblk->sblk;
1873 long long next_block = SQUASHFS_I(i)->start_block +
1874 sblk->directory_table_start;
1875 int next_offset = SQUASHFS_I(i)->offset, length = 0,
1876 dir_count;
1877 struct squashfs_dir_header dirh;
1878 char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
1879 struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
1880
1881 TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
1882
1883 if (len > SQUASHFS_NAME_LEN)
1884 goto exit_loop;
1885
1886 length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
1887 SQUASHFS_I(i)->u.s2.directory_index_start,
1888 SQUASHFS_I(i)->u.s2.directory_index_offset,
1889 SQUASHFS_I(i)->u.s2.directory_index_count, name,
1890 len);
1891
1892 while (length < i_size_read(i)) {
1893 /* read directory header */
1894 if (msblk->swap) {
1895 struct squashfs_dir_header sdirh;
1896 if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
1897 next_block, next_offset, sizeof(sdirh),
1898 &next_block, &next_offset))
1899 goto failed_read;
1900
1901 length += sizeof(sdirh);
1902 SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
1903 } else {
1904 if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
1905 next_block, next_offset, sizeof(dirh),
1906 &next_block, &next_offset))
1907 goto failed_read;
1908
1909 length += sizeof(dirh);
1910 }
1911
1912 dir_count = dirh.count + 1;
1913 while (dir_count--) {
1914 if (msblk->swap) {
1915 struct squashfs_dir_entry sdire;
1916 if (!squashfs_get_cached_block(i->i_sb, (char *)
1917 &sdire, next_block,next_offset,
1918 sizeof(sdire), &next_block,
1919 &next_offset))
1920 goto failed_read;
1921
1922 length += sizeof(sdire);
1923 SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
1924 } else {
1925 if (!squashfs_get_cached_block(i->i_sb, (char *)
1926 dire, next_block,next_offset,
1927 sizeof(*dire), &next_block,
1928 &next_offset))
1929 goto failed_read;
1930
1931 length += sizeof(*dire);
1932 }
1933
1934 if (!squashfs_get_cached_block(i->i_sb, dire->name,
1935 next_block, next_offset, dire->size + 1,
1936 &next_block, &next_offset))
1937 goto failed_read;
1938
1939 length += dire->size + 1;
1940
1941 if (name[0] < dire->name[0])
1942 goto exit_loop;
1943
1944 if ((len == dire->size + 1) && !strncmp(name,
1945 dire->name, len)) {
1946 squashfs_inode_t ino =
1947 SQUASHFS_MKINODE(dirh.start_block,
1948 dire->offset);
1949
1950 TRACE("calling squashfs_iget for directory "
1951 "entry %s, inode %x:%x, %d\n", name,
1952 dirh.start_block, dire->offset,
1953 dirh.inode_number + dire->inode_number);
1954
1955 inode = (msblk->iget)(i->i_sb, ino);
1956
1957 goto exit_loop;
1958 }
1959 }
1960 }
1961
1962 exit_loop:
1963 d_add(dentry, inode);
1964 return ERR_PTR(0);
1965
1966 failed_read:
1967 ERROR("Unable to read directory block [%llx:%x]\n", next_block,
1968 next_offset);
1969 goto exit_loop;
1970 }
1971
1972
squashfs_put_super(struct super_block * s)1973 static void squashfs_put_super(struct super_block *s)
1974 {
1975 int i;
1976
1977 struct squashfs_sb_info *sbi = &s->u.squashfs_sb;
1978 if (sbi->block_cache)
1979 for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
1980 if (sbi->block_cache[i].block !=
1981 SQUASHFS_INVALID_BLK)
1982 kfree(sbi->block_cache[i].data);
1983 if (sbi->fragment)
1984 for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
1985 SQUASHFS_FREE(sbi->fragment[i].data);
1986 kfree(sbi->fragment);
1987 kfree(sbi->block_cache);
1988 kfree(sbi->read_data);
1989 kfree(sbi->read_page);
1990 kfree(sbi->uid);
1991 kfree(sbi->fragment_index);
1992 kfree(sbi->fragment_index_2);
1993 kfree(sbi->meta_index);
1994 vfree(sbi->stream.workspace);
1995 sbi->block_cache = NULL;
1996 sbi->uid = NULL;
1997 sbi->read_data = NULL;
1998 sbi->read_page = NULL;
1999 sbi->fragment = NULL;
2000 sbi->fragment_index = NULL;
2001 sbi->fragment_index_2 = NULL;
2002 sbi->meta_index = NULL;
2003 sbi->stream.workspace = NULL;
2004 }
2005
2006
init_squashfs_fs(void)2007 static int __init init_squashfs_fs(void)
2008 {
2009
2010 printk(KERN_INFO "squashfs: version 3.1 (2006/08/15) "
2011 "Phillip Lougher\n");
2012
2013 return register_filesystem(&squashfs_fs_type);
2014 }
2015
2016
exit_squashfs_fs(void)2017 static void __exit exit_squashfs_fs(void)
2018 {
2019 unregister_filesystem(&squashfs_fs_type);
2020 }
2021
2022
2023 EXPORT_NO_SYMBOLS;
2024
2025 module_init(init_squashfs_fs);
2026 module_exit(exit_squashfs_fs);
2027 MODULE_DESCRIPTION("squashfs 3.1, a compressed read-only filesystem");
2028 MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
2029 MODULE_LICENSE("GPL");
2030