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 43static struct super_block *squashfs_read_super(struct super_block *, void *, int); 44static void squashfs_put_super(struct super_block *); 45static int squashfs_statfs(struct super_block *, struct statfs *); 46static int squashfs_symlink_readpage(struct file *file, struct page *page); 47static int squashfs_readpage(struct file *file, struct page *page); 48static int squashfs_readpage4K(struct file *file, struct page *page); 49static int squashfs_readdir(struct file *, void *, filldir_t); 50static struct dentry *squashfs_lookup(struct inode *, struct dentry *); 51static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode); 52static 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 56static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super); 57 58static unsigned char squashfs_filetype_table[] = { 59 DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK 60}; 61 62static struct super_operations squashfs_ops = { 63 .statfs = squashfs_statfs, 64 .put_super = squashfs_put_super, 65}; 66 67SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { 68 .readpage = squashfs_symlink_readpage 69}; 70 71SQSH_EXTERN struct address_space_operations squashfs_aops = { 72 .readpage = squashfs_readpage 73}; 74 75SQSH_EXTERN struct address_space_operations squashfs_aops_4K = { 76 .readpage = squashfs_readpage4K 77}; 78 79static struct file_operations squashfs_dir_ops = { 80 .read = generic_read_dir, 81 .readdir = squashfs_readdir 82}; 83 84static struct inode_operations squashfs_dir_inode_ops = { 85 .lookup = squashfs_lookup 86}; 87 88static 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 150out: 151 return NULL; 152} 153 154 155SQSH_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 254block_release: 255 while (--b >= 0) 256 brelse(bh[b]); 257 258read_failure: 259 ERROR("sb_bread failed reading block 0x%x\n", cur_index); 260 return 0; 261} 262 263 264SQSH_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 367finish: 368 return return_length; 369out: 370 return 0; 371} 372 373 374static 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 405out: 406 return 0; 407} 408 409 410SQSH_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 420SQSH_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 495out: 496 return NULL; 497} 498 499 500static 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 524static 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 847failed_read: 848 ERROR("Unable to read inode [%llx:%x]\n", block, offset); 849 850failed_read1: 851 return NULL; 852} 853 854 855int 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 893static 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 929static 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 1096allocate_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 1109failed_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 1122static 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 1141static 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 1177skip_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 1187struct 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 1214not_allocated: 1215 up(&msblk->meta_index_mutex); 1216 1217 return meta; 1218} 1219 1220 1221struct 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 1268failed: 1269 up(&msblk->meta_index_mutex); 1270 return meta; 1271} 1272 1273 1274void release_meta_index(struct inode *inode, struct meta_index *meta) 1275{ 1276 meta->locked = 0; 1277} 1278 1279 1280static 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 1312failure: 1313 return -1; 1314} 1315 1316 1317#define SIZE 256 1318 1319static 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 1325static 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 1396all_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 1403failed: 1404 release_meta_index(inode, meta); 1405 return -1; 1406} 1407 1408 1409static 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 1445failure: 1446 return 0; 1447} 1448 1449 1450static 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 1555skip_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 1567static 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 1622skip_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 1633static 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 1678finish: 1679 return length + 3; 1680} 1681 1682 1683static 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 1733static 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 1856finish: 1857 return 0; 1858 1859failed_read: 1860 ERROR("Unable to read directory block [%llx:%x]\n", next_block, 1861 next_offset); 1862 return 0; 1863} 1864 1865 1866static 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 1962exit_loop: 1963 d_add(dentry, inode); 1964 return ERR_PTR(0); 1965 1966failed_read: 1967 ERROR("Unable to read directory block [%llx:%x]\n", next_block, 1968 next_offset); 1969 goto exit_loop; 1970} 1971 1972 1973static 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 2007static 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 2017static void __exit exit_squashfs_fs(void) 2018{ 2019 unregister_filesystem(&squashfs_fs_type); 2020} 2021 2022 2023EXPORT_NO_SYMBOLS; 2024 2025module_init(init_squashfs_fs); 2026module_exit(exit_squashfs_fs); 2027MODULE_DESCRIPTION("squashfs 3.1, a compressed read-only filesystem"); 2028MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); 2029MODULE_LICENSE("GPL"); 2030